diff options
author | Dave Jones <davej@redhat.com> | 2005-08-18 01:56:07 -0400 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2005-08-18 01:56:07 -0400 |
commit | a8b3e6f10f08f66ae1072efd087b30966a3654f6 (patch) | |
tree | 1d1409855f8ad5beabafe061c6453edd84ba94c8 /sound | |
parent | 46acac3b4fd8ef66eec63b51de8d556a17c7d4f7 (diff) | |
parent | 099d44e869f1886b5eb02a5145ca97b5e4142e28 (diff) |
Merge /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'sound')
196 files changed, 18193 insertions, 3660 deletions
diff --git a/sound/Kconfig b/sound/Kconfig index 047d59ea0573..ee794ae06040 100644 --- a/sound/Kconfig +++ b/sound/Kconfig | |||
@@ -42,6 +42,11 @@ menu "Advanced Linux Sound Architecture" | |||
42 | config SND | 42 | config SND |
43 | tristate "Advanced Linux Sound Architecture" | 43 | tristate "Advanced Linux Sound Architecture" |
44 | depends on SOUND | 44 | depends on SOUND |
45 | help | ||
46 | Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture), | ||
47 | the new base sound system. | ||
48 | |||
49 | For more information, see <http://www.alsa-project.org/> | ||
45 | 50 | ||
46 | source "sound/core/Kconfig" | 51 | source "sound/core/Kconfig" |
47 | 52 | ||
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig index cdacf4d3a387..2e4a5e0d16db 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig | |||
@@ -14,5 +14,23 @@ config SND_SA11XX_UDA1341 | |||
14 | To compile this driver as a module, choose M here: the module | 14 | To compile this driver as a module, choose M here: the module |
15 | will be called snd-sa11xx-uda1341. | 15 | will be called snd-sa11xx-uda1341. |
16 | 16 | ||
17 | endmenu | 17 | config SND_ARMAACI |
18 | tristate "ARM PrimeCell PL041 AC Link support" | ||
19 | depends on SND && ARM_AMBA | ||
20 | select SND_PCM | ||
21 | select SND_AC97_CODEC | ||
22 | |||
23 | config SND_PXA2XX_PCM | ||
24 | tristate | ||
25 | select SND_PCM | ||
18 | 26 | ||
27 | config SND_PXA2XX_AC97 | ||
28 | tristate "AC97 driver for the Intel PXA2xx chip" | ||
29 | depends on ARCH_PXA && SND | ||
30 | select SND_PXA2XX_PCM | ||
31 | select SND_AC97_CODEC | ||
32 | help | ||
33 | Say Y or M if you want to support any AC97 codec attached to | ||
34 | the PXA2xx AC97 interface. | ||
35 | |||
36 | endmenu | ||
diff --git a/sound/arm/Makefile b/sound/arm/Makefile index d7e7dc0c3cdf..103f136926d9 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile | |||
@@ -3,6 +3,11 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | snd-sa11xx-uda1341-objs := sa11xx-uda1341.o | 5 | snd-sa11xx-uda1341-objs := sa11xx-uda1341.o |
6 | snd-aaci-objs := aaci.o devdma.o | ||
7 | snd-pxa2xx-pcm-objs := pxa2xx-pcm.o | ||
8 | snd-pxa2xx-ac97-objs := pxa2xx-ac97.o | ||
6 | 9 | ||
7 | # Toplevel Module Dependency | ||
8 | obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o | 10 | obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o |
11 | obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o | ||
12 | obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o | ||
13 | obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o | ||
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c new file mode 100644 index 000000000000..08cc3ddca96f --- /dev/null +++ b/sound/arm/aaci.c | |||
@@ -0,0 +1,968 @@ | |||
1 | /* | ||
2 | * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver | ||
3 | * | ||
4 | * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * Documentation: ARM DDI 0173B | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/ioport.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/err.h> | ||
20 | |||
21 | #include <asm/io.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/hardware/amba.h> | ||
24 | |||
25 | #include <sound/driver.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/initval.h> | ||
28 | #include <sound/ac97_codec.h> | ||
29 | #include <sound/pcm.h> | ||
30 | #include <sound/pcm_params.h> | ||
31 | |||
32 | #include "aaci.h" | ||
33 | #include "devdma.h" | ||
34 | |||
35 | #define DRIVER_NAME "aaci-pl041" | ||
36 | |||
37 | /* | ||
38 | * PM support is not complete. Turn it off. | ||
39 | */ | ||
40 | #undef CONFIG_PM | ||
41 | |||
42 | static void aaci_ac97_select_codec(struct aaci *aaci, ac97_t *ac97) | ||
43 | { | ||
44 | u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num); | ||
45 | |||
46 | /* | ||
47 | * Ensure that the slot 1/2 RX registers are empty. | ||
48 | */ | ||
49 | v = readl(aaci->base + AACI_SLFR); | ||
50 | if (v & SLFR_2RXV) | ||
51 | readl(aaci->base + AACI_SL2RX); | ||
52 | if (v & SLFR_1RXV) | ||
53 | readl(aaci->base + AACI_SL1RX); | ||
54 | |||
55 | writel(maincr, aaci->base + AACI_MAINCR); | ||
56 | } | ||
57 | |||
58 | /* | ||
59 | * P29: | ||
60 | * The recommended use of programming the external codec through slot 1 | ||
61 | * and slot 2 data is to use the channels during setup routines and the | ||
62 | * slot register at any other time. The data written into slot 1, slot 2 | ||
63 | * and slot 12 registers is transmitted only when their corresponding | ||
64 | * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR | ||
65 | * register. | ||
66 | */ | ||
67 | static void aaci_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) | ||
68 | { | ||
69 | struct aaci *aaci = ac97->private_data; | ||
70 | u32 v; | ||
71 | |||
72 | if (ac97->num >= 4) | ||
73 | return; | ||
74 | |||
75 | down(&aaci->ac97_sem); | ||
76 | |||
77 | aaci_ac97_select_codec(aaci, ac97); | ||
78 | |||
79 | /* | ||
80 | * P54: You must ensure that AACI_SL2TX is always written | ||
81 | * to, if required, before data is written to AACI_SL1TX. | ||
82 | */ | ||
83 | writel(val << 4, aaci->base + AACI_SL2TX); | ||
84 | writel(reg << 12, aaci->base + AACI_SL1TX); | ||
85 | |||
86 | /* | ||
87 | * Wait for the transmission of both slots to complete. | ||
88 | */ | ||
89 | do { | ||
90 | v = readl(aaci->base + AACI_SLFR); | ||
91 | } while (v & (SLFR_1TXB|SLFR_2TXB)); | ||
92 | |||
93 | up(&aaci->ac97_sem); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Read an AC'97 register. | ||
98 | */ | ||
99 | static unsigned short aaci_ac97_read(ac97_t *ac97, unsigned short reg) | ||
100 | { | ||
101 | struct aaci *aaci = ac97->private_data; | ||
102 | u32 v; | ||
103 | |||
104 | if (ac97->num >= 4) | ||
105 | return ~0; | ||
106 | |||
107 | down(&aaci->ac97_sem); | ||
108 | |||
109 | aaci_ac97_select_codec(aaci, ac97); | ||
110 | |||
111 | /* | ||
112 | * Write the register address to slot 1. | ||
113 | */ | ||
114 | writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX); | ||
115 | |||
116 | /* | ||
117 | * Wait for the transmission to complete. | ||
118 | */ | ||
119 | do { | ||
120 | v = readl(aaci->base + AACI_SLFR); | ||
121 | } while (v & SLFR_1TXB); | ||
122 | |||
123 | /* | ||
124 | * Give the AC'97 codec more than enough time | ||
125 | * to respond. (42us = ~2 frames at 48kHz.) | ||
126 | */ | ||
127 | udelay(42); | ||
128 | |||
129 | /* | ||
130 | * Wait for slot 2 to indicate data. | ||
131 | */ | ||
132 | do { | ||
133 | cond_resched(); | ||
134 | v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV); | ||
135 | } while (v != (SLFR_1RXV|SLFR_2RXV)); | ||
136 | |||
137 | v = readl(aaci->base + AACI_SL1RX) >> 12; | ||
138 | if (v == reg) { | ||
139 | v = readl(aaci->base + AACI_SL2RX) >> 4; | ||
140 | } else { | ||
141 | dev_err(&aaci->dev->dev, | ||
142 | "wrong ac97 register read back (%x != %x)\n", | ||
143 | v, reg); | ||
144 | v = ~0; | ||
145 | } | ||
146 | |||
147 | up(&aaci->ac97_sem); | ||
148 | return v; | ||
149 | } | ||
150 | |||
151 | static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun) | ||
152 | { | ||
153 | u32 val; | ||
154 | int timeout = 5000; | ||
155 | |||
156 | do { | ||
157 | val = readl(aacirun->base + AACI_SR); | ||
158 | } while (val & (SR_TXB|SR_RXB) && timeout--); | ||
159 | } | ||
160 | |||
161 | |||
162 | |||
163 | /* | ||
164 | * Interrupt support. | ||
165 | */ | ||
166 | static void aaci_fifo_irq(struct aaci *aaci, u32 mask) | ||
167 | { | ||
168 | if (mask & ISR_URINTR) { | ||
169 | writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR); | ||
170 | } | ||
171 | |||
172 | if (mask & ISR_TXINTR) { | ||
173 | struct aaci_runtime *aacirun = &aaci->playback; | ||
174 | void *ptr; | ||
175 | |||
176 | if (!aacirun->substream || !aacirun->start) { | ||
177 | dev_warn(&aaci->dev->dev, "TX interrupt???"); | ||
178 | writel(0, aacirun->base + AACI_IE); | ||
179 | return; | ||
180 | } | ||
181 | |||
182 | ptr = aacirun->ptr; | ||
183 | do { | ||
184 | unsigned int len = aacirun->fifosz; | ||
185 | u32 val; | ||
186 | |||
187 | if (aacirun->bytes <= 0) { | ||
188 | aacirun->bytes += aacirun->period; | ||
189 | aacirun->ptr = ptr; | ||
190 | spin_unlock(&aaci->lock); | ||
191 | snd_pcm_period_elapsed(aacirun->substream); | ||
192 | spin_lock(&aaci->lock); | ||
193 | } | ||
194 | if (!(aacirun->cr & TXCR_TXEN)) | ||
195 | break; | ||
196 | |||
197 | val = readl(aacirun->base + AACI_SR); | ||
198 | if (!(val & SR_TXHE)) | ||
199 | break; | ||
200 | if (!(val & SR_TXFE)) | ||
201 | len >>= 1; | ||
202 | |||
203 | aacirun->bytes -= len; | ||
204 | |||
205 | /* writing 16 bytes at a time */ | ||
206 | for ( ; len > 0; len -= 16) { | ||
207 | asm( | ||
208 | "ldmia %0!, {r0, r1, r2, r3}\n\t" | ||
209 | "stmia %1, {r0, r1, r2, r3}" | ||
210 | : "+r" (ptr) | ||
211 | : "r" (aacirun->fifo) | ||
212 | : "r0", "r1", "r2", "r3", "cc"); | ||
213 | |||
214 | if (ptr >= aacirun->end) | ||
215 | ptr = aacirun->start; | ||
216 | } | ||
217 | } while (1); | ||
218 | |||
219 | aacirun->ptr = ptr; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | static irqreturn_t aaci_irq(int irq, void *devid, struct pt_regs *regs) | ||
224 | { | ||
225 | struct aaci *aaci = devid; | ||
226 | u32 mask; | ||
227 | int i; | ||
228 | |||
229 | spin_lock(&aaci->lock); | ||
230 | mask = readl(aaci->base + AACI_ALLINTS); | ||
231 | if (mask) { | ||
232 | u32 m = mask; | ||
233 | for (i = 0; i < 4; i++, m >>= 7) { | ||
234 | if (m & 0x7f) { | ||
235 | aaci_fifo_irq(aaci, m); | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | spin_unlock(&aaci->lock); | ||
240 | |||
241 | return mask ? IRQ_HANDLED : IRQ_NONE; | ||
242 | } | ||
243 | |||
244 | |||
245 | |||
246 | /* | ||
247 | * ALSA support. | ||
248 | */ | ||
249 | |||
250 | struct aaci_stream { | ||
251 | unsigned char codec_idx; | ||
252 | unsigned char rate_idx; | ||
253 | }; | ||
254 | |||
255 | static struct aaci_stream aaci_streams[] = { | ||
256 | [ACSTREAM_FRONT] = { | ||
257 | .codec_idx = 0, | ||
258 | .rate_idx = AC97_RATES_FRONT_DAC, | ||
259 | }, | ||
260 | [ACSTREAM_SURROUND] = { | ||
261 | .codec_idx = 0, | ||
262 | .rate_idx = AC97_RATES_SURR_DAC, | ||
263 | }, | ||
264 | [ACSTREAM_LFE] = { | ||
265 | .codec_idx = 0, | ||
266 | .rate_idx = AC97_RATES_LFE_DAC, | ||
267 | }, | ||
268 | }; | ||
269 | |||
270 | static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid) | ||
271 | { | ||
272 | struct aaci_stream *s = aaci_streams + streamid; | ||
273 | return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx]; | ||
274 | } | ||
275 | |||
276 | static unsigned int rate_list[] = { | ||
277 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, | ||
278 | 48000, 64000, 88200, 96000, 176400, 192000 | ||
279 | }; | ||
280 | |||
281 | /* | ||
282 | * Double-rate rule: we can support double rate iff channels == 2 | ||
283 | * (unimplemented) | ||
284 | */ | ||
285 | static int | ||
286 | aaci_rule_rate_by_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule) | ||
287 | { | ||
288 | struct aaci *aaci = rule->private; | ||
289 | unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512; | ||
290 | snd_interval_t *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
291 | |||
292 | switch (c->max) { | ||
293 | case 6: | ||
294 | rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE); | ||
295 | case 4: | ||
296 | rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND); | ||
297 | case 2: | ||
298 | rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT); | ||
299 | } | ||
300 | |||
301 | return snd_interval_list(hw_param_interval(p, rule->var), | ||
302 | ARRAY_SIZE(rate_list), rate_list, | ||
303 | rate_mask); | ||
304 | } | ||
305 | |||
306 | static snd_pcm_hardware_t aaci_hw_info = { | ||
307 | .info = SNDRV_PCM_INFO_MMAP | | ||
308 | SNDRV_PCM_INFO_MMAP_VALID | | ||
309 | SNDRV_PCM_INFO_INTERLEAVED | | ||
310 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
311 | SNDRV_PCM_INFO_RESUME, | ||
312 | |||
313 | /* | ||
314 | * ALSA doesn't support 18-bit or 20-bit packed into 32-bit | ||
315 | * words. It also doesn't support 12-bit at all. | ||
316 | */ | ||
317 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
318 | |||
319 | /* should this be continuous or knot? */ | ||
320 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
321 | .rate_max = 48000, | ||
322 | .rate_min = 4000, | ||
323 | .channels_min = 2, | ||
324 | .channels_max = 6, | ||
325 | .buffer_bytes_max = 64 * 1024, | ||
326 | .period_bytes_min = 256, | ||
327 | .period_bytes_max = PAGE_SIZE, | ||
328 | .periods_min = 4, | ||
329 | .periods_max = PAGE_SIZE / 16, | ||
330 | }; | ||
331 | |||
332 | static int aaci_pcm_open(struct aaci *aaci, snd_pcm_substream_t *substream, | ||
333 | struct aaci_runtime *aacirun) | ||
334 | { | ||
335 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
336 | int ret; | ||
337 | |||
338 | aacirun->substream = substream; | ||
339 | runtime->private_data = aacirun; | ||
340 | runtime->hw = aaci_hw_info; | ||
341 | |||
342 | /* | ||
343 | * FIXME: ALSA specifies fifo_size in bytes. If we're in normal | ||
344 | * mode, each 32-bit word contains one sample. If we're in | ||
345 | * compact mode, each 32-bit word contains two samples, effectively | ||
346 | * halving the FIFO size. However, we don't know for sure which | ||
347 | * we'll be using at this point. We set this to the lower limit. | ||
348 | */ | ||
349 | runtime->hw.fifo_size = aaci->fifosize * 2; | ||
350 | |||
351 | /* | ||
352 | * Add rule describing hardware rate dependency | ||
353 | * on the number of channels. | ||
354 | */ | ||
355 | ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
356 | aaci_rule_rate_by_channels, aaci, | ||
357 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
358 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
359 | if (ret) | ||
360 | goto out; | ||
361 | |||
362 | ret = request_irq(aaci->dev->irq[0], aaci_irq, SA_SHIRQ|SA_INTERRUPT, | ||
363 | DRIVER_NAME, aaci); | ||
364 | if (ret) | ||
365 | goto out; | ||
366 | |||
367 | return 0; | ||
368 | |||
369 | out: | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | |||
374 | /* | ||
375 | * Common ALSA stuff | ||
376 | */ | ||
377 | static int aaci_pcm_close(snd_pcm_substream_t *substream) | ||
378 | { | ||
379 | struct aaci *aaci = substream->private_data; | ||
380 | struct aaci_runtime *aacirun = substream->runtime->private_data; | ||
381 | |||
382 | WARN_ON(aacirun->cr & TXCR_TXEN); | ||
383 | |||
384 | aacirun->substream = NULL; | ||
385 | free_irq(aaci->dev->irq[0], aaci); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int aaci_pcm_hw_free(snd_pcm_substream_t *substream) | ||
391 | { | ||
392 | struct aaci_runtime *aacirun = substream->runtime->private_data; | ||
393 | |||
394 | /* | ||
395 | * This must not be called with the device enabled. | ||
396 | */ | ||
397 | WARN_ON(aacirun->cr & TXCR_TXEN); | ||
398 | |||
399 | if (aacirun->pcm_open) | ||
400 | snd_ac97_pcm_close(aacirun->pcm); | ||
401 | aacirun->pcm_open = 0; | ||
402 | |||
403 | /* | ||
404 | * Clear out the DMA and any allocated buffers. | ||
405 | */ | ||
406 | devdma_hw_free(NULL, substream); | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static int aaci_pcm_hw_params(snd_pcm_substream_t *substream, | ||
412 | struct aaci_runtime *aacirun, | ||
413 | snd_pcm_hw_params_t *params) | ||
414 | { | ||
415 | int err; | ||
416 | |||
417 | aaci_pcm_hw_free(substream); | ||
418 | |||
419 | err = devdma_hw_alloc(NULL, substream, | ||
420 | params_buffer_bytes(params)); | ||
421 | if (err < 0) | ||
422 | goto out; | ||
423 | |||
424 | err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params), | ||
425 | params_channels(params), | ||
426 | aacirun->pcm->r[0].slots); | ||
427 | if (err) | ||
428 | goto out; | ||
429 | |||
430 | aacirun->pcm_open = 1; | ||
431 | |||
432 | out: | ||
433 | return err; | ||
434 | } | ||
435 | |||
436 | static int aaci_pcm_prepare(snd_pcm_substream_t *substream) | ||
437 | { | ||
438 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
439 | struct aaci_runtime *aacirun = runtime->private_data; | ||
440 | |||
441 | aacirun->start = (void *)runtime->dma_area; | ||
442 | aacirun->end = aacirun->start + runtime->dma_bytes; | ||
443 | aacirun->ptr = aacirun->start; | ||
444 | aacirun->period = | ||
445 | aacirun->bytes = frames_to_bytes(runtime, runtime->period_size); | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static snd_pcm_uframes_t aaci_pcm_pointer(snd_pcm_substream_t *substream) | ||
451 | { | ||
452 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
453 | struct aaci_runtime *aacirun = runtime->private_data; | ||
454 | ssize_t bytes = aacirun->ptr - aacirun->start; | ||
455 | |||
456 | return bytes_to_frames(runtime, bytes); | ||
457 | } | ||
458 | |||
459 | static int aaci_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma) | ||
460 | { | ||
461 | return devdma_mmap(NULL, substream, vma); | ||
462 | } | ||
463 | |||
464 | |||
465 | /* | ||
466 | * Playback specific ALSA stuff | ||
467 | */ | ||
468 | static const u32 channels_to_txmask[] = { | ||
469 | [2] = TXCR_TX3 | TXCR_TX4, | ||
470 | [4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8, | ||
471 | [6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9, | ||
472 | }; | ||
473 | |||
474 | /* | ||
475 | * We can support two and four channel audio. Unfortunately | ||
476 | * six channel audio requires a non-standard channel ordering: | ||
477 | * 2 -> FL(3), FR(4) | ||
478 | * 4 -> FL(3), FR(4), SL(7), SR(8) | ||
479 | * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required) | ||
480 | * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual) | ||
481 | * This requires an ALSA configuration file to correct. | ||
482 | */ | ||
483 | static unsigned int channel_list[] = { 2, 4, 6 }; | ||
484 | |||
485 | static int | ||
486 | aaci_rule_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule) | ||
487 | { | ||
488 | struct aaci *aaci = rule->private; | ||
489 | unsigned int chan_mask = 1 << 0, slots; | ||
490 | |||
491 | /* | ||
492 | * pcms[0] is the our 5.1 PCM instance. | ||
493 | */ | ||
494 | slots = aaci->ac97_bus->pcms[0].r[0].slots; | ||
495 | if (slots & (1 << AC97_SLOT_PCM_SLEFT)) { | ||
496 | chan_mask |= 1 << 1; | ||
497 | if (slots & (1 << AC97_SLOT_LFE)) | ||
498 | chan_mask |= 1 << 2; | ||
499 | } | ||
500 | |||
501 | return snd_interval_list(hw_param_interval(p, rule->var), | ||
502 | ARRAY_SIZE(channel_list), channel_list, | ||
503 | chan_mask); | ||
504 | } | ||
505 | |||
506 | static int aaci_pcm_playback_open(snd_pcm_substream_t *substream) | ||
507 | { | ||
508 | struct aaci *aaci = substream->private_data; | ||
509 | int ret; | ||
510 | |||
511 | /* | ||
512 | * Add rule describing channel dependency. | ||
513 | */ | ||
514 | ret = snd_pcm_hw_rule_add(substream->runtime, 0, | ||
515 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
516 | aaci_rule_channels, aaci, | ||
517 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
518 | if (ret) | ||
519 | return ret; | ||
520 | |||
521 | return aaci_pcm_open(aaci, substream, &aaci->playback); | ||
522 | } | ||
523 | |||
524 | static int aaci_pcm_playback_hw_params(snd_pcm_substream_t *substream, | ||
525 | snd_pcm_hw_params_t *params) | ||
526 | { | ||
527 | struct aaci *aaci = substream->private_data; | ||
528 | struct aaci_runtime *aacirun = substream->runtime->private_data; | ||
529 | unsigned int channels = params_channels(params); | ||
530 | int ret; | ||
531 | |||
532 | WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) || | ||
533 | !channels_to_txmask[channels]); | ||
534 | |||
535 | ret = aaci_pcm_hw_params(substream, aacirun, params); | ||
536 | |||
537 | /* | ||
538 | * Enable FIFO, compact mode, 16 bits per sample. | ||
539 | * FIXME: double rate slots? | ||
540 | */ | ||
541 | if (ret >= 0) { | ||
542 | aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16; | ||
543 | aacirun->cr |= channels_to_txmask[channels]; | ||
544 | |||
545 | aacirun->fifosz = aaci->fifosize * 4; | ||
546 | if (aacirun->cr & TXCR_COMPACT) | ||
547 | aacirun->fifosz >>= 1; | ||
548 | } | ||
549 | return ret; | ||
550 | } | ||
551 | |||
552 | static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) | ||
553 | { | ||
554 | u32 ie; | ||
555 | |||
556 | ie = readl(aacirun->base + AACI_IE); | ||
557 | ie &= ~(IE_URIE|IE_TXIE); | ||
558 | writel(ie, aacirun->base + AACI_IE); | ||
559 | aacirun->cr &= ~TXCR_TXEN; | ||
560 | aaci_chan_wait_ready(aacirun); | ||
561 | writel(aacirun->cr, aacirun->base + AACI_TXCR); | ||
562 | } | ||
563 | |||
564 | static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) | ||
565 | { | ||
566 | u32 ie; | ||
567 | |||
568 | aaci_chan_wait_ready(aacirun); | ||
569 | aacirun->cr |= TXCR_TXEN; | ||
570 | |||
571 | ie = readl(aacirun->base + AACI_IE); | ||
572 | ie |= IE_URIE | IE_TXIE; | ||
573 | writel(ie, aacirun->base + AACI_IE); | ||
574 | writel(aacirun->cr, aacirun->base + AACI_TXCR); | ||
575 | } | ||
576 | |||
577 | static int aaci_pcm_playback_trigger(snd_pcm_substream_t *substream, int cmd) | ||
578 | { | ||
579 | struct aaci *aaci = substream->private_data; | ||
580 | struct aaci_runtime *aacirun = substream->runtime->private_data; | ||
581 | unsigned long flags; | ||
582 | int ret = 0; | ||
583 | |||
584 | spin_lock_irqsave(&aaci->lock, flags); | ||
585 | switch (cmd) { | ||
586 | case SNDRV_PCM_TRIGGER_START: | ||
587 | aaci_pcm_playback_start(aacirun); | ||
588 | break; | ||
589 | |||
590 | case SNDRV_PCM_TRIGGER_RESUME: | ||
591 | aaci_pcm_playback_start(aacirun); | ||
592 | break; | ||
593 | |||
594 | case SNDRV_PCM_TRIGGER_STOP: | ||
595 | aaci_pcm_playback_stop(aacirun); | ||
596 | break; | ||
597 | |||
598 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
599 | aaci_pcm_playback_stop(aacirun); | ||
600 | break; | ||
601 | |||
602 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
603 | break; | ||
604 | |||
605 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
606 | break; | ||
607 | |||
608 | default: | ||
609 | ret = -EINVAL; | ||
610 | } | ||
611 | spin_unlock_irqrestore(&aaci->lock, flags); | ||
612 | |||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | static snd_pcm_ops_t aaci_playback_ops = { | ||
617 | .open = aaci_pcm_playback_open, | ||
618 | .close = aaci_pcm_close, | ||
619 | .ioctl = snd_pcm_lib_ioctl, | ||
620 | .hw_params = aaci_pcm_playback_hw_params, | ||
621 | .hw_free = aaci_pcm_hw_free, | ||
622 | .prepare = aaci_pcm_prepare, | ||
623 | .trigger = aaci_pcm_playback_trigger, | ||
624 | .pointer = aaci_pcm_pointer, | ||
625 | .mmap = aaci_pcm_mmap, | ||
626 | }; | ||
627 | |||
628 | |||
629 | |||
630 | /* | ||
631 | * Power Management. | ||
632 | */ | ||
633 | #ifdef CONFIG_PM | ||
634 | static int aaci_do_suspend(snd_card_t *card, unsigned int state) | ||
635 | { | ||
636 | struct aaci *aaci = card->private_data; | ||
637 | if (aaci->card->power_state != SNDRV_CTL_POWER_D3cold) { | ||
638 | snd_pcm_suspend_all(aaci->pcm); | ||
639 | snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D3cold); | ||
640 | } | ||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static int aaci_do_resume(snd_card_t *card, unsigned int state) | ||
645 | { | ||
646 | struct aaci *aaci = card->private_data; | ||
647 | if (aaci->card->power_state != SNDRV_CTL_POWER_D0) { | ||
648 | snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D0); | ||
649 | } | ||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | static int aaci_suspend(struct amba_device *dev, u32 state) | ||
654 | { | ||
655 | snd_card_t *card = amba_get_drvdata(dev); | ||
656 | return card ? aaci_do_suspend(card) : 0; | ||
657 | } | ||
658 | |||
659 | static int aaci_resume(struct amba_device *dev) | ||
660 | { | ||
661 | snd_card_t *card = amba_get_drvdata(dev); | ||
662 | return card ? aaci_do_resume(card) : 0; | ||
663 | } | ||
664 | #else | ||
665 | #define aaci_do_suspend NULL | ||
666 | #define aaci_do_resume NULL | ||
667 | #define aaci_suspend NULL | ||
668 | #define aaci_resume NULL | ||
669 | #endif | ||
670 | |||
671 | |||
672 | static struct ac97_pcm ac97_defs[] __devinitdata = { | ||
673 | [0] = { /* Front PCM */ | ||
674 | .exclusive = 1, | ||
675 | .r = { | ||
676 | [0] = { | ||
677 | .slots = (1 << AC97_SLOT_PCM_LEFT) | | ||
678 | (1 << AC97_SLOT_PCM_RIGHT) | | ||
679 | (1 << AC97_SLOT_PCM_CENTER) | | ||
680 | (1 << AC97_SLOT_PCM_SLEFT) | | ||
681 | (1 << AC97_SLOT_PCM_SRIGHT) | | ||
682 | (1 << AC97_SLOT_LFE), | ||
683 | }, | ||
684 | }, | ||
685 | }, | ||
686 | [1] = { /* PCM in */ | ||
687 | .stream = 1, | ||
688 | .exclusive = 1, | ||
689 | .r = { | ||
690 | [0] = { | ||
691 | .slots = (1 << AC97_SLOT_PCM_LEFT) | | ||
692 | (1 << AC97_SLOT_PCM_RIGHT), | ||
693 | }, | ||
694 | }, | ||
695 | }, | ||
696 | [2] = { /* Mic in */ | ||
697 | .stream = 1, | ||
698 | .exclusive = 1, | ||
699 | .r = { | ||
700 | [0] = { | ||
701 | .slots = (1 << AC97_SLOT_MIC), | ||
702 | }, | ||
703 | }, | ||
704 | } | ||
705 | }; | ||
706 | |||
707 | static ac97_bus_ops_t aaci_bus_ops = { | ||
708 | .write = aaci_ac97_write, | ||
709 | .read = aaci_ac97_read, | ||
710 | }; | ||
711 | |||
712 | static int __devinit aaci_probe_ac97(struct aaci *aaci) | ||
713 | { | ||
714 | ac97_template_t ac97_template; | ||
715 | ac97_bus_t *ac97_bus; | ||
716 | ac97_t *ac97; | ||
717 | int ret; | ||
718 | |||
719 | /* | ||
720 | * Assert AACIRESET for 2us | ||
721 | */ | ||
722 | writel(0, aaci->base + AACI_RESET); | ||
723 | udelay(2); | ||
724 | writel(RESET_NRST, aaci->base + AACI_RESET); | ||
725 | |||
726 | /* | ||
727 | * Give the AC'97 codec more than enough time | ||
728 | * to wake up. (42us = ~2 frames at 48kHz.) | ||
729 | */ | ||
730 | udelay(42); | ||
731 | |||
732 | ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus); | ||
733 | if (ret) | ||
734 | goto out; | ||
735 | |||
736 | ac97_bus->clock = 48000; | ||
737 | aaci->ac97_bus = ac97_bus; | ||
738 | |||
739 | memset(&ac97_template, 0, sizeof(ac97_template_t)); | ||
740 | ac97_template.private_data = aaci; | ||
741 | ac97_template.num = 0; | ||
742 | ac97_template.scaps = AC97_SCAP_SKIP_MODEM; | ||
743 | |||
744 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97); | ||
745 | if (ret) | ||
746 | goto out; | ||
747 | |||
748 | /* | ||
749 | * Disable AC97 PC Beep input on audio codecs. | ||
750 | */ | ||
751 | if (ac97_is_audio(ac97)) | ||
752 | snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e); | ||
753 | |||
754 | ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs); | ||
755 | if (ret) | ||
756 | goto out; | ||
757 | |||
758 | aaci->playback.pcm = &ac97_bus->pcms[0]; | ||
759 | |||
760 | out: | ||
761 | return ret; | ||
762 | } | ||
763 | |||
764 | static void aaci_free_card(snd_card_t *card) | ||
765 | { | ||
766 | struct aaci *aaci = card->private_data; | ||
767 | if (aaci->base) | ||
768 | iounmap(aaci->base); | ||
769 | } | ||
770 | |||
771 | static struct aaci * __devinit aaci_init_card(struct amba_device *dev) | ||
772 | { | ||
773 | struct aaci *aaci; | ||
774 | snd_card_t *card; | ||
775 | |||
776 | card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | ||
777 | THIS_MODULE, sizeof(struct aaci)); | ||
778 | if (card == NULL) | ||
779 | return ERR_PTR(-ENOMEM); | ||
780 | |||
781 | card->private_free = aaci_free_card; | ||
782 | snd_card_set_pm_callback(card, aaci_do_suspend, aaci_do_resume, NULL); | ||
783 | |||
784 | strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); | ||
785 | strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); | ||
786 | snprintf(card->longname, sizeof(card->longname), | ||
787 | "%s at 0x%08lx, irq %d", | ||
788 | card->shortname, dev->res.start, dev->irq[0]); | ||
789 | |||
790 | aaci = card->private_data; | ||
791 | init_MUTEX(&aaci->ac97_sem); | ||
792 | spin_lock_init(&aaci->lock); | ||
793 | aaci->card = card; | ||
794 | aaci->dev = dev; | ||
795 | |||
796 | /* Set MAINCR to allow slot 1 and 2 data IO */ | ||
797 | aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN | | ||
798 | MAINCR_SL2RXEN | MAINCR_SL2TXEN; | ||
799 | |||
800 | return aaci; | ||
801 | } | ||
802 | |||
803 | static int __devinit aaci_init_pcm(struct aaci *aaci) | ||
804 | { | ||
805 | snd_pcm_t *pcm; | ||
806 | int ret; | ||
807 | |||
808 | ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm); | ||
809 | if (ret == 0) { | ||
810 | aaci->pcm = pcm; | ||
811 | pcm->private_data = aaci; | ||
812 | pcm->info_flags = 0; | ||
813 | |||
814 | strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name)); | ||
815 | |||
816 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); | ||
817 | } | ||
818 | |||
819 | return ret; | ||
820 | } | ||
821 | |||
822 | static unsigned int __devinit aaci_size_fifo(struct aaci *aaci) | ||
823 | { | ||
824 | void *base = aaci->base + AACI_CSCH1; | ||
825 | int i; | ||
826 | |||
827 | writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR); | ||
828 | |||
829 | for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++) | ||
830 | writel(0, aaci->base + AACI_DR1); | ||
831 | |||
832 | writel(0, base + AACI_TXCR); | ||
833 | |||
834 | /* | ||
835 | * Re-initialise the AACI after the FIFO depth test, to | ||
836 | * ensure that the FIFOs are empty. Unfortunately, merely | ||
837 | * disabling the channel doesn't clear the FIFO. | ||
838 | */ | ||
839 | writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR); | ||
840 | writel(aaci->maincr, aaci->base + AACI_MAINCR); | ||
841 | |||
842 | /* | ||
843 | * If we hit 4096, we failed. Go back to the specified | ||
844 | * fifo depth. | ||
845 | */ | ||
846 | if (i == 4096) | ||
847 | i = 8; | ||
848 | |||
849 | return i; | ||
850 | } | ||
851 | |||
852 | static int __devinit aaci_probe(struct amba_device *dev, void *id) | ||
853 | { | ||
854 | struct aaci *aaci; | ||
855 | int ret, i; | ||
856 | |||
857 | ret = amba_request_regions(dev, NULL); | ||
858 | if (ret) | ||
859 | return ret; | ||
860 | |||
861 | aaci = aaci_init_card(dev); | ||
862 | if (IS_ERR(aaci)) { | ||
863 | ret = PTR_ERR(aaci); | ||
864 | goto out; | ||
865 | } | ||
866 | |||
867 | aaci->base = ioremap(dev->res.start, SZ_4K); | ||
868 | if (!aaci->base) { | ||
869 | ret = -ENOMEM; | ||
870 | goto out; | ||
871 | } | ||
872 | |||
873 | /* | ||
874 | * Playback uses AACI channel 0 | ||
875 | */ | ||
876 | aaci->playback.base = aaci->base + AACI_CSCH1; | ||
877 | aaci->playback.fifo = aaci->base + AACI_DR1; | ||
878 | |||
879 | for (i = 0; i < 4; i++) { | ||
880 | void *base = aaci->base + i * 0x14; | ||
881 | |||
882 | writel(0, base + AACI_IE); | ||
883 | writel(0, base + AACI_TXCR); | ||
884 | writel(0, base + AACI_RXCR); | ||
885 | } | ||
886 | |||
887 | writel(0x1fff, aaci->base + AACI_INTCLR); | ||
888 | writel(aaci->maincr, aaci->base + AACI_MAINCR); | ||
889 | |||
890 | /* | ||
891 | * Size the FIFOs. | ||
892 | */ | ||
893 | aaci->fifosize = aaci_size_fifo(aaci); | ||
894 | |||
895 | ret = aaci_probe_ac97(aaci); | ||
896 | if (ret) | ||
897 | goto out; | ||
898 | |||
899 | ret = aaci_init_pcm(aaci); | ||
900 | if (ret) | ||
901 | goto out; | ||
902 | |||
903 | ret = snd_card_register(aaci->card); | ||
904 | if (ret == 0) { | ||
905 | dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname, | ||
906 | aaci->fifosize); | ||
907 | amba_set_drvdata(dev, aaci->card); | ||
908 | return ret; | ||
909 | } | ||
910 | |||
911 | out: | ||
912 | if (aaci) | ||
913 | snd_card_free(aaci->card); | ||
914 | amba_release_regions(dev); | ||
915 | return ret; | ||
916 | } | ||
917 | |||
918 | static int __devexit aaci_remove(struct amba_device *dev) | ||
919 | { | ||
920 | snd_card_t *card = amba_get_drvdata(dev); | ||
921 | |||
922 | amba_set_drvdata(dev, NULL); | ||
923 | |||
924 | if (card) { | ||
925 | struct aaci *aaci = card->private_data; | ||
926 | writel(0, aaci->base + AACI_MAINCR); | ||
927 | |||
928 | snd_card_free(card); | ||
929 | amba_release_regions(dev); | ||
930 | } | ||
931 | |||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | static struct amba_id aaci_ids[] = { | ||
936 | { | ||
937 | .id = 0x00041041, | ||
938 | .mask = 0x000fffff, | ||
939 | }, | ||
940 | { 0, 0 }, | ||
941 | }; | ||
942 | |||
943 | static struct amba_driver aaci_driver = { | ||
944 | .drv = { | ||
945 | .name = DRIVER_NAME, | ||
946 | }, | ||
947 | .probe = aaci_probe, | ||
948 | .remove = __devexit_p(aaci_remove), | ||
949 | .suspend = aaci_suspend, | ||
950 | .resume = aaci_resume, | ||
951 | .id_table = aaci_ids, | ||
952 | }; | ||
953 | |||
954 | static int __init aaci_init(void) | ||
955 | { | ||
956 | return amba_driver_register(&aaci_driver); | ||
957 | } | ||
958 | |||
959 | static void __exit aaci_exit(void) | ||
960 | { | ||
961 | amba_driver_unregister(&aaci_driver); | ||
962 | } | ||
963 | |||
964 | module_init(aaci_init); | ||
965 | module_exit(aaci_exit); | ||
966 | |||
967 | MODULE_LICENSE("GPL"); | ||
968 | MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver"); | ||
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h new file mode 100644 index 000000000000..d752e6426894 --- /dev/null +++ b/sound/arm/aaci.h | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver | ||
3 | * | ||
4 | * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #ifndef AACI_H | ||
11 | #define AACI_H | ||
12 | |||
13 | /* | ||
14 | * Control and status register offsets | ||
15 | * P39. | ||
16 | */ | ||
17 | #define AACI_CSCH1 0x000 | ||
18 | #define AACI_CSCH2 0x014 | ||
19 | #define AACI_CSCH3 0x028 | ||
20 | #define AACI_CSCH4 0x03c | ||
21 | |||
22 | #define AACI_RXCR 0x000 /* 29 bits Control Rx FIFO */ | ||
23 | #define AACI_TXCR 0x004 /* 17 bits Control Tx FIFO */ | ||
24 | #define AACI_SR 0x008 /* 12 bits Status */ | ||
25 | #define AACI_ISR 0x00c /* 7 bits Int Status */ | ||
26 | #define AACI_IE 0x010 /* 7 bits Int Enable */ | ||
27 | |||
28 | /* | ||
29 | * Other registers | ||
30 | */ | ||
31 | #define AACI_SL1RX 0x050 | ||
32 | #define AACI_SL1TX 0x054 | ||
33 | #define AACI_SL2RX 0x058 | ||
34 | #define AACI_SL2TX 0x05c | ||
35 | #define AACI_SL12RX 0x060 | ||
36 | #define AACI_SL12TX 0x064 | ||
37 | #define AACI_SLFR 0x068 /* slot flags */ | ||
38 | #define AACI_SLISTAT 0x06c /* slot interrupt status */ | ||
39 | #define AACI_SLIEN 0x070 /* slot interrupt enable */ | ||
40 | #define AACI_INTCLR 0x074 /* interrupt clear */ | ||
41 | #define AACI_MAINCR 0x078 /* main control */ | ||
42 | #define AACI_RESET 0x07c /* reset control */ | ||
43 | #define AACI_SYNC 0x080 /* sync control */ | ||
44 | #define AACI_ALLINTS 0x084 /* all fifo interrupt status */ | ||
45 | #define AACI_MAINFR 0x088 /* main flag register */ | ||
46 | #define AACI_DR1 0x090 /* data read/written fifo 1 */ | ||
47 | #define AACI_DR2 0x0b0 /* data read/written fifo 2 */ | ||
48 | #define AACI_DR3 0x0d0 /* data read/written fifo 3 */ | ||
49 | #define AACI_DR4 0x0f0 /* data read/written fifo 4 */ | ||
50 | |||
51 | /* | ||
52 | * transmit fifo control register. P48 | ||
53 | */ | ||
54 | #define TXCR_FEN (1 << 16) /* fifo enable */ | ||
55 | #define TXCR_COMPACT (1 << 15) /* compact mode */ | ||
56 | #define TXCR_TSZ16 (0 << 13) /* 16 bits */ | ||
57 | #define TXCR_TSZ18 (1 << 13) /* 18 bits */ | ||
58 | #define TXCR_TSZ20 (2 << 13) /* 20 bits */ | ||
59 | #define TXCR_TSZ12 (3 << 13) /* 12 bits */ | ||
60 | #define TXCR_TX12 (1 << 12) /* transmits slot 12 */ | ||
61 | #define TXCR_TX11 (1 << 11) /* transmits slot 12 */ | ||
62 | #define TXCR_TX10 (1 << 10) /* transmits slot 12 */ | ||
63 | #define TXCR_TX9 (1 << 9) /* transmits slot 12 */ | ||
64 | #define TXCR_TX8 (1 << 8) /* transmits slot 12 */ | ||
65 | #define TXCR_TX7 (1 << 7) /* transmits slot 12 */ | ||
66 | #define TXCR_TX6 (1 << 6) /* transmits slot 12 */ | ||
67 | #define TXCR_TX5 (1 << 5) /* transmits slot 12 */ | ||
68 | #define TXCR_TX4 (1 << 4) /* transmits slot 12 */ | ||
69 | #define TXCR_TX3 (1 << 3) /* transmits slot 12 */ | ||
70 | #define TXCR_TX2 (1 << 2) /* transmits slot 12 */ | ||
71 | #define TXCR_TX1 (1 << 1) /* transmits slot 12 */ | ||
72 | #define TXCR_TXEN (1 << 0) /* transmit enable */ | ||
73 | |||
74 | /* | ||
75 | * status register bits. P49 | ||
76 | */ | ||
77 | #define SR_RXTOFE (1 << 11) /* rx timeout fifo empty */ | ||
78 | #define SR_TXTO (1 << 10) /* rx timeout fifo nonempty */ | ||
79 | #define SR_TXU (1 << 9) /* tx underrun */ | ||
80 | #define SR_RXO (1 << 8) /* rx overrun */ | ||
81 | #define SR_TXB (1 << 7) /* tx busy */ | ||
82 | #define SR_RXB (1 << 6) /* rx busy */ | ||
83 | #define SR_TXFF (1 << 5) /* tx fifo full */ | ||
84 | #define SR_RXFF (1 << 4) /* rx fifo full */ | ||
85 | #define SR_TXHE (1 << 3) /* tx fifo half empty */ | ||
86 | #define SR_RXHF (1 << 2) /* rx fifo half full */ | ||
87 | #define SR_TXFE (1 << 1) /* tx fifo empty */ | ||
88 | #define SR_RXFE (1 << 0) /* rx fifo empty */ | ||
89 | |||
90 | /* | ||
91 | * interrupt status register bits. | ||
92 | */ | ||
93 | #define ISR_RXTOFEINTR (1 << 6) /* rx fifo empty */ | ||
94 | #define ISR_URINTR (1 << 5) /* tx underflow */ | ||
95 | #define ISR_ORINTR (1 << 4) /* rx overflow */ | ||
96 | #define ISR_RXINTR (1 << 3) /* rx fifo */ | ||
97 | #define ISR_TXINTR (1 << 2) /* tx fifo intr */ | ||
98 | #define ISR_RXTOINTR (1 << 1) /* tx timeout */ | ||
99 | #define ISR_TXCINTR (1 << 0) /* tx complete */ | ||
100 | |||
101 | /* | ||
102 | * interrupt enable register bits. | ||
103 | */ | ||
104 | #define IE_RXTOIE (1 << 6) | ||
105 | #define IE_URIE (1 << 5) | ||
106 | #define IE_ORIE (1 << 4) | ||
107 | #define IE_RXIE (1 << 3) | ||
108 | #define IE_TXIE (1 << 2) | ||
109 | #define IE_RXTIE (1 << 1) | ||
110 | #define IE_TXCIE (1 << 0) | ||
111 | |||
112 | /* | ||
113 | * interrupt status. P51 | ||
114 | */ | ||
115 | #define ISR_RXTOFE (1 << 6) /* rx timeout fifo empty */ | ||
116 | #define ISR_UR (1 << 5) /* tx fifo underrun */ | ||
117 | #define ISR_OR (1 << 4) /* rx fifo overrun */ | ||
118 | #define ISR_RX (1 << 3) /* rx interrupt status */ | ||
119 | #define ISR_TX (1 << 2) /* tx interrupt status */ | ||
120 | #define ISR_RXTO (1 << 1) /* rx timeout */ | ||
121 | #define ISR_TXC (1 << 0) /* tx complete */ | ||
122 | |||
123 | /* | ||
124 | * interrupt enable. P52 | ||
125 | */ | ||
126 | #define IE_RXTOFE (1 << 6) /* rx timeout fifo empty */ | ||
127 | #define IE_UR (1 << 5) /* tx fifo underrun */ | ||
128 | #define IE_OR (1 << 4) /* rx fifo overrun */ | ||
129 | #define IE_RX (1 << 3) /* rx interrupt status */ | ||
130 | #define IE_TX (1 << 2) /* tx interrupt status */ | ||
131 | #define IE_RXTO (1 << 1) /* rx timeout */ | ||
132 | #define IE_TXC (1 << 0) /* tx complete */ | ||
133 | |||
134 | /* | ||
135 | * slot flag register bits. P56 | ||
136 | */ | ||
137 | #define SLFR_RWIS (1 << 13) /* raw wake-up interrupt status */ | ||
138 | #define SLFR_RGPIOINTR (1 << 12) /* raw gpio interrupt */ | ||
139 | #define SLFR_12TXE (1 << 11) /* slot 12 tx empty */ | ||
140 | #define SLFR_12RXV (1 << 10) /* slot 12 rx valid */ | ||
141 | #define SLFR_2TXE (1 << 9) /* slot 2 tx empty */ | ||
142 | #define SLFR_2RXV (1 << 8) /* slot 2 rx valid */ | ||
143 | #define SLFR_1TXE (1 << 7) /* slot 1 tx empty */ | ||
144 | #define SLFR_1RXV (1 << 6) /* slot 1 rx valid */ | ||
145 | #define SLFR_12TXB (1 << 5) /* slot 12 tx busy */ | ||
146 | #define SLFR_12RXB (1 << 4) /* slot 12 rx busy */ | ||
147 | #define SLFR_2TXB (1 << 3) /* slot 2 tx busy */ | ||
148 | #define SLFR_2RXB (1 << 2) /* slot 2 rx busy */ | ||
149 | #define SLFR_1TXB (1 << 1) /* slot 1 tx busy */ | ||
150 | #define SLFR_1RXB (1 << 0) /* slot 1 rx busy */ | ||
151 | |||
152 | /* | ||
153 | * Interrupt clear register. | ||
154 | */ | ||
155 | #define ICLR_RXTOFEC4 (1 << 12) | ||
156 | #define ICLR_RXTOFEC3 (1 << 11) | ||
157 | #define ICLR_RXTOFEC2 (1 << 10) | ||
158 | #define ICLR_RXTOFEC1 (1 << 9) | ||
159 | #define ICLR_TXUEC4 (1 << 8) | ||
160 | #define ICLR_TXUEC3 (1 << 7) | ||
161 | #define ICLR_TXUEC2 (1 << 6) | ||
162 | #define ICLR_TXUEC1 (1 << 5) | ||
163 | #define ICLR_RXOEC4 (1 << 4) | ||
164 | #define ICLR_RXOEC3 (1 << 3) | ||
165 | #define ICLR_RXOEC2 (1 << 2) | ||
166 | #define ICLR_RXOEC1 (1 << 1) | ||
167 | #define ICLR_WISC (1 << 0) | ||
168 | |||
169 | /* | ||
170 | * Main control register bits. P62 | ||
171 | */ | ||
172 | #define MAINCR_SCRA(x) ((x) << 10) /* secondary codec reg access */ | ||
173 | #define MAINCR_DMAEN (1 << 9) /* dma enable */ | ||
174 | #define MAINCR_SL12TXEN (1 << 8) /* slot 12 transmit enable */ | ||
175 | #define MAINCR_SL12RXEN (1 << 7) /* slot 12 receive enable */ | ||
176 | #define MAINCR_SL2TXEN (1 << 6) /* slot 2 transmit enable */ | ||
177 | #define MAINCR_SL2RXEN (1 << 5) /* slot 2 receive enable */ | ||
178 | #define MAINCR_SL1TXEN (1 << 4) /* slot 1 transmit enable */ | ||
179 | #define MAINCR_SL1RXEN (1 << 3) /* slot 1 receive enable */ | ||
180 | #define MAINCR_LPM (1 << 2) /* low power mode */ | ||
181 | #define MAINCR_LOOPBK (1 << 1) /* loopback */ | ||
182 | #define MAINCR_IE (1 << 0) /* aaci interface enable */ | ||
183 | |||
184 | /* | ||
185 | * Reset register bits. P65 | ||
186 | */ | ||
187 | #define RESET_NRST (1 << 0) | ||
188 | |||
189 | /* | ||
190 | * Sync register bits. P65 | ||
191 | */ | ||
192 | #define SYNC_FORCE (1 << 0) | ||
193 | |||
194 | /* | ||
195 | * Main flag register bits. P66 | ||
196 | */ | ||
197 | #define MAINFR_TXB (1 << 1) /* transmit busy */ | ||
198 | #define MAINFR_RXB (1 << 0) /* receive busy */ | ||
199 | |||
200 | |||
201 | |||
202 | struct aaci_runtime { | ||
203 | void *base; | ||
204 | void *fifo; | ||
205 | |||
206 | struct ac97_pcm *pcm; | ||
207 | int pcm_open; | ||
208 | |||
209 | u32 cr; | ||
210 | snd_pcm_substream_t *substream; | ||
211 | |||
212 | /* | ||
213 | * PIO support | ||
214 | */ | ||
215 | void *start; | ||
216 | void *end; | ||
217 | void *ptr; | ||
218 | int bytes; | ||
219 | unsigned int period; | ||
220 | unsigned int fifosz; | ||
221 | }; | ||
222 | |||
223 | struct aaci { | ||
224 | struct amba_device *dev; | ||
225 | snd_card_t *card; | ||
226 | void *base; | ||
227 | unsigned int fifosize; | ||
228 | |||
229 | /* AC'97 */ | ||
230 | struct semaphore ac97_sem; | ||
231 | ac97_bus_t *ac97_bus; | ||
232 | |||
233 | u32 maincr; | ||
234 | spinlock_t lock; | ||
235 | |||
236 | struct aaci_runtime playback; | ||
237 | struct aaci_runtime capture; | ||
238 | |||
239 | snd_pcm_t *pcm; | ||
240 | }; | ||
241 | |||
242 | #define ACSTREAM_FRONT 0 | ||
243 | #define ACSTREAM_SURROUND 1 | ||
244 | #define ACSTREAM_LFE 2 | ||
245 | |||
246 | #endif | ||
diff --git a/sound/arm/devdma.c b/sound/arm/devdma.c new file mode 100644 index 000000000000..60826a5324b4 --- /dev/null +++ b/sound/arm/devdma.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * linux/sound/arm/devdma.c | ||
3 | * | ||
4 | * Copyright (C) 2003-2004 Russell King, All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * ARM DMA shim for ALSA. | ||
11 | */ | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/dma-mapping.h> | ||
14 | |||
15 | #include <sound/driver.h> | ||
16 | #include <sound/core.h> | ||
17 | #include <sound/pcm.h> | ||
18 | |||
19 | #include "devdma.h" | ||
20 | |||
21 | void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream) | ||
22 | { | ||
23 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
24 | struct snd_dma_buffer *buf = runtime->dma_buffer_p; | ||
25 | |||
26 | if (runtime->dma_area == NULL) | ||
27 | return; | ||
28 | |||
29 | if (buf != &substream->dma_buffer) { | ||
30 | dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr); | ||
31 | kfree(runtime->dma_buffer_p); | ||
32 | } | ||
33 | |||
34 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
35 | } | ||
36 | |||
37 | int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size) | ||
38 | { | ||
39 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
40 | struct snd_dma_buffer *buf = runtime->dma_buffer_p; | ||
41 | int ret = 0; | ||
42 | |||
43 | if (buf) { | ||
44 | if (buf->bytes >= size) | ||
45 | goto out; | ||
46 | devdma_hw_free(dev, substream); | ||
47 | } | ||
48 | |||
49 | if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) { | ||
50 | buf = &substream->dma_buffer; | ||
51 | } else { | ||
52 | buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL); | ||
53 | if (!buf) | ||
54 | goto nomem; | ||
55 | |||
56 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
57 | buf->dev.dev = dev; | ||
58 | buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL); | ||
59 | buf->bytes = size; | ||
60 | buf->private_data = NULL; | ||
61 | |||
62 | if (!buf->area) | ||
63 | goto free; | ||
64 | } | ||
65 | snd_pcm_set_runtime_buffer(substream, buf); | ||
66 | ret = 1; | ||
67 | out: | ||
68 | runtime->dma_bytes = size; | ||
69 | return ret; | ||
70 | |||
71 | free: | ||
72 | kfree(buf); | ||
73 | nomem: | ||
74 | return -ENOMEM; | ||
75 | } | ||
76 | |||
77 | int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma) | ||
78 | { | ||
79 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
80 | return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes); | ||
81 | } | ||
diff --git a/sound/arm/devdma.h b/sound/arm/devdma.h new file mode 100644 index 000000000000..5a33b6bacc34 --- /dev/null +++ b/sound/arm/devdma.h | |||
@@ -0,0 +1,3 @@ | |||
1 | void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream); | ||
2 | int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size); | ||
3 | int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma); | ||
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c new file mode 100644 index 000000000000..46052304e230 --- /dev/null +++ b/sound/arm/pxa2xx-ac97.c | |||
@@ -0,0 +1,410 @@ | |||
1 | /* | ||
2 | * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip. | ||
3 | * | ||
4 | * Author: Nicolas Pitre | ||
5 | * Created: Dec 02, 2004 | ||
6 | * Copyright: MontaVista Software Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/wait.h> | ||
19 | #include <linux/delay.h> | ||
20 | |||
21 | #include <sound/driver.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/ac97_codec.h> | ||
25 | #include <sound/initval.h> | ||
26 | |||
27 | #include <asm/irq.h> | ||
28 | #include <asm/semaphore.h> | ||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/arch/pxa-regs.h> | ||
31 | #include <asm/arch/audio.h> | ||
32 | |||
33 | #include "pxa2xx-pcm.h" | ||
34 | |||
35 | |||
36 | static DECLARE_MUTEX(car_mutex); | ||
37 | static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); | ||
38 | static volatile long gsr_bits; | ||
39 | |||
40 | static unsigned short pxa2xx_ac97_read(ac97_t *ac97, unsigned short reg) | ||
41 | { | ||
42 | unsigned short val = -1; | ||
43 | volatile u32 *reg_addr; | ||
44 | |||
45 | down(&car_mutex); | ||
46 | if (CAR & CAR_CAIP) { | ||
47 | printk(KERN_CRIT"%s: CAR_CAIP already set\n", __FUNCTION__); | ||
48 | goto out; | ||
49 | } | ||
50 | |||
51 | /* set up primary or secondary codec space */ | ||
52 | reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; | ||
53 | reg_addr += (reg >> 1); | ||
54 | |||
55 | /* start read access across the ac97 link */ | ||
56 | gsr_bits = 0; | ||
57 | val = *reg_addr; | ||
58 | if (reg == AC97_GPIO_STATUS) | ||
59 | goto out; | ||
60 | wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1); | ||
61 | if (!gsr_bits & GSR_SDONE) { | ||
62 | printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", | ||
63 | __FUNCTION__, reg, gsr_bits); | ||
64 | val = -1; | ||
65 | goto out; | ||
66 | } | ||
67 | |||
68 | /* valid data now */ | ||
69 | gsr_bits = 0; | ||
70 | val = *reg_addr; | ||
71 | /* but we've just started another cycle... */ | ||
72 | wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1); | ||
73 | |||
74 | out: up(&car_mutex); | ||
75 | return val; | ||
76 | } | ||
77 | |||
78 | static void pxa2xx_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) | ||
79 | { | ||
80 | volatile u32 *reg_addr; | ||
81 | |||
82 | down(&car_mutex); | ||
83 | |||
84 | if (CAR & CAR_CAIP) { | ||
85 | printk(KERN_CRIT "%s: CAR_CAIP already set\n", __FUNCTION__); | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | /* set up primary or secondary codec space */ | ||
90 | reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; | ||
91 | reg_addr += (reg >> 1); | ||
92 | gsr_bits = 0; | ||
93 | *reg_addr = val; | ||
94 | wait_event_timeout(gsr_wq, gsr_bits & GSR_CDONE, 1); | ||
95 | if (!gsr_bits & GSR_SDONE) | ||
96 | printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n", | ||
97 | __FUNCTION__, reg, gsr_bits); | ||
98 | |||
99 | out: up(&car_mutex); | ||
100 | } | ||
101 | |||
102 | static void pxa2xx_ac97_reset(ac97_t *ac97) | ||
103 | { | ||
104 | /* First, try cold reset */ | ||
105 | GCR &= GCR_COLD_RST; /* clear everything but nCRST */ | ||
106 | GCR &= ~GCR_COLD_RST; /* then assert nCRST */ | ||
107 | |||
108 | gsr_bits = 0; | ||
109 | #ifdef CONFIG_PXA27x | ||
110 | /* PXA27x Developers Manual section 13.5.2.2.1 */ | ||
111 | pxa_set_cken(1 << 31, 1); | ||
112 | udelay(5); | ||
113 | pxa_set_cken(1 << 31, 0); | ||
114 | GCR = GCR_COLD_RST; | ||
115 | udelay(50); | ||
116 | #else | ||
117 | GCR = GCR_COLD_RST; | ||
118 | GCR |= GCR_CDONE_IE|GCR_SDONE_IE; | ||
119 | wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); | ||
120 | #endif | ||
121 | |||
122 | if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { | ||
123 | printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", | ||
124 | __FUNCTION__, gsr_bits); | ||
125 | |||
126 | /* let's try warm reset */ | ||
127 | gsr_bits = 0; | ||
128 | #ifdef CONFIG_PXA27x | ||
129 | /* warm reset broken on Bulverde, | ||
130 | so manually keep AC97 reset high */ | ||
131 | pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); | ||
132 | udelay(10); | ||
133 | GCR |= GCR_WARM_RST; | ||
134 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | ||
135 | udelay(50); | ||
136 | #else | ||
137 | GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;; | ||
138 | wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); | ||
139 | #endif | ||
140 | |||
141 | if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) | ||
142 | printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", | ||
143 | __FUNCTION__, gsr_bits); | ||
144 | } | ||
145 | |||
146 | GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); | ||
147 | GCR |= GCR_SDONE_IE|GCR_CDONE_IE; | ||
148 | } | ||
149 | |||
150 | static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
151 | { | ||
152 | long status; | ||
153 | |||
154 | status = GSR; | ||
155 | if (status) { | ||
156 | GSR = status; | ||
157 | gsr_bits |= status; | ||
158 | wake_up(&gsr_wq); | ||
159 | |||
160 | #ifdef CONFIG_PXA27x | ||
161 | /* Although we don't use those we still need to clear them | ||
162 | since they tend to spuriously trigger when MMC is used | ||
163 | (hardware bug? go figure)... */ | ||
164 | MISR = MISR_EOC; | ||
165 | PISR = PISR_EOC; | ||
166 | MCSR = MCSR_EOC; | ||
167 | #endif | ||
168 | |||
169 | return IRQ_HANDLED; | ||
170 | } | ||
171 | |||
172 | return IRQ_NONE; | ||
173 | } | ||
174 | |||
175 | static ac97_bus_ops_t pxa2xx_ac97_ops = { | ||
176 | .read = pxa2xx_ac97_read, | ||
177 | .write = pxa2xx_ac97_write, | ||
178 | .reset = pxa2xx_ac97_reset, | ||
179 | }; | ||
180 | |||
181 | static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_out = { | ||
182 | .name = "AC97 PCM out", | ||
183 | .dev_addr = __PREG(PCDR), | ||
184 | .drcmr = &DRCMRTXPCDR, | ||
185 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | ||
186 | DCMD_BURST32 | DCMD_WIDTH4, | ||
187 | }; | ||
188 | |||
189 | static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_in = { | ||
190 | .name = "AC97 PCM in", | ||
191 | .dev_addr = __PREG(PCDR), | ||
192 | .drcmr = &DRCMRRXPCDR, | ||
193 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | ||
194 | DCMD_BURST32 | DCMD_WIDTH4, | ||
195 | }; | ||
196 | |||
197 | static snd_pcm_t *pxa2xx_ac97_pcm; | ||
198 | static ac97_t *pxa2xx_ac97_ac97; | ||
199 | |||
200 | static int pxa2xx_ac97_pcm_startup(snd_pcm_substream_t *substream) | ||
201 | { | ||
202 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
203 | pxa2xx_audio_ops_t *platform_ops; | ||
204 | int r; | ||
205 | |||
206 | runtime->hw.channels_min = 2; | ||
207 | runtime->hw.channels_max = 2; | ||
208 | |||
209 | r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
210 | AC97_RATES_FRONT_DAC : AC97_RATES_ADC; | ||
211 | runtime->hw.rates = pxa2xx_ac97_ac97->rates[r]; | ||
212 | snd_pcm_limit_hw_rates(runtime); | ||
213 | |||
214 | platform_ops = substream->pcm->card->dev->platform_data; | ||
215 | if (platform_ops && platform_ops->startup) | ||
216 | return platform_ops->startup(substream, platform_ops->priv); | ||
217 | else | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static void pxa2xx_ac97_pcm_shutdown(snd_pcm_substream_t *substream) | ||
222 | { | ||
223 | pxa2xx_audio_ops_t *platform_ops; | ||
224 | |||
225 | platform_ops = substream->pcm->card->dev->platform_data; | ||
226 | if (platform_ops && platform_ops->shutdown) | ||
227 | platform_ops->shutdown(substream, platform_ops->priv); | ||
228 | } | ||
229 | |||
230 | static int pxa2xx_ac97_pcm_prepare(snd_pcm_substream_t *substream) | ||
231 | { | ||
232 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
233 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
234 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; | ||
235 | return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate); | ||
236 | } | ||
237 | |||
238 | static pxa2xx_pcm_client_t pxa2xx_ac97_pcm_client = { | ||
239 | .playback_params = &pxa2xx_ac97_pcm_out, | ||
240 | .capture_params = &pxa2xx_ac97_pcm_in, | ||
241 | .startup = pxa2xx_ac97_pcm_startup, | ||
242 | .shutdown = pxa2xx_ac97_pcm_shutdown, | ||
243 | .prepare = pxa2xx_ac97_pcm_prepare, | ||
244 | }; | ||
245 | |||
246 | #ifdef CONFIG_PM | ||
247 | |||
248 | static int pxa2xx_ac97_do_suspend(snd_card_t *card, unsigned int state) | ||
249 | { | ||
250 | if (card->power_state != SNDRV_CTL_POWER_D3cold) { | ||
251 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; | ||
252 | snd_pcm_suspend_all(pxa2xx_ac97_pcm); | ||
253 | snd_ac97_suspend(pxa2xx_ac97_ac97); | ||
254 | snd_power_change_state(card, SNDRV_CTL_POWER_D3cold); | ||
255 | if (platform_ops && platform_ops->suspend) | ||
256 | platform_ops->suspend(platform_ops->priv); | ||
257 | GCR |= GCR_ACLINK_OFF; | ||
258 | pxa_set_cken(CKEN2_AC97, 0); | ||
259 | } | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int pxa2xx_ac97_do_resume(snd_card_t *card, unsigned int state) | ||
265 | { | ||
266 | if (card->power_state != SNDRV_CTL_POWER_D0) { | ||
267 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; | ||
268 | pxa_set_cken(CKEN2_AC97, 1); | ||
269 | if (platform_ops && platform_ops->resume) | ||
270 | platform_ops->resume(platform_ops->priv); | ||
271 | snd_ac97_resume(pxa2xx_ac97_ac97); | ||
272 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
273 | } | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int pxa2xx_ac97_suspend(struct device *_dev, u32 state, u32 level) | ||
279 | { | ||
280 | snd_card_t *card = dev_get_drvdata(_dev); | ||
281 | int ret = 0; | ||
282 | |||
283 | if (card && level == SUSPEND_DISABLE) | ||
284 | ret = pxa2xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold); | ||
285 | |||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | static int pxa2xx_ac97_resume(struct device *_dev, u32 level) | ||
290 | { | ||
291 | snd_card_t *card = dev_get_drvdata(_dev); | ||
292 | int ret = 0; | ||
293 | |||
294 | if (card && level == RESUME_ENABLE) | ||
295 | ret = pxa2xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0); | ||
296 | |||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | #else | ||
301 | #define pxa2xx_ac97_suspend NULL | ||
302 | #define pxa2xx_ac97_resume NULL | ||
303 | #endif | ||
304 | |||
305 | static int pxa2xx_ac97_probe(struct device *dev) | ||
306 | { | ||
307 | snd_card_t *card; | ||
308 | ac97_bus_t *ac97_bus; | ||
309 | ac97_template_t ac97_template; | ||
310 | int ret; | ||
311 | |||
312 | ret = -ENOMEM; | ||
313 | card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | ||
314 | THIS_MODULE, 0); | ||
315 | if (!card) | ||
316 | goto err; | ||
317 | |||
318 | card->dev = dev; | ||
319 | strncpy(card->driver, dev->driver->name, sizeof(card->driver)); | ||
320 | |||
321 | ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm); | ||
322 | if (ret) | ||
323 | goto err; | ||
324 | |||
325 | ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL); | ||
326 | if (ret < 0) | ||
327 | goto err; | ||
328 | |||
329 | pxa_gpio_mode(GPIO31_SYNC_AC97_MD); | ||
330 | pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); | ||
331 | pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); | ||
332 | pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); | ||
333 | #ifdef CONFIG_PXA27x | ||
334 | /* Use GPIO 113 as AC97 Reset on Bulverde */ | ||
335 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | ||
336 | #endif | ||
337 | pxa_set_cken(CKEN2_AC97, 1); | ||
338 | |||
339 | ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus); | ||
340 | if (ret) | ||
341 | goto err; | ||
342 | memset(&ac97_template, 0, sizeof(ac97_template)); | ||
343 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97); | ||
344 | if (ret) | ||
345 | goto err; | ||
346 | |||
347 | snprintf(card->shortname, sizeof(card->shortname), | ||
348 | "%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97)); | ||
349 | snprintf(card->longname, sizeof(card->longname), | ||
350 | "%s (%s)", dev->driver->name, card->mixername); | ||
351 | |||
352 | snd_card_set_pm_callback(card, pxa2xx_ac97_do_suspend, | ||
353 | pxa2xx_ac97_do_resume, NULL); | ||
354 | ret = snd_card_register(card); | ||
355 | if (ret == 0) { | ||
356 | dev_set_drvdata(dev, card); | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | err: | ||
361 | if (card) | ||
362 | snd_card_free(card); | ||
363 | if (CKEN & CKEN2_AC97) { | ||
364 | GCR |= GCR_ACLINK_OFF; | ||
365 | free_irq(IRQ_AC97, NULL); | ||
366 | pxa_set_cken(CKEN2_AC97, 0); | ||
367 | } | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | static int pxa2xx_ac97_remove(struct device *dev) | ||
372 | { | ||
373 | snd_card_t *card = dev_get_drvdata(dev); | ||
374 | |||
375 | if (card) { | ||
376 | snd_card_free(card); | ||
377 | dev_set_drvdata(dev, NULL); | ||
378 | GCR |= GCR_ACLINK_OFF; | ||
379 | free_irq(IRQ_AC97, NULL); | ||
380 | pxa_set_cken(CKEN2_AC97, 0); | ||
381 | } | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static struct device_driver pxa2xx_ac97_driver = { | ||
387 | .name = "pxa2xx-ac97", | ||
388 | .bus = &platform_bus_type, | ||
389 | .probe = pxa2xx_ac97_probe, | ||
390 | .remove = pxa2xx_ac97_remove, | ||
391 | .suspend = pxa2xx_ac97_suspend, | ||
392 | .resume = pxa2xx_ac97_resume, | ||
393 | }; | ||
394 | |||
395 | static int __init pxa2xx_ac97_init(void) | ||
396 | { | ||
397 | return driver_register(&pxa2xx_ac97_driver); | ||
398 | } | ||
399 | |||
400 | static void __exit pxa2xx_ac97_exit(void) | ||
401 | { | ||
402 | driver_unregister(&pxa2xx_ac97_driver); | ||
403 | } | ||
404 | |||
405 | module_init(pxa2xx_ac97_init); | ||
406 | module_exit(pxa2xx_ac97_exit); | ||
407 | |||
408 | MODULE_AUTHOR("Nicolas Pitre"); | ||
409 | MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); | ||
410 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c new file mode 100644 index 000000000000..b1eb53b02eae --- /dev/null +++ b/sound/arm/pxa2xx-pcm.c | |||
@@ -0,0 +1,367 @@ | |||
1 | /* | ||
2 | * linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip | ||
3 | * | ||
4 | * Author: Nicolas Pitre | ||
5 | * Created: Nov 30, 2004 | ||
6 | * Copyright: (C) 2004 MontaVista Software, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | |||
19 | #include <sound/driver.h> | ||
20 | #include <sound/core.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | |||
24 | #include <asm/dma.h> | ||
25 | #include <asm/hardware.h> | ||
26 | #include <asm/arch/pxa-regs.h> | ||
27 | |||
28 | #include "pxa2xx-pcm.h" | ||
29 | |||
30 | |||
31 | static const snd_pcm_hardware_t pxa2xx_pcm_hardware = { | ||
32 | .info = SNDRV_PCM_INFO_MMAP | | ||
33 | SNDRV_PCM_INFO_MMAP_VALID | | ||
34 | SNDRV_PCM_INFO_INTERLEAVED | | ||
35 | SNDRV_PCM_INFO_PAUSE, | ||
36 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
37 | .period_bytes_min = 32, | ||
38 | .period_bytes_max = 8192 - 32, | ||
39 | .periods_min = 1, | ||
40 | .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc), | ||
41 | .buffer_bytes_max = 128 * 1024, | ||
42 | .fifo_size = 32, | ||
43 | }; | ||
44 | |||
45 | struct pxa2xx_runtime_data { | ||
46 | int dma_ch; | ||
47 | pxa2xx_pcm_dma_params_t *params; | ||
48 | pxa_dma_desc *dma_desc_array; | ||
49 | dma_addr_t dma_desc_array_phys; | ||
50 | }; | ||
51 | |||
52 | static int pxa2xx_pcm_hw_params(snd_pcm_substream_t *substream, | ||
53 | snd_pcm_hw_params_t *params) | ||
54 | { | ||
55 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
56 | struct pxa2xx_runtime_data *rtd = runtime->private_data; | ||
57 | size_t totsize = params_buffer_bytes(params); | ||
58 | size_t period = params_period_bytes(params); | ||
59 | pxa_dma_desc *dma_desc; | ||
60 | dma_addr_t dma_buff_phys, next_desc_phys; | ||
61 | |||
62 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
63 | runtime->dma_bytes = totsize; | ||
64 | |||
65 | dma_desc = rtd->dma_desc_array; | ||
66 | next_desc_phys = rtd->dma_desc_array_phys; | ||
67 | dma_buff_phys = runtime->dma_addr; | ||
68 | do { | ||
69 | next_desc_phys += sizeof(pxa_dma_desc); | ||
70 | dma_desc->ddadr = next_desc_phys; | ||
71 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
72 | dma_desc->dsadr = dma_buff_phys; | ||
73 | dma_desc->dtadr = rtd->params->dev_addr; | ||
74 | } else { | ||
75 | dma_desc->dsadr = rtd->params->dev_addr; | ||
76 | dma_desc->dtadr = dma_buff_phys; | ||
77 | } | ||
78 | if (period > totsize) | ||
79 | period = totsize; | ||
80 | dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN; | ||
81 | dma_desc++; | ||
82 | dma_buff_phys += period; | ||
83 | } while (totsize -= period); | ||
84 | dma_desc[-1].ddadr = rtd->dma_desc_array_phys; | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int pxa2xx_pcm_hw_free(snd_pcm_substream_t *substream) | ||
90 | { | ||
91 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; | ||
92 | |||
93 | *rtd->params->drcmr = 0; | ||
94 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int pxa2xx_pcm_prepare(snd_pcm_substream_t *substream) | ||
99 | { | ||
100 | pxa2xx_pcm_client_t *client = substream->private_data; | ||
101 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
102 | struct pxa2xx_runtime_data *rtd = runtime->private_data; | ||
103 | |||
104 | DCSR(rtd->dma_ch) &= ~DCSR_RUN; | ||
105 | DCSR(rtd->dma_ch) = 0; | ||
106 | DCMD(rtd->dma_ch) = 0; | ||
107 | *rtd->params->drcmr = rtd->dma_ch | DRCMR_MAPVLD; | ||
108 | |||
109 | return client->prepare(substream); | ||
110 | } | ||
111 | |||
112 | static int pxa2xx_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | ||
113 | { | ||
114 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; | ||
115 | int ret = 0; | ||
116 | |||
117 | switch (cmd) { | ||
118 | case SNDRV_PCM_TRIGGER_START: | ||
119 | DDADR(rtd->dma_ch) = rtd->dma_desc_array_phys; | ||
120 | DCSR(rtd->dma_ch) = DCSR_RUN; | ||
121 | break; | ||
122 | |||
123 | case SNDRV_PCM_TRIGGER_STOP: | ||
124 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
125 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
126 | DCSR(rtd->dma_ch) &= ~DCSR_RUN; | ||
127 | break; | ||
128 | |||
129 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
130 | DCSR(rtd->dma_ch) |= DCSR_RUN; | ||
131 | break; | ||
132 | |||
133 | default: | ||
134 | ret = -EINVAL; | ||
135 | } | ||
136 | |||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id, struct pt_regs *regs) | ||
141 | { | ||
142 | snd_pcm_substream_t *substream = dev_id; | ||
143 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; | ||
144 | int dcsr; | ||
145 | |||
146 | dcsr = DCSR(dma_ch); | ||
147 | DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN; | ||
148 | |||
149 | if (dcsr & DCSR_ENDINTR) { | ||
150 | snd_pcm_period_elapsed(substream); | ||
151 | } else { | ||
152 | printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n", | ||
153 | rtd->params->name, dma_ch, dcsr ); | ||
154 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); | ||
155 | } | ||
156 | } | ||
157 | |||
158 | static snd_pcm_uframes_t pxa2xx_pcm_pointer(snd_pcm_substream_t *substream) | ||
159 | { | ||
160 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
161 | struct pxa2xx_runtime_data *rtd = runtime->private_data; | ||
162 | dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
163 | DSADR(rtd->dma_ch) : DTADR(rtd->dma_ch); | ||
164 | snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr); | ||
165 | if (x == runtime->buffer_size) | ||
166 | x = 0; | ||
167 | return x; | ||
168 | } | ||
169 | |||
170 | static int | ||
171 | pxa2xx_pcm_hw_rule_mult32(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule) | ||
172 | { | ||
173 | snd_interval_t *i = hw_param_interval(params, rule->var); | ||
174 | int changed = 0; | ||
175 | |||
176 | if (i->min & 31) { | ||
177 | i->min = (i->min & ~31) + 32; | ||
178 | i->openmin = 0; | ||
179 | changed = 1; | ||
180 | } | ||
181 | |||
182 | if (i->max & 31) { | ||
183 | i->max &= ~31; | ||
184 | i->openmax = 0; | ||
185 | changed = 1; | ||
186 | } | ||
187 | |||
188 | return changed; | ||
189 | } | ||
190 | |||
191 | static int pxa2xx_pcm_open(snd_pcm_substream_t *substream) | ||
192 | { | ||
193 | pxa2xx_pcm_client_t *client = substream->private_data; | ||
194 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
195 | struct pxa2xx_runtime_data *rtd; | ||
196 | int ret; | ||
197 | |||
198 | runtime->hw = pxa2xx_pcm_hardware; | ||
199 | |||
200 | /* | ||
201 | * For mysterious reasons (and despite what the manual says) | ||
202 | * playback samples are lost if the DMA count is not a multiple | ||
203 | * of the DMA burst size. Let's add a rule to enforce that. | ||
204 | */ | ||
205 | ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, | ||
206 | pxa2xx_pcm_hw_rule_mult32, NULL, | ||
207 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -1); | ||
208 | if (ret) | ||
209 | goto out; | ||
210 | ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | ||
211 | pxa2xx_pcm_hw_rule_mult32, NULL, | ||
212 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1); | ||
213 | if (ret) | ||
214 | goto out; | ||
215 | |||
216 | ret = -ENOMEM; | ||
217 | rtd = kmalloc(sizeof(*rtd), GFP_KERNEL); | ||
218 | if (!rtd) | ||
219 | goto out; | ||
220 | rtd->dma_desc_array = | ||
221 | dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE, | ||
222 | &rtd->dma_desc_array_phys, GFP_KERNEL); | ||
223 | if (!rtd->dma_desc_array) | ||
224 | goto err1; | ||
225 | |||
226 | rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
227 | client->playback_params : client->capture_params; | ||
228 | ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW, | ||
229 | pxa2xx_pcm_dma_irq, substream); | ||
230 | if (ret < 0) | ||
231 | goto err2; | ||
232 | rtd->dma_ch = ret; | ||
233 | |||
234 | runtime->private_data = rtd; | ||
235 | ret = client->startup(substream); | ||
236 | if (!ret) | ||
237 | goto out; | ||
238 | |||
239 | pxa_free_dma(rtd->dma_ch); | ||
240 | err2: | ||
241 | dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, | ||
242 | rtd->dma_desc_array, rtd->dma_desc_array_phys); | ||
243 | err1: | ||
244 | kfree(rtd); | ||
245 | out: | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | static int pxa2xx_pcm_close(snd_pcm_substream_t *substream) | ||
250 | { | ||
251 | pxa2xx_pcm_client_t *client = substream->private_data; | ||
252 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; | ||
253 | |||
254 | pxa_free_dma(rtd->dma_ch); | ||
255 | client->shutdown(substream); | ||
256 | dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, | ||
257 | rtd->dma_desc_array, rtd->dma_desc_array_phys); | ||
258 | kfree(rtd); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static int | ||
263 | pxa2xx_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma) | ||
264 | { | ||
265 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
266 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
267 | runtime->dma_area, | ||
268 | runtime->dma_addr, | ||
269 | runtime->dma_bytes); | ||
270 | } | ||
271 | |||
272 | static snd_pcm_ops_t pxa2xx_pcm_ops = { | ||
273 | .open = pxa2xx_pcm_open, | ||
274 | .close = pxa2xx_pcm_close, | ||
275 | .ioctl = snd_pcm_lib_ioctl, | ||
276 | .hw_params = pxa2xx_pcm_hw_params, | ||
277 | .hw_free = pxa2xx_pcm_hw_free, | ||
278 | .prepare = pxa2xx_pcm_prepare, | ||
279 | .trigger = pxa2xx_pcm_trigger, | ||
280 | .pointer = pxa2xx_pcm_pointer, | ||
281 | .mmap = pxa2xx_pcm_mmap, | ||
282 | }; | ||
283 | |||
284 | static int pxa2xx_pcm_preallocate_dma_buffer(snd_pcm_t *pcm, int stream) | ||
285 | { | ||
286 | snd_pcm_substream_t *substream = pcm->streams[stream].substream; | ||
287 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
288 | size_t size = pxa2xx_pcm_hardware.buffer_bytes_max; | ||
289 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
290 | buf->dev.dev = pcm->card->dev; | ||
291 | buf->private_data = NULL; | ||
292 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
293 | &buf->addr, GFP_KERNEL); | ||
294 | if (!buf->area) | ||
295 | return -ENOMEM; | ||
296 | buf->bytes = size; | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static void pxa2xx_pcm_free_dma_buffers(snd_pcm_t *pcm) | ||
301 | { | ||
302 | snd_pcm_substream_t *substream; | ||
303 | struct snd_dma_buffer *buf; | ||
304 | int stream; | ||
305 | |||
306 | for (stream = 0; stream < 2; stream++) { | ||
307 | substream = pcm->streams[stream].substream; | ||
308 | if (!substream) | ||
309 | continue; | ||
310 | buf = &substream->dma_buffer; | ||
311 | if (!buf->area) | ||
312 | continue; | ||
313 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
314 | buf->area, buf->addr); | ||
315 | buf->area = NULL; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | static u64 pxa2xx_pcm_dmamask = 0xffffffff; | ||
320 | |||
321 | int pxa2xx_pcm_new(snd_card_t *card, pxa2xx_pcm_client_t *client, snd_pcm_t **rpcm) | ||
322 | { | ||
323 | snd_pcm_t *pcm; | ||
324 | int play = client->playback_params ? 1 : 0; | ||
325 | int capt = client->capture_params ? 1 : 0; | ||
326 | int ret; | ||
327 | |||
328 | ret = snd_pcm_new(card, "PXA2xx-PCM", 0, play, capt, &pcm); | ||
329 | if (ret) | ||
330 | goto out; | ||
331 | |||
332 | pcm->private_data = client; | ||
333 | pcm->private_free = pxa2xx_pcm_free_dma_buffers; | ||
334 | |||
335 | if (!card->dev->dma_mask) | ||
336 | card->dev->dma_mask = &pxa2xx_pcm_dmamask; | ||
337 | if (!card->dev->coherent_dma_mask) | ||
338 | card->dev->coherent_dma_mask = 0xffffffff; | ||
339 | |||
340 | if (play) { | ||
341 | int stream = SNDRV_PCM_STREAM_PLAYBACK; | ||
342 | snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops); | ||
343 | ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream); | ||
344 | if (ret) | ||
345 | goto out; | ||
346 | } | ||
347 | if (capt) { | ||
348 | int stream = SNDRV_PCM_STREAM_CAPTURE; | ||
349 | snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops); | ||
350 | ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream); | ||
351 | if (ret) | ||
352 | goto out; | ||
353 | } | ||
354 | |||
355 | if (rpcm) | ||
356 | *rpcm = pcm; | ||
357 | ret = 0; | ||
358 | |||
359 | out: | ||
360 | return ret; | ||
361 | } | ||
362 | |||
363 | EXPORT_SYMBOL(pxa2xx_pcm_new); | ||
364 | |||
365 | MODULE_AUTHOR("Nicolas Pitre"); | ||
366 | MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); | ||
367 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h new file mode 100644 index 000000000000..43517597cab9 --- /dev/null +++ b/sound/arm/pxa2xx-pcm.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip | ||
3 | * | ||
4 | * Author: Nicolas Pitre | ||
5 | * Created: Nov 30, 2004 | ||
6 | * Copyright: MontaVista Software, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | typedef struct { | ||
14 | char *name; /* stream identifier */ | ||
15 | u32 dcmd; /* DMA descriptor dcmd field */ | ||
16 | volatile u32 *drcmr; /* the DMA request channel to use */ | ||
17 | u32 dev_addr; /* device physical address for DMA */ | ||
18 | } pxa2xx_pcm_dma_params_t; | ||
19 | |||
20 | typedef struct { | ||
21 | pxa2xx_pcm_dma_params_t *playback_params; | ||
22 | pxa2xx_pcm_dma_params_t *capture_params; | ||
23 | int (*startup)(snd_pcm_substream_t *); | ||
24 | void (*shutdown)(snd_pcm_substream_t *); | ||
25 | int (*prepare)(snd_pcm_substream_t *); | ||
26 | } pxa2xx_pcm_client_t; | ||
27 | |||
28 | extern int pxa2xx_pcm_new(snd_card_t *, pxa2xx_pcm_client_t *, snd_pcm_t **); | ||
29 | |||
diff --git a/sound/core/control.c b/sound/core/control.c index f4ea6bff1dd3..227f3cf02771 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -215,7 +215,7 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access) | |||
215 | * | 215 | * |
216 | * Returns the pointer of the newly generated instance, or NULL on failure. | 216 | * Returns the pointer of the newly generated instance, or NULL on failure. |
217 | */ | 217 | */ |
218 | snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * ncontrol, void *private_data) | 218 | snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * ncontrol, void *private_data) |
219 | { | 219 | { |
220 | snd_kcontrol_t kctl; | 220 | snd_kcontrol_t kctl; |
221 | unsigned int access; | 221 | unsigned int access; |
@@ -1102,7 +1102,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg | |||
1102 | } | 1102 | } |
1103 | } | 1103 | } |
1104 | up_read(&snd_ioctl_rwsem); | 1104 | up_read(&snd_ioctl_rwsem); |
1105 | snd_printd("unknown ioctl = 0x%x\n", cmd); | 1105 | snd_printdd("unknown ioctl = 0x%x\n", cmd); |
1106 | return -ENOTTY; | 1106 | return -ENOTTY; |
1107 | } | 1107 | } |
1108 | 1108 | ||
diff --git a/sound/core/device.c b/sound/core/device.c index 18c71f913d2a..ca00ad7740c9 100644 --- a/sound/core/device.c +++ b/sound/core/device.c | |||
@@ -28,7 +28,7 @@ | |||
28 | /** | 28 | /** |
29 | * snd_device_new - create an ALSA device component | 29 | * snd_device_new - create an ALSA device component |
30 | * @card: the card instance | 30 | * @card: the card instance |
31 | * @type: the device type, SNDRV_DEV_TYPE_XXX | 31 | * @type: the device type, SNDRV_DEV_XXX |
32 | * @device_data: the data pointer of this device | 32 | * @device_data: the data pointer of this device |
33 | * @ops: the operator table | 33 | * @ops: the operator table |
34 | * | 34 | * |
@@ -46,7 +46,9 @@ int snd_device_new(snd_card_t *card, snd_device_type_t type, | |||
46 | { | 46 | { |
47 | snd_device_t *dev; | 47 | snd_device_t *dev; |
48 | 48 | ||
49 | snd_assert(card != NULL && device_data != NULL && ops != NULL, return -ENXIO); | 49 | snd_assert(card != NULL, return -ENXIO); |
50 | snd_assert(device_data != NULL, return -ENXIO); | ||
51 | snd_assert(ops != NULL, return -ENXIO); | ||
50 | dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); | 52 | dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); |
51 | if (dev == NULL) | 53 | if (dev == NULL) |
52 | return -ENOMEM; | 54 | return -ENOMEM; |
@@ -102,7 +104,7 @@ int snd_device_free(snd_card_t *card, void *device_data) | |||
102 | } | 104 | } |
103 | 105 | ||
104 | /** | 106 | /** |
105 | * snd_device_free - disconnect the device | 107 | * snd_device_disconnect - disconnect the device |
106 | * @card: the card instance | 108 | * @card: the card instance |
107 | * @device_data: the data pointer to disconnect | 109 | * @device_data: the data pointer to disconnect |
108 | * | 110 | * |
@@ -118,7 +120,7 @@ int snd_device_disconnect(snd_card_t *card, void *device_data) | |||
118 | { | 120 | { |
119 | struct list_head *list; | 121 | struct list_head *list; |
120 | snd_device_t *dev; | 122 | snd_device_t *dev; |
121 | 123 | ||
122 | snd_assert(card != NULL, return -ENXIO); | 124 | snd_assert(card != NULL, return -ENXIO); |
123 | snd_assert(device_data != NULL, return -ENXIO); | 125 | snd_assert(device_data != NULL, return -ENXIO); |
124 | list_for_each(list, &card->devices) { | 126 | list_for_each(list, &card->devices) { |
@@ -154,8 +156,9 @@ int snd_device_register(snd_card_t *card, void *device_data) | |||
154 | struct list_head *list; | 156 | struct list_head *list; |
155 | snd_device_t *dev; | 157 | snd_device_t *dev; |
156 | int err; | 158 | int err; |
157 | 159 | ||
158 | snd_assert(card != NULL && device_data != NULL, return -ENXIO); | 160 | snd_assert(card != NULL, return -ENXIO); |
161 | snd_assert(device_data != NULL, return -ENXIO); | ||
159 | list_for_each(list, &card->devices) { | 162 | list_for_each(list, &card->devices) { |
160 | dev = snd_device(list); | 163 | dev = snd_device(list); |
161 | if (dev->device_data != device_data) | 164 | if (dev->device_data != device_data) |
diff --git a/sound/core/info.c b/sound/core/info.c index 31faffe01cb0..7f8bdf7b0058 100644 --- a/sound/core/info.c +++ b/sound/core/info.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/vmalloc.h> | 24 | #include <linux/vmalloc.h> |
25 | #include <linux/time.h> | 25 | #include <linux/time.h> |
26 | #include <linux/smp_lock.h> | 26 | #include <linux/smp_lock.h> |
27 | #include <linux/string.h> | ||
27 | #include <sound/core.h> | 28 | #include <sound/core.h> |
28 | #include <sound/minors.h> | 29 | #include <sound/minors.h> |
29 | #include <sound/info.h> | 30 | #include <sound/info.h> |
@@ -701,7 +702,7 @@ int snd_info_get_line(snd_info_buffer_t * buffer, char *line, int len) | |||
701 | } | 702 | } |
702 | 703 | ||
703 | /** | 704 | /** |
704 | * snd_info_get_line - parse a string token | 705 | * snd_info_get_str - parse a string token |
705 | * @dest: the buffer to store the string token | 706 | * @dest: the buffer to store the string token |
706 | * @src: the original string | 707 | * @src: the original string |
707 | * @len: the max. length of token - 1 | 708 | * @len: the max. length of token - 1 |
@@ -754,7 +755,7 @@ static snd_info_entry_t *snd_info_create_entry(const char *name) | |||
754 | entry = kcalloc(1, sizeof(*entry), GFP_KERNEL); | 755 | entry = kcalloc(1, sizeof(*entry), GFP_KERNEL); |
755 | if (entry == NULL) | 756 | if (entry == NULL) |
756 | return NULL; | 757 | return NULL; |
757 | entry->name = snd_kmalloc_strdup(name, GFP_KERNEL); | 758 | entry->name = kstrdup(name, GFP_KERNEL); |
758 | if (entry->name == NULL) { | 759 | if (entry->name == NULL) { |
759 | kfree(entry); | 760 | kfree(entry); |
760 | return NULL; | 761 | return NULL; |
@@ -938,7 +939,8 @@ int snd_info_unregister(snd_info_entry_t * entry) | |||
938 | { | 939 | { |
939 | struct proc_dir_entry *root; | 940 | struct proc_dir_entry *root; |
940 | 941 | ||
941 | snd_assert(entry != NULL && entry->p != NULL, return -ENXIO); | 942 | snd_assert(entry != NULL, return -ENXIO); |
943 | snd_assert(entry->p != NULL, return -ENXIO); | ||
942 | root = entry->parent == NULL ? snd_proc_root : entry->parent->p; | 944 | root = entry->parent == NULL ? snd_proc_root : entry->parent->p; |
943 | snd_assert(root, return -ENXIO); | 945 | snd_assert(root, return -ENXIO); |
944 | down(&info_mutex); | 946 | down(&info_mutex); |
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index f9e4ce443454..12107968d402 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/time.h> | 24 | #include <linux/time.h> |
25 | #include <linux/string.h> | ||
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <sound/minors.h> | 27 | #include <sound/minors.h> |
27 | #include <sound/info.h> | 28 | #include <sound/info.h> |
@@ -51,7 +52,7 @@ int snd_oss_info_register(int dev, int num, char *string) | |||
51 | x = NULL; | 52 | x = NULL; |
52 | } | 53 | } |
53 | } else { | 54 | } else { |
54 | x = snd_kmalloc_strdup(string, GFP_KERNEL); | 55 | x = kstrdup(string, GFP_KERNEL); |
55 | if (x == NULL) { | 56 | if (x == NULL) { |
56 | up(&strings); | 57 | up(&strings); |
57 | return -ENOMEM; | 58 | return -ENOMEM; |
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 344a83fd7c2e..02132561c3f8 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
31 | #include <asm/uaccess.h> | ||
31 | #include <linux/dma-mapping.h> | 32 | #include <linux/dma-mapping.h> |
32 | #include <linux/moduleparam.h> | 33 | #include <linux/moduleparam.h> |
33 | #include <asm/semaphore.h> | 34 | #include <asm/semaphore.h> |
@@ -46,13 +47,6 @@ MODULE_LICENSE("GPL"); | |||
46 | #define SNDRV_CARDS 8 | 47 | #define SNDRV_CARDS 8 |
47 | #endif | 48 | #endif |
48 | 49 | ||
49 | /* FIXME: so far only some PCI devices have the preallocation table */ | ||
50 | #ifdef CONFIG_PCI | ||
51 | static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; | ||
52 | module_param_array(enable, bool, NULL, 0444); | ||
53 | MODULE_PARM_DESC(enable, "Enable cards to allocate buffers."); | ||
54 | #endif | ||
55 | |||
56 | /* | 50 | /* |
57 | */ | 51 | */ |
58 | 52 | ||
@@ -111,7 +105,8 @@ struct snd_mem_list { | |||
111 | */ | 105 | */ |
112 | 106 | ||
113 | static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size, | 107 | static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size, |
114 | dma_addr_t *dma_handle, int flags) | 108 | dma_addr_t *dma_handle, |
109 | unsigned int __nocast flags) | ||
115 | { | 110 | { |
116 | void *ret; | 111 | void *ret; |
117 | u64 dma_mask, coherent_dma_mask; | 112 | u64 dma_mask, coherent_dma_mask; |
@@ -451,9 +446,13 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id) | |||
451 | list_for_each(p, &mem_list_head) { | 446 | list_for_each(p, &mem_list_head) { |
452 | mem = list_entry(p, struct snd_mem_list, list); | 447 | mem = list_entry(p, struct snd_mem_list, list); |
453 | if (mem->id == id && | 448 | if (mem->id == id && |
454 | ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev))) { | 449 | (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL || |
450 | ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) { | ||
451 | struct device *dev = dmab->dev.dev; | ||
455 | list_del(p); | 452 | list_del(p); |
456 | *dmab = mem->buffer; | 453 | *dmab = mem->buffer; |
454 | if (dmab->dev.dev == NULL) | ||
455 | dmab->dev.dev = dev; | ||
457 | kfree(mem); | 456 | kfree(mem); |
458 | up(&list_mutex); | 457 | up(&list_mutex); |
459 | return dmab->bytes; | 458 | return dmab->bytes; |
@@ -508,91 +507,13 @@ static void free_all_reserved_pages(void) | |||
508 | } | 507 | } |
509 | 508 | ||
510 | 509 | ||
511 | |||
512 | /* | ||
513 | * allocation of buffers for pre-defined devices | ||
514 | */ | ||
515 | |||
516 | #ifdef CONFIG_PCI | ||
517 | /* FIXME: for pci only - other bus? */ | ||
518 | struct prealloc_dev { | ||
519 | unsigned short vendor; | ||
520 | unsigned short device; | ||
521 | unsigned long dma_mask; | ||
522 | unsigned int size; | ||
523 | unsigned int buffers; | ||
524 | }; | ||
525 | |||
526 | #define HAMMERFALL_BUFFER_SIZE (16*1024*4*(26+1)+0x10000) | ||
527 | |||
528 | static struct prealloc_dev prealloc_devices[] __initdata = { | ||
529 | { | ||
530 | /* hammerfall */ | ||
531 | .vendor = 0x10ee, | ||
532 | .device = 0x3fc4, | ||
533 | .dma_mask = 0xffffffff, | ||
534 | .size = HAMMERFALL_BUFFER_SIZE, | ||
535 | .buffers = 2 | ||
536 | }, | ||
537 | { | ||
538 | /* HDSP */ | ||
539 | .vendor = 0x10ee, | ||
540 | .device = 0x3fc5, | ||
541 | .dma_mask = 0xffffffff, | ||
542 | .size = HAMMERFALL_BUFFER_SIZE, | ||
543 | .buffers = 2 | ||
544 | }, | ||
545 | { }, /* terminator */ | ||
546 | }; | ||
547 | |||
548 | static void __init preallocate_cards(void) | ||
549 | { | ||
550 | struct pci_dev *pci = NULL; | ||
551 | int card; | ||
552 | |||
553 | card = 0; | ||
554 | |||
555 | while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) { | ||
556 | struct prealloc_dev *dev; | ||
557 | unsigned int i; | ||
558 | if (card >= SNDRV_CARDS) | ||
559 | break; | ||
560 | for (dev = prealloc_devices; dev->vendor; dev++) { | ||
561 | if (dev->vendor == pci->vendor && dev->device == pci->device) | ||
562 | break; | ||
563 | } | ||
564 | if (! dev->vendor) | ||
565 | continue; | ||
566 | if (! enable[card++]) { | ||
567 | printk(KERN_DEBUG "snd-page-alloc: skipping card %d, device %04x:%04x\n", card, pci->vendor, pci->device); | ||
568 | continue; | ||
569 | } | ||
570 | |||
571 | if (pci_set_dma_mask(pci, dev->dma_mask) < 0 || | ||
572 | pci_set_consistent_dma_mask(pci, dev->dma_mask) < 0) { | ||
573 | printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", dev->dma_mask, dev->vendor, dev->device); | ||
574 | continue; | ||
575 | } | ||
576 | for (i = 0; i < dev->buffers; i++) { | ||
577 | struct snd_dma_buffer dmab; | ||
578 | memset(&dmab, 0, sizeof(dmab)); | ||
579 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | ||
580 | dev->size, &dmab) < 0) | ||
581 | printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size); | ||
582 | else | ||
583 | snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci)); | ||
584 | } | ||
585 | } | ||
586 | } | ||
587 | #else | ||
588 | #define preallocate_cards() /* NOP */ | ||
589 | #endif | ||
590 | |||
591 | |||
592 | #ifdef CONFIG_PROC_FS | 510 | #ifdef CONFIG_PROC_FS |
593 | /* | 511 | /* |
594 | * proc file interface | 512 | * proc file interface |
595 | */ | 513 | */ |
514 | #define SND_MEM_PROC_FILE "driver/snd-page-alloc" | ||
515 | struct proc_dir_entry *snd_mem_proc; | ||
516 | |||
596 | static int snd_mem_proc_read(char *page, char **start, off_t off, | 517 | static int snd_mem_proc_read(char *page, char **start, off_t off, |
597 | int count, int *eof, void *data) | 518 | int count, int *eof, void *data) |
598 | { | 519 | { |
@@ -621,6 +542,97 @@ static int snd_mem_proc_read(char *page, char **start, off_t off, | |||
621 | up(&list_mutex); | 542 | up(&list_mutex); |
622 | return len; | 543 | return len; |
623 | } | 544 | } |
545 | |||
546 | /* FIXME: for pci only - other bus? */ | ||
547 | #ifdef CONFIG_PCI | ||
548 | #define gettoken(bufp) strsep(bufp, " \t\n") | ||
549 | |||
550 | static int snd_mem_proc_write(struct file *file, const char __user *buffer, | ||
551 | unsigned long count, void *data) | ||
552 | { | ||
553 | char buf[128]; | ||
554 | char *token, *p; | ||
555 | |||
556 | if (count > ARRAY_SIZE(buf) - 1) | ||
557 | count = ARRAY_SIZE(buf) - 1; | ||
558 | if (copy_from_user(buf, buffer, count)) | ||
559 | return -EFAULT; | ||
560 | buf[ARRAY_SIZE(buf) - 1] = '\0'; | ||
561 | |||
562 | p = buf; | ||
563 | token = gettoken(&p); | ||
564 | if (! token || *token == '#') | ||
565 | return (int)count; | ||
566 | if (strcmp(token, "add") == 0) { | ||
567 | char *endp; | ||
568 | int vendor, device, size, buffers; | ||
569 | long mask; | ||
570 | int i, alloced; | ||
571 | struct pci_dev *pci; | ||
572 | |||
573 | if ((token = gettoken(&p)) == NULL || | ||
574 | (vendor = simple_strtol(token, NULL, 0)) <= 0 || | ||
575 | (token = gettoken(&p)) == NULL || | ||
576 | (device = simple_strtol(token, NULL, 0)) <= 0 || | ||
577 | (token = gettoken(&p)) == NULL || | ||
578 | (mask = simple_strtol(token, NULL, 0)) < 0 || | ||
579 | (token = gettoken(&p)) == NULL || | ||
580 | (size = memparse(token, &endp)) < 64*1024 || | ||
581 | size > 16*1024*1024 /* too big */ || | ||
582 | (token = gettoken(&p)) == NULL || | ||
583 | (buffers = simple_strtol(token, NULL, 0)) <= 0 || | ||
584 | buffers > 4) { | ||
585 | printk(KERN_ERR "snd-page-alloc: invalid proc write format\n"); | ||
586 | return (int)count; | ||
587 | } | ||
588 | vendor &= 0xffff; | ||
589 | device &= 0xffff; | ||
590 | |||
591 | alloced = 0; | ||
592 | pci = NULL; | ||
593 | while ((pci = pci_find_device(vendor, device, pci)) != NULL) { | ||
594 | if (mask > 0 && mask < 0xffffffff) { | ||
595 | if (pci_set_dma_mask(pci, mask) < 0 || | ||
596 | pci_set_consistent_dma_mask(pci, mask) < 0) { | ||
597 | printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device); | ||
598 | return (int)count; | ||
599 | } | ||
600 | } | ||
601 | for (i = 0; i < buffers; i++) { | ||
602 | struct snd_dma_buffer dmab; | ||
603 | memset(&dmab, 0, sizeof(dmab)); | ||
604 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | ||
605 | size, &dmab) < 0) { | ||
606 | printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size); | ||
607 | return (int)count; | ||
608 | } | ||
609 | snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci)); | ||
610 | } | ||
611 | alloced++; | ||
612 | } | ||
613 | if (! alloced) { | ||
614 | for (i = 0; i < buffers; i++) { | ||
615 | struct snd_dma_buffer dmab; | ||
616 | memset(&dmab, 0, sizeof(dmab)); | ||
617 | /* FIXME: We can allocate only in ZONE_DMA | ||
618 | * without a device pointer! | ||
619 | */ | ||
620 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL, | ||
621 | size, &dmab) < 0) { | ||
622 | printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size); | ||
623 | break; | ||
624 | } | ||
625 | snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device)); | ||
626 | } | ||
627 | } | ||
628 | } else if (strcmp(token, "erase") == 0) | ||
629 | /* FIXME: need for releasing each buffer chunk? */ | ||
630 | free_all_reserved_pages(); | ||
631 | else | ||
632 | printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n"); | ||
633 | return (int)count; | ||
634 | } | ||
635 | #endif /* CONFIG_PCI */ | ||
624 | #endif /* CONFIG_PROC_FS */ | 636 | #endif /* CONFIG_PROC_FS */ |
625 | 637 | ||
626 | /* | 638 | /* |
@@ -630,15 +642,21 @@ static int snd_mem_proc_read(char *page, char **start, off_t off, | |||
630 | static int __init snd_mem_init(void) | 642 | static int __init snd_mem_init(void) |
631 | { | 643 | { |
632 | #ifdef CONFIG_PROC_FS | 644 | #ifdef CONFIG_PROC_FS |
633 | create_proc_read_entry("driver/snd-page-alloc", 0, NULL, snd_mem_proc_read, NULL); | 645 | snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL); |
646 | if (snd_mem_proc) { | ||
647 | snd_mem_proc->read_proc = snd_mem_proc_read; | ||
648 | #ifdef CONFIG_PCI | ||
649 | snd_mem_proc->write_proc = snd_mem_proc_write; | ||
650 | #endif | ||
651 | } | ||
634 | #endif | 652 | #endif |
635 | preallocate_cards(); | ||
636 | return 0; | 653 | return 0; |
637 | } | 654 | } |
638 | 655 | ||
639 | static void __exit snd_mem_exit(void) | 656 | static void __exit snd_mem_exit(void) |
640 | { | 657 | { |
641 | remove_proc_entry("driver/snd-page-alloc", NULL); | 658 | if (snd_mem_proc) |
659 | remove_proc_entry(SND_MEM_PROC_FILE, NULL); | ||
642 | free_all_reserved_pages(); | 660 | free_all_reserved_pages(); |
643 | if (snd_allocated_pages > 0) | 661 | if (snd_allocated_pages > 0) |
644 | printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages); | 662 | printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages); |
diff --git a/sound/core/memory.c b/sound/core/memory.c index 20860fec9364..f6895577bf86 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c | |||
@@ -89,7 +89,7 @@ void snd_memory_done(void) | |||
89 | } | 89 | } |
90 | } | 90 | } |
91 | 91 | ||
92 | static void *__snd_kmalloc(size_t size, int flags, void *caller) | 92 | static void *__snd_kmalloc(size_t size, unsigned int __nocast flags, void *caller) |
93 | { | 93 | { |
94 | unsigned long cpu_flags; | 94 | unsigned long cpu_flags; |
95 | struct snd_alloc_track *t; | 95 | struct snd_alloc_track *t; |
@@ -111,12 +111,12 @@ static void *__snd_kmalloc(size_t size, int flags, void *caller) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | #define _snd_kmalloc(size, flags) __snd_kmalloc((size), (flags), __builtin_return_address(0)); | 113 | #define _snd_kmalloc(size, flags) __snd_kmalloc((size), (flags), __builtin_return_address(0)); |
114 | void *snd_hidden_kmalloc(size_t size, int flags) | 114 | void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags) |
115 | { | 115 | { |
116 | return _snd_kmalloc(size, flags); | 116 | return _snd_kmalloc(size, flags); |
117 | } | 117 | } |
118 | 118 | ||
119 | void *snd_hidden_kcalloc(size_t n, size_t size, int flags) | 119 | void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags) |
120 | { | 120 | { |
121 | void *ret = NULL; | 121 | void *ret = NULL; |
122 | if (n != 0 && size > INT_MAX / n) | 122 | if (n != 0 && size > INT_MAX / n) |
@@ -184,6 +184,20 @@ void snd_hidden_vfree(void *obj) | |||
184 | snd_wrapper_vfree(obj); | 184 | snd_wrapper_vfree(obj); |
185 | } | 185 | } |
186 | 186 | ||
187 | char *snd_hidden_kstrdup(const char *s, unsigned int __nocast flags) | ||
188 | { | ||
189 | int len; | ||
190 | char *buf; | ||
191 | |||
192 | if (!s) return NULL; | ||
193 | |||
194 | len = strlen(s) + 1; | ||
195 | buf = _snd_kmalloc(len, flags); | ||
196 | if (buf) | ||
197 | memcpy(buf, s, len); | ||
198 | return buf; | ||
199 | } | ||
200 | |||
187 | static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) | 201 | static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer) |
188 | { | 202 | { |
189 | snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc); | 203 | snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc); |
@@ -214,36 +228,9 @@ int __exit snd_memory_info_done(void) | |||
214 | return 0; | 228 | return 0; |
215 | } | 229 | } |
216 | 230 | ||
217 | #else | ||
218 | |||
219 | #define _snd_kmalloc kmalloc | ||
220 | |||
221 | #endif /* CONFIG_SND_DEBUG_MEMORY */ | 231 | #endif /* CONFIG_SND_DEBUG_MEMORY */ |
222 | 232 | ||
223 | /** | 233 | /** |
224 | * snd_kmalloc_strdup - copy the string | ||
225 | * @string: the original string | ||
226 | * @flags: allocation conditions, GFP_XXX | ||
227 | * | ||
228 | * Allocates a memory chunk via kmalloc() and copies the string to it. | ||
229 | * | ||
230 | * Returns the pointer, or NULL if no enoguh memory. | ||
231 | */ | ||
232 | char *snd_kmalloc_strdup(const char *string, int flags) | ||
233 | { | ||
234 | size_t len; | ||
235 | char *ptr; | ||
236 | |||
237 | if (!string) | ||
238 | return NULL; | ||
239 | len = strlen(string) + 1; | ||
240 | ptr = _snd_kmalloc(len, flags); | ||
241 | if (ptr) | ||
242 | memcpy(ptr, string, len); | ||
243 | return ptr; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * copy_to_user_fromio - copy data from mmio-space to user-space | 234 | * copy_to_user_fromio - copy data from mmio-space to user-space |
248 | * @dst: the destination pointer on user-space | 235 | * @dst: the destination pointer on user-space |
249 | * @src: the source pointer on mmio | 236 | * @src: the source pointer on mmio |
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 98ed9a9f0da6..98fc0766f885 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/smp_lock.h> | 24 | #include <linux/smp_lock.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/time.h> | 26 | #include <linux/time.h> |
27 | #include <linux/string.h> | ||
27 | #include <sound/core.h> | 28 | #include <sound/core.h> |
28 | #include <sound/minors.h> | 29 | #include <sound/minors.h> |
29 | #include <sound/control.h> | 30 | #include <sound/control.h> |
@@ -1137,7 +1138,7 @@ static void snd_mixer_oss_proc_write(snd_info_entry_t *entry, | |||
1137 | goto __unlock; | 1138 | goto __unlock; |
1138 | } | 1139 | } |
1139 | tbl->oss_id = ch; | 1140 | tbl->oss_id = ch; |
1140 | tbl->name = snd_kmalloc_strdup(str, GFP_KERNEL); | 1141 | tbl->name = kstrdup(str, GFP_KERNEL); |
1141 | if (! tbl->name) { | 1142 | if (! tbl->name) { |
1142 | kfree(tbl); | 1143 | kfree(tbl); |
1143 | goto __unlock; | 1144 | goto __unlock; |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 1a805020f57a..de7444c586f9 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/time.h> | 33 | #include <linux/time.h> |
34 | #include <linux/vmalloc.h> | 34 | #include <linux/vmalloc.h> |
35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
36 | #include <linux/string.h> | ||
36 | #include <sound/core.h> | 37 | #include <sound/core.h> |
37 | #include <sound/minors.h> | 38 | #include <sound/minors.h> |
38 | #include <sound/pcm.h> | 39 | #include <sound/pcm.h> |
@@ -125,17 +126,26 @@ int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin) | |||
125 | static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames) | 126 | static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames) |
126 | { | 127 | { |
127 | snd_pcm_runtime_t *runtime = substream->runtime; | 128 | snd_pcm_runtime_t *runtime = substream->runtime; |
128 | snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream); | 129 | long buffer_size = snd_pcm_lib_buffer_bytes(substream); |
129 | frames = frames_to_bytes(runtime, frames); | 130 | long bytes = frames_to_bytes(runtime, frames); |
130 | if (buffer_size == runtime->oss.buffer_bytes) | 131 | if (buffer_size == runtime->oss.buffer_bytes) |
131 | return frames; | 132 | return bytes; |
132 | return (runtime->oss.buffer_bytes * frames) / buffer_size; | 133 | #if BITS_PER_LONG >= 64 |
134 | return runtime->oss.buffer_bytes * bytes / buffer_size; | ||
135 | #else | ||
136 | { | ||
137 | u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes; | ||
138 | u32 rem; | ||
139 | div64_32(&bsize, buffer_size, &rem); | ||
140 | return (long)bsize; | ||
141 | } | ||
142 | #endif | ||
133 | } | 143 | } |
134 | 144 | ||
135 | static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes) | 145 | static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes) |
136 | { | 146 | { |
137 | snd_pcm_runtime_t *runtime = substream->runtime; | 147 | snd_pcm_runtime_t *runtime = substream->runtime; |
138 | snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream); | 148 | long buffer_size = snd_pcm_lib_buffer_bytes(substream); |
139 | if (buffer_size == runtime->oss.buffer_bytes) | 149 | if (buffer_size == runtime->oss.buffer_bytes) |
140 | return bytes_to_frames(runtime, bytes); | 150 | return bytes_to_frames(runtime, bytes); |
141 | return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); | 151 | return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); |
@@ -464,7 +474,8 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) | |||
464 | sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; | 474 | sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; |
465 | sw_params->period_step = 1; | 475 | sw_params->period_step = 1; |
466 | sw_params->sleep_min = 0; | 476 | sw_params->sleep_min = 0; |
467 | sw_params->avail_min = 1; | 477 | sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? |
478 | 1 : runtime->period_size; | ||
468 | sw_params->xfer_align = 1; | 479 | sw_params->xfer_align = 1; |
469 | if (atomic_read(&runtime->mmap_count) || | 480 | if (atomic_read(&runtime->mmap_count) || |
470 | (substream->oss.setup && substream->oss.setup->nosilence)) { | 481 | (substream->oss.setup && substream->oss.setup->nosilence)) { |
@@ -1527,12 +1538,15 @@ static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, str | |||
1527 | snd_pcm_oss_simulate_fill(substream, delay); | 1538 | snd_pcm_oss_simulate_fill(substream, delay); |
1528 | info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX; | 1539 | info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX; |
1529 | } else { | 1540 | } else { |
1530 | delay = snd_pcm_oss_bytes(substream, delay) + fixup; | 1541 | delay = snd_pcm_oss_bytes(substream, delay); |
1531 | info.blocks = delay / runtime->oss.period_bytes; | 1542 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
1532 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | 1543 | info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes; |
1533 | info.bytes = (runtime->oss.bytes - delay) & INT_MAX; | 1544 | info.bytes = (runtime->oss.bytes - delay) & INT_MAX; |
1534 | else | 1545 | } else { |
1546 | delay += fixup; | ||
1547 | info.blocks = delay / runtime->oss.period_bytes; | ||
1535 | info.bytes = (runtime->oss.bytes + delay) & INT_MAX; | 1548 | info.bytes = (runtime->oss.bytes + delay) & INT_MAX; |
1549 | } | ||
1536 | } | 1550 | } |
1537 | if (copy_to_user(_info, &info, sizeof(info))) | 1551 | if (copy_to_user(_info, &info, sizeof(info))) |
1538 | return -EFAULT; | 1552 | return -EFAULT; |
@@ -2347,7 +2361,7 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry, | |||
2347 | for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next); | 2361 | for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next); |
2348 | setup1->next = setup; | 2362 | setup1->next = setup; |
2349 | } | 2363 | } |
2350 | template.task_name = snd_kmalloc_strdup(task_name, GFP_KERNEL); | 2364 | template.task_name = kstrdup(task_name, GFP_KERNEL); |
2351 | } else { | 2365 | } else { |
2352 | buffer->error = -ENOMEM; | 2366 | buffer->error = -ENOMEM; |
2353 | } | 2367 | } |
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 6bb31009f0b4..6430410c6c04 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c | |||
@@ -663,10 +663,7 @@ static int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug, | |||
663 | bitset_t *dstmask = bs; | 663 | bitset_t *dstmask = bs; |
664 | int err; | 664 | int err; |
665 | bitset_one(dstmask, schannels); | 665 | bitset_one(dstmask, schannels); |
666 | if (plugin == NULL) { | 666 | |
667 | bitset_and(client_vmask, dstmask, schannels); | ||
668 | return 0; | ||
669 | } | ||
670 | while (1) { | 667 | while (1) { |
671 | err = plugin->src_channels_mask(plugin, dstmask, &srcmask); | 668 | err = plugin->src_channels_mask(plugin, dstmask, &srcmask); |
672 | if (err < 0) | 669 | if (err < 0) |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 8d94325529a8..9f4c9209b271 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -451,6 +451,7 @@ static int snd_pcm_stream_proc_init(snd_pcm_str_t *pstr) | |||
451 | entry->c.text.read = snd_pcm_xrun_debug_read; | 451 | entry->c.text.read = snd_pcm_xrun_debug_read; |
452 | entry->c.text.write_size = 64; | 452 | entry->c.text.write_size = 64; |
453 | entry->c.text.write = snd_pcm_xrun_debug_write; | 453 | entry->c.text.write = snd_pcm_xrun_debug_write; |
454 | entry->mode |= S_IWUSR; | ||
454 | entry->private_data = pstr; | 455 | entry->private_data = pstr; |
455 | if (snd_info_register(entry) < 0) { | 456 | if (snd_info_register(entry) < 0) { |
456 | snd_info_free_entry(entry); | 457 | snd_info_free_entry(entry); |
@@ -1048,7 +1049,6 @@ EXPORT_SYMBOL(snd_pcm_release_substream); | |||
1048 | EXPORT_SYMBOL(snd_pcm_format_name); | 1049 | EXPORT_SYMBOL(snd_pcm_format_name); |
1049 | /* pcm_native.c */ | 1050 | /* pcm_native.c */ |
1050 | EXPORT_SYMBOL(snd_pcm_link_rwlock); | 1051 | EXPORT_SYMBOL(snd_pcm_link_rwlock); |
1051 | EXPORT_SYMBOL(snd_pcm_start); | ||
1052 | #ifdef CONFIG_PM | 1052 | #ifdef CONFIG_PM |
1053 | EXPORT_SYMBOL(snd_pcm_suspend); | 1053 | EXPORT_SYMBOL(snd_pcm_suspend); |
1054 | EXPORT_SYMBOL(snd_pcm_suspend_all); | 1054 | EXPORT_SYMBOL(snd_pcm_suspend_all); |
@@ -1068,6 +1068,7 @@ EXPORT_SYMBOL(snd_pcm_format_little_endian); | |||
1068 | EXPORT_SYMBOL(snd_pcm_format_big_endian); | 1068 | EXPORT_SYMBOL(snd_pcm_format_big_endian); |
1069 | EXPORT_SYMBOL(snd_pcm_format_width); | 1069 | EXPORT_SYMBOL(snd_pcm_format_width); |
1070 | EXPORT_SYMBOL(snd_pcm_format_physical_width); | 1070 | EXPORT_SYMBOL(snd_pcm_format_physical_width); |
1071 | EXPORT_SYMBOL(snd_pcm_format_size); | ||
1071 | EXPORT_SYMBOL(snd_pcm_format_silence_64); | 1072 | EXPORT_SYMBOL(snd_pcm_format_silence_64); |
1072 | EXPORT_SYMBOL(snd_pcm_format_set_silence); | 1073 | EXPORT_SYMBOL(snd_pcm_format_set_silence); |
1073 | EXPORT_SYMBOL(snd_pcm_build_linear_format); | 1074 | EXPORT_SYMBOL(snd_pcm_build_linear_format); |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 151fd99ca2c9..c5bfd0918cff 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -1143,7 +1143,8 @@ int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime, | |||
1143 | #define INT_MIN ((int)((unsigned int)INT_MAX+1)) | 1143 | #define INT_MIN ((int)((unsigned int)INT_MAX+1)) |
1144 | #endif | 1144 | #endif |
1145 | 1145 | ||
1146 | void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var) | 1146 | static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, |
1147 | snd_pcm_hw_param_t var) | ||
1147 | { | 1148 | { |
1148 | if (hw_is_mask(var)) { | 1149 | if (hw_is_mask(var)) { |
1149 | snd_mask_any(hw_param_mask(params, var)); | 1150 | snd_mask_any(hw_param_mask(params, var)); |
@@ -1160,6 +1161,7 @@ void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var) | |||
1160 | snd_BUG(); | 1161 | snd_BUG(); |
1161 | } | 1162 | } |
1162 | 1163 | ||
1164 | #if 0 | ||
1163 | /** | 1165 | /** |
1164 | * snd_pcm_hw_param_any | 1166 | * snd_pcm_hw_param_any |
1165 | */ | 1167 | */ |
@@ -1169,6 +1171,7 @@ int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, | |||
1169 | _snd_pcm_hw_param_any(params, var); | 1171 | _snd_pcm_hw_param_any(params, var); |
1170 | return snd_pcm_hw_refine(pcm, params); | 1172 | return snd_pcm_hw_refine(pcm, params); |
1171 | } | 1173 | } |
1174 | #endif /* 0 */ | ||
1172 | 1175 | ||
1173 | void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params) | 1176 | void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params) |
1174 | { | 1177 | { |
@@ -1181,6 +1184,7 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params) | |||
1181 | params->info = ~0U; | 1184 | params->info = ~0U; |
1182 | } | 1185 | } |
1183 | 1186 | ||
1187 | #if 0 | ||
1184 | /** | 1188 | /** |
1185 | * snd_pcm_hw_params_any | 1189 | * snd_pcm_hw_params_any |
1186 | * | 1190 | * |
@@ -1191,6 +1195,7 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
1191 | _snd_pcm_hw_params_any(params); | 1195 | _snd_pcm_hw_params_any(params); |
1192 | return snd_pcm_hw_refine(pcm, params); | 1196 | return snd_pcm_hw_refine(pcm, params); |
1193 | } | 1197 | } |
1198 | #endif /* 0 */ | ||
1194 | 1199 | ||
1195 | /** | 1200 | /** |
1196 | * snd_pcm_hw_param_value | 1201 | * snd_pcm_hw_param_value |
@@ -1198,8 +1203,8 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) | |||
1198 | * Return the value for field PAR if it's fixed in configuration space | 1203 | * Return the value for field PAR if it's fixed in configuration space |
1199 | * defined by PARAMS. Return -EINVAL otherwise | 1204 | * defined by PARAMS. Return -EINVAL otherwise |
1200 | */ | 1205 | */ |
1201 | int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params, | 1206 | static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params, |
1202 | snd_pcm_hw_param_t var, int *dir) | 1207 | snd_pcm_hw_param_t var, int *dir) |
1203 | { | 1208 | { |
1204 | if (hw_is_mask(var)) { | 1209 | if (hw_is_mask(var)) { |
1205 | const snd_mask_t *mask = hw_param_mask_c(params, var); | 1210 | const snd_mask_t *mask = hw_param_mask_c(params, var); |
@@ -1296,6 +1301,7 @@ int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params, | |||
1296 | return changed; | 1301 | return changed; |
1297 | } | 1302 | } |
1298 | 1303 | ||
1304 | #if 0 | ||
1299 | /** | 1305 | /** |
1300 | * snd_pcm_hw_param_setinteger | 1306 | * snd_pcm_hw_param_setinteger |
1301 | * | 1307 | * |
@@ -1317,9 +1323,10 @@ int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm, | |||
1317 | } | 1323 | } |
1318 | return 0; | 1324 | return 0; |
1319 | } | 1325 | } |
1326 | #endif /* 0 */ | ||
1320 | 1327 | ||
1321 | int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, | 1328 | static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, |
1322 | snd_pcm_hw_param_t var) | 1329 | snd_pcm_hw_param_t var) |
1323 | { | 1330 | { |
1324 | int changed; | 1331 | int changed; |
1325 | if (hw_is_mask(var)) | 1332 | if (hw_is_mask(var)) |
@@ -1345,9 +1352,9 @@ int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params, | |||
1345 | * values > minimum. Reduce configuration space accordingly. | 1352 | * values > minimum. Reduce configuration space accordingly. |
1346 | * Return the minimum. | 1353 | * Return the minimum. |
1347 | */ | 1354 | */ |
1348 | int snd_pcm_hw_param_first(snd_pcm_t *pcm, | 1355 | static int snd_pcm_hw_param_first(snd_pcm_t *pcm, |
1349 | snd_pcm_hw_params_t *params, | 1356 | snd_pcm_hw_params_t *params, |
1350 | snd_pcm_hw_param_t var, int *dir) | 1357 | snd_pcm_hw_param_t var, int *dir) |
1351 | { | 1358 | { |
1352 | int changed = _snd_pcm_hw_param_first(params, var); | 1359 | int changed = _snd_pcm_hw_param_first(params, var); |
1353 | if (changed < 0) | 1360 | if (changed < 0) |
@@ -1359,8 +1366,8 @@ int snd_pcm_hw_param_first(snd_pcm_t *pcm, | |||
1359 | return snd_pcm_hw_param_value(params, var, dir); | 1366 | return snd_pcm_hw_param_value(params, var, dir); |
1360 | } | 1367 | } |
1361 | 1368 | ||
1362 | int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, | 1369 | static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, |
1363 | snd_pcm_hw_param_t var) | 1370 | snd_pcm_hw_param_t var) |
1364 | { | 1371 | { |
1365 | int changed; | 1372 | int changed; |
1366 | if (hw_is_mask(var)) | 1373 | if (hw_is_mask(var)) |
@@ -1386,9 +1393,9 @@ int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params, | |||
1386 | * values < maximum. Reduce configuration space accordingly. | 1393 | * values < maximum. Reduce configuration space accordingly. |
1387 | * Return the maximum. | 1394 | * Return the maximum. |
1388 | */ | 1395 | */ |
1389 | int snd_pcm_hw_param_last(snd_pcm_t *pcm, | 1396 | static int snd_pcm_hw_param_last(snd_pcm_t *pcm, |
1390 | snd_pcm_hw_params_t *params, | 1397 | snd_pcm_hw_params_t *params, |
1391 | snd_pcm_hw_param_t var, int *dir) | 1398 | snd_pcm_hw_param_t var, int *dir) |
1392 | { | 1399 | { |
1393 | int changed = _snd_pcm_hw_param_last(params, var); | 1400 | int changed = _snd_pcm_hw_param_last(params, var); |
1394 | if (changed < 0) | 1401 | if (changed < 0) |
@@ -1437,8 +1444,9 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params, | |||
1437 | * values < VAL. Reduce configuration space accordingly. | 1444 | * values < VAL. Reduce configuration space accordingly. |
1438 | * Return new minimum or -EINVAL if the configuration space is empty | 1445 | * Return new minimum or -EINVAL if the configuration space is empty |
1439 | */ | 1446 | */ |
1440 | int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, | 1447 | static int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, |
1441 | snd_pcm_hw_param_t var, unsigned int val, int *dir) | 1448 | snd_pcm_hw_param_t var, unsigned int val, |
1449 | int *dir) | ||
1442 | { | 1450 | { |
1443 | int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0); | 1451 | int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0); |
1444 | if (changed < 0) | 1452 | if (changed < 0) |
@@ -1451,8 +1459,9 @@ int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, | |||
1451 | return snd_pcm_hw_param_value_min(params, var, dir); | 1459 | return snd_pcm_hw_param_value_min(params, var, dir); |
1452 | } | 1460 | } |
1453 | 1461 | ||
1454 | int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, | 1462 | static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, |
1455 | snd_pcm_hw_param_t var, unsigned int val, int dir) | 1463 | snd_pcm_hw_param_t var, unsigned int val, |
1464 | int dir) | ||
1456 | { | 1465 | { |
1457 | int changed; | 1466 | int changed; |
1458 | int open = 0; | 1467 | int open = 0; |
@@ -1490,8 +1499,9 @@ int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params, | |||
1490 | * values >= VAL + 1. Reduce configuration space accordingly. | 1499 | * values >= VAL + 1. Reduce configuration space accordingly. |
1491 | * Return new maximum or -EINVAL if the configuration space is empty | 1500 | * Return new maximum or -EINVAL if the configuration space is empty |
1492 | */ | 1501 | */ |
1493 | int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, | 1502 | static int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, |
1494 | snd_pcm_hw_param_t var, unsigned int val, int *dir) | 1503 | snd_pcm_hw_param_t var, unsigned int val, |
1504 | int *dir) | ||
1495 | { | 1505 | { |
1496 | int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0); | 1506 | int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0); |
1497 | if (changed < 0) | 1507 | if (changed < 0) |
@@ -2564,9 +2574,6 @@ snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream, | |||
2564 | EXPORT_SYMBOL(snd_interval_refine); | 2574 | EXPORT_SYMBOL(snd_interval_refine); |
2565 | EXPORT_SYMBOL(snd_interval_list); | 2575 | EXPORT_SYMBOL(snd_interval_list); |
2566 | EXPORT_SYMBOL(snd_interval_ratnum); | 2576 | EXPORT_SYMBOL(snd_interval_ratnum); |
2567 | EXPORT_SYMBOL(snd_interval_muldivk); | ||
2568 | EXPORT_SYMBOL(snd_interval_mulkdiv); | ||
2569 | EXPORT_SYMBOL(snd_interval_div); | ||
2570 | EXPORT_SYMBOL(_snd_pcm_hw_params_any); | 2577 | EXPORT_SYMBOL(_snd_pcm_hw_params_any); |
2571 | EXPORT_SYMBOL(_snd_pcm_hw_param_min); | 2578 | EXPORT_SYMBOL(_snd_pcm_hw_param_min); |
2572 | EXPORT_SYMBOL(_snd_pcm_hw_param_set); | 2579 | EXPORT_SYMBOL(_snd_pcm_hw_param_set); |
@@ -2580,7 +2587,6 @@ EXPORT_SYMBOL(snd_pcm_hw_param_last); | |||
2580 | EXPORT_SYMBOL(snd_pcm_hw_param_near); | 2587 | EXPORT_SYMBOL(snd_pcm_hw_param_near); |
2581 | EXPORT_SYMBOL(snd_pcm_hw_param_set); | 2588 | EXPORT_SYMBOL(snd_pcm_hw_param_set); |
2582 | EXPORT_SYMBOL(snd_pcm_hw_refine); | 2589 | EXPORT_SYMBOL(snd_pcm_hw_refine); |
2583 | EXPORT_SYMBOL(snd_pcm_hw_params); | ||
2584 | EXPORT_SYMBOL(snd_pcm_hw_constraints_init); | 2590 | EXPORT_SYMBOL(snd_pcm_hw_constraints_init); |
2585 | EXPORT_SYMBOL(snd_pcm_hw_constraints_complete); | 2591 | EXPORT_SYMBOL(snd_pcm_hw_constraints_complete); |
2586 | EXPORT_SYMBOL(snd_pcm_hw_constraint_list); | 2592 | EXPORT_SYMBOL(snd_pcm_hw_constraint_list); |
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index f1d5f7a6ee0c..9a174fb96565 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c | |||
@@ -204,6 +204,7 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream, | |||
204 | entry->c.text.read = snd_pcm_lib_preallocate_proc_read; | 204 | entry->c.text.read = snd_pcm_lib_preallocate_proc_read; |
205 | entry->c.text.write_size = 64; | 205 | entry->c.text.write_size = 64; |
206 | entry->c.text.write = snd_pcm_lib_preallocate_proc_write; | 206 | entry->c.text.write = snd_pcm_lib_preallocate_proc_write; |
207 | entry->mode |= S_IWUSR; | ||
207 | entry->private_data = substream; | 208 | entry->private_data = substream; |
208 | if (snd_info_register(entry) < 0) { | 209 | if (snd_info_register(entry) < 0) { |
209 | snd_info_free_entry(entry); | 210 | snd_info_free_entry(entry); |
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 422b8db14154..1453743e4da0 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c | |||
@@ -270,22 +270,6 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format) | |||
270 | } | 270 | } |
271 | 271 | ||
272 | /** | 272 | /** |
273 | * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian | ||
274 | * @format: the format to check | ||
275 | * | ||
276 | * Returns 1 if the given PCM format is CPU-endian, 0 if | ||
277 | * opposite, or a negative error code if endian not specified. | ||
278 | */ | ||
279 | int snd_pcm_format_cpu_endian(snd_pcm_format_t format) | ||
280 | { | ||
281 | #ifdef SNDRV_LITTLE_ENDIAN | ||
282 | return snd_pcm_format_little_endian(format); | ||
283 | #else | ||
284 | return snd_pcm_format_big_endian(format); | ||
285 | #endif | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * snd_pcm_format_width - return the bit-width of the format | 273 | * snd_pcm_format_width - return the bit-width of the format |
290 | * @format: the format to check | 274 | * @format: the format to check |
291 | * | 275 | * |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index cad9bbde9986..10c2c9832649 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -337,8 +337,8 @@ out: | |||
337 | return err; | 337 | return err; |
338 | } | 338 | } |
339 | 339 | ||
340 | int snd_pcm_hw_params(snd_pcm_substream_t *substream, | 340 | static int snd_pcm_hw_params(snd_pcm_substream_t *substream, |
341 | snd_pcm_hw_params_t *params) | 341 | snd_pcm_hw_params_t *params) |
342 | { | 342 | { |
343 | snd_pcm_runtime_t *runtime; | 343 | snd_pcm_runtime_t *runtime; |
344 | int err; | 344 | int err; |
@@ -1368,43 +1368,32 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) | |||
1368 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 1368 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
1369 | return -EBADFD; | 1369 | return -EBADFD; |
1370 | 1370 | ||
1371 | down_read(&snd_pcm_link_rwsem); | ||
1372 | snd_power_lock(card); | 1371 | snd_power_lock(card); |
1373 | if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { | 1372 | if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { |
1374 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); | 1373 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile); |
1375 | if (result < 0) | 1374 | if (result < 0) { |
1376 | goto _unlock; | 1375 | snd_power_unlock(card); |
1376 | return result; | ||
1377 | } | ||
1377 | } | 1378 | } |
1378 | 1379 | ||
1379 | /* allocate temporary record for drain sync */ | 1380 | /* allocate temporary record for drain sync */ |
1381 | down_read(&snd_pcm_link_rwsem); | ||
1380 | if (snd_pcm_stream_linked(substream)) { | 1382 | if (snd_pcm_stream_linked(substream)) { |
1381 | drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL); | 1383 | drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL); |
1382 | if (! drec) { | 1384 | if (! drec) { |
1383 | result = -ENOMEM; | 1385 | up_read(&snd_pcm_link_rwsem); |
1384 | goto _unlock; | 1386 | snd_power_unlock(card); |
1387 | return -ENOMEM; | ||
1385 | } | 1388 | } |
1386 | } else | 1389 | } else |
1387 | drec = &drec_tmp; | 1390 | drec = &drec_tmp; |
1388 | 1391 | ||
1389 | snd_pcm_stream_lock_irq(substream); | 1392 | /* count only playback streams */ |
1390 | /* resume pause */ | ||
1391 | if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) | ||
1392 | snd_pcm_pause(substream, 0); | ||
1393 | |||
1394 | /* pre-start/stop - all running streams are changed to DRAINING state */ | ||
1395 | result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); | ||
1396 | if (result < 0) | ||
1397 | goto _end; | ||
1398 | |||
1399 | /* check streams with PLAYBACK & DRAINING */ | ||
1400 | num_drecs = 0; | 1393 | num_drecs = 0; |
1401 | snd_pcm_group_for_each(pos, substream) { | 1394 | snd_pcm_group_for_each(pos, substream) { |
1402 | snd_pcm_substream_t *s = snd_pcm_group_substream_entry(pos); | 1395 | snd_pcm_substream_t *s = snd_pcm_group_substream_entry(pos); |
1403 | runtime = s->runtime; | 1396 | runtime = s->runtime; |
1404 | if (runtime->status->state != SNDRV_PCM_STATE_DRAINING) { | ||
1405 | runtime->status->state = SNDRV_PCM_STATE_SETUP; | ||
1406 | continue; | ||
1407 | } | ||
1408 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 1397 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
1409 | d = &drec[num_drecs++]; | 1398 | d = &drec[num_drecs++]; |
1410 | d->substream = s; | 1399 | d->substream = s; |
@@ -1418,9 +1407,21 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) | |||
1418 | runtime->stop_threshold = runtime->buffer_size; | 1407 | runtime->stop_threshold = runtime->buffer_size; |
1419 | } | 1408 | } |
1420 | } | 1409 | } |
1421 | 1410 | up_read(&snd_pcm_link_rwsem); | |
1422 | if (! num_drecs) | 1411 | if (! num_drecs) |
1423 | goto _end; | 1412 | goto _error; |
1413 | |||
1414 | snd_pcm_stream_lock_irq(substream); | ||
1415 | /* resume pause */ | ||
1416 | if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) | ||
1417 | snd_pcm_pause(substream, 0); | ||
1418 | |||
1419 | /* pre-start/stop - all running streams are changed to DRAINING state */ | ||
1420 | result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); | ||
1421 | if (result < 0) { | ||
1422 | snd_pcm_stream_unlock_irq(substream); | ||
1423 | goto _error; | ||
1424 | } | ||
1424 | 1425 | ||
1425 | for (;;) { | 1426 | for (;;) { |
1426 | long tout; | 1427 | long tout; |
@@ -1428,6 +1429,15 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) | |||
1428 | result = -ERESTARTSYS; | 1429 | result = -ERESTARTSYS; |
1429 | break; | 1430 | break; |
1430 | } | 1431 | } |
1432 | /* all finished? */ | ||
1433 | for (i = 0; i < num_drecs; i++) { | ||
1434 | runtime = drec[i].substream->runtime; | ||
1435 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) | ||
1436 | break; | ||
1437 | } | ||
1438 | if (i == num_drecs) | ||
1439 | break; /* yes, all drained */ | ||
1440 | |||
1431 | set_current_state(TASK_INTERRUPTIBLE); | 1441 | set_current_state(TASK_INTERRUPTIBLE); |
1432 | snd_pcm_stream_unlock_irq(substream); | 1442 | snd_pcm_stream_unlock_irq(substream); |
1433 | snd_power_unlock(card); | 1443 | snd_power_unlock(card); |
@@ -1444,15 +1454,11 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) | |||
1444 | } | 1454 | } |
1445 | break; | 1455 | break; |
1446 | } | 1456 | } |
1447 | /* all finished? */ | ||
1448 | for (i = 0; i < num_drecs; i++) { | ||
1449 | runtime = drec[i].substream->runtime; | ||
1450 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) | ||
1451 | break; | ||
1452 | } | ||
1453 | if (i == num_drecs) | ||
1454 | break; | ||
1455 | } | 1457 | } |
1458 | |||
1459 | snd_pcm_stream_unlock_irq(substream); | ||
1460 | |||
1461 | _error: | ||
1456 | for (i = 0; i < num_drecs; i++) { | 1462 | for (i = 0; i < num_drecs; i++) { |
1457 | d = &drec[i]; | 1463 | d = &drec[i]; |
1458 | runtime = d->substream->runtime; | 1464 | runtime = d->substream->runtime; |
@@ -1460,13 +1466,9 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream) | |||
1460 | runtime->stop_threshold = d->stop_threshold; | 1466 | runtime->stop_threshold = d->stop_threshold; |
1461 | } | 1467 | } |
1462 | 1468 | ||
1463 | _end: | ||
1464 | snd_pcm_stream_unlock_irq(substream); | ||
1465 | if (drec != &drec_tmp) | 1469 | if (drec != &drec_tmp) |
1466 | kfree(drec); | 1470 | kfree(drec); |
1467 | _unlock: | ||
1468 | snd_power_unlock(card); | 1471 | snd_power_unlock(card); |
1469 | up_read(&snd_pcm_link_rwsem); | ||
1470 | 1472 | ||
1471 | return result; | 1473 | return result; |
1472 | } | 1474 | } |
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile index 64cb50d7b589..402e2b4a34c6 100644 --- a/sound/core/seq/Makefile +++ b/sound/core/seq/Makefile | |||
@@ -38,7 +38,7 @@ obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o | |||
38 | obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o | 38 | obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o |
39 | obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o | 39 | obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o |
40 | obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o | 40 | obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o |
41 | obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-instr.o | 41 | obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-midi-emul.o snd-seq-instr.o |
42 | obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o | 42 | obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o |
43 | obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o | 43 | obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o |
44 | obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o | 44 | obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o |
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c index 0779c41ca037..32e91c6b25fe 100644 --- a/sound/core/seq/instr/ainstr_gf1.c +++ b/sound/core/seq/instr/ainstr_gf1.c | |||
@@ -50,7 +50,8 @@ static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops, | |||
50 | { | 50 | { |
51 | gf1_wave_t *wp, *prev; | 51 | gf1_wave_t *wp, *prev; |
52 | gf1_xwave_t xp; | 52 | gf1_xwave_t xp; |
53 | int err, gfp_mask; | 53 | int err; |
54 | unsigned int gfp_mask; | ||
54 | unsigned int real_size; | 55 | unsigned int real_size; |
55 | 56 | ||
56 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; | 57 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; |
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c index 39ff72b2aab3..2622b8679ca7 100644 --- a/sound/core/seq/instr/ainstr_iw.c +++ b/sound/core/seq/instr/ainstr_iw.c | |||
@@ -58,7 +58,7 @@ static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype, | |||
58 | iwffff_xenv_t *ex, | 58 | iwffff_xenv_t *ex, |
59 | char __user **data, | 59 | char __user **data, |
60 | long *len, | 60 | long *len, |
61 | int gfp_mask) | 61 | unsigned int __nocast gfp_mask) |
62 | { | 62 | { |
63 | __u32 stype; | 63 | __u32 stype; |
64 | iwffff_env_record_t *rp, *rp_last; | 64 | iwffff_env_record_t *rp, *rp_last; |
@@ -128,7 +128,8 @@ static int snd_seq_iwffff_copy_wave_from_stream(snd_iwffff_ops_t *ops, | |||
128 | { | 128 | { |
129 | iwffff_wave_t *wp, *prev; | 129 | iwffff_wave_t *wp, *prev; |
130 | iwffff_xwave_t xp; | 130 | iwffff_xwave_t xp; |
131 | int err, gfp_mask; | 131 | int err; |
132 | unsigned int gfp_mask; | ||
132 | unsigned int real_size; | 133 | unsigned int real_size; |
133 | 134 | ||
134 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; | 135 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; |
@@ -234,7 +235,8 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr, | |||
234 | iwffff_xinstrument_t ix; | 235 | iwffff_xinstrument_t ix; |
235 | iwffff_layer_t *lp, *prev_lp; | 236 | iwffff_layer_t *lp, *prev_lp; |
236 | iwffff_xlayer_t lx; | 237 | iwffff_xlayer_t lx; |
237 | int err, gfp_mask; | 238 | int err; |
239 | unsigned int gfp_mask; | ||
238 | 240 | ||
239 | if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE) | 241 | if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE) |
240 | return -EINVAL; | 242 | return -EINVAL; |
diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h index da23c4db8dd5..973786758c55 100644 --- a/sound/core/seq/oss/seq_oss_device.h +++ b/sound/core/seq/oss/seq_oss_device.h | |||
@@ -158,21 +158,21 @@ void snd_seq_oss_readq_info_read(seq_oss_readq_t *q, snd_info_buffer_t *buf); | |||
158 | #define is_nonblock_mode(mode) ((mode) & SNDRV_SEQ_OSS_FILE_NONBLOCK) | 158 | #define is_nonblock_mode(mode) ((mode) & SNDRV_SEQ_OSS_FILE_NONBLOCK) |
159 | 159 | ||
160 | /* dispatch event */ | 160 | /* dispatch event */ |
161 | inline static int | 161 | static inline int |
162 | snd_seq_oss_dispatch(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, int atomic, int hop) | 162 | snd_seq_oss_dispatch(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, int atomic, int hop) |
163 | { | 163 | { |
164 | return snd_seq_kernel_client_dispatch(dp->cseq, ev, atomic, hop); | 164 | return snd_seq_kernel_client_dispatch(dp->cseq, ev, atomic, hop); |
165 | } | 165 | } |
166 | 166 | ||
167 | /* ioctl */ | 167 | /* ioctl */ |
168 | inline static int | 168 | static inline int |
169 | snd_seq_oss_control(seq_oss_devinfo_t *dp, unsigned int type, void *arg) | 169 | snd_seq_oss_control(seq_oss_devinfo_t *dp, unsigned int type, void *arg) |
170 | { | 170 | { |
171 | return snd_seq_kernel_client_ctl(dp->cseq, type, arg); | 171 | return snd_seq_kernel_client_ctl(dp->cseq, type, arg); |
172 | } | 172 | } |
173 | 173 | ||
174 | /* fill the addresses in header */ | 174 | /* fill the addresses in header */ |
175 | inline static void | 175 | static inline void |
176 | snd_seq_oss_fill_addr(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, | 176 | snd_seq_oss_fill_addr(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, |
177 | int dest_client, int dest_port) | 177 | int dest_client, int dest_port) |
178 | { | 178 | { |
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index 638cc148706d..1a7736cbf3a4 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c | |||
@@ -325,14 +325,10 @@ snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp) | |||
325 | } | 325 | } |
326 | snd_use_lock_free(&rec->use_lock); | 326 | snd_use_lock_free(&rec->use_lock); |
327 | } | 327 | } |
328 | if (info->sysex) { | 328 | kfree(info->sysex); |
329 | kfree(info->sysex); | 329 | info->sysex = NULL; |
330 | info->sysex = NULL; | 330 | kfree(info->ch); |
331 | } | 331 | info->ch = NULL; |
332 | if (info->ch) { | ||
333 | kfree(info->ch); | ||
334 | info->ch = NULL; | ||
335 | } | ||
336 | } | 332 | } |
337 | dp->synth_opened = 0; | 333 | dp->synth_opened = 0; |
338 | dp->max_synthdev = 0; | 334 | dp->max_synthdev = 0; |
@@ -418,14 +414,10 @@ snd_seq_oss_synth_reset(seq_oss_devinfo_t *dp, int dev) | |||
418 | dp->file_mode) < 0) { | 414 | dp->file_mode) < 0) { |
419 | midi_synth_dev.opened--; | 415 | midi_synth_dev.opened--; |
420 | info->opened = 0; | 416 | info->opened = 0; |
421 | if (info->sysex) { | 417 | kfree(info->sysex); |
422 | kfree(info->sysex); | 418 | info->sysex = NULL; |
423 | info->sysex = NULL; | 419 | kfree(info->ch); |
424 | } | 420 | info->ch = NULL; |
425 | if (info->ch) { | ||
426 | kfree(info->ch); | ||
427 | info->ch = NULL; | ||
428 | } | ||
429 | } | 421 | } |
430 | return; | 422 | return; |
431 | } | 423 | } |
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index e88967c5b93d..ea945a5d2a0b 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c | |||
@@ -140,10 +140,7 @@ dummy_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int | |||
140 | static void | 140 | static void |
141 | dummy_free(void *private_data) | 141 | dummy_free(void *private_data) |
142 | { | 142 | { |
143 | snd_seq_dummy_port_t *p; | 143 | kfree(private_data); |
144 | |||
145 | p = private_data; | ||
146 | kfree(p); | ||
147 | } | 144 | } |
148 | 145 | ||
149 | /* | 146 | /* |
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 00d841e82fbc..03acb2d519ba 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c | |||
@@ -36,12 +36,12 @@ | |||
36 | #define semaphore_of(fp) ((fp)->f_dentry->d_inode->i_sem) | 36 | #define semaphore_of(fp) ((fp)->f_dentry->d_inode->i_sem) |
37 | 37 | ||
38 | 38 | ||
39 | inline static int snd_seq_pool_available(pool_t *pool) | 39 | static inline int snd_seq_pool_available(pool_t *pool) |
40 | { | 40 | { |
41 | return pool->total_elements - atomic_read(&pool->counter); | 41 | return pool->total_elements - atomic_read(&pool->counter); |
42 | } | 42 | } |
43 | 43 | ||
44 | inline static int snd_seq_output_ok(pool_t *pool) | 44 | static inline int snd_seq_output_ok(pool_t *pool) |
45 | { | 45 | { |
46 | return snd_seq_pool_available(pool) >= pool->room; | 46 | return snd_seq_pool_available(pool) >= pool->room; |
47 | } | 47 | } |
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 18247db45db6..4374829ea770 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c | |||
@@ -134,7 +134,7 @@ static int event_process_midi(snd_seq_event_t * ev, int direct, | |||
134 | seq_midisynth_t *msynth = (seq_midisynth_t *) private_data; | 134 | seq_midisynth_t *msynth = (seq_midisynth_t *) private_data; |
135 | unsigned char msg[10]; /* buffer for constructing midi messages */ | 135 | unsigned char msg[10]; /* buffer for constructing midi messages */ |
136 | snd_rawmidi_substream_t *substream; | 136 | snd_rawmidi_substream_t *substream; |
137 | int res; | 137 | int len; |
138 | 138 | ||
139 | snd_assert(msynth != NULL, return -EINVAL); | 139 | snd_assert(msynth != NULL, return -EINVAL); |
140 | substream = msynth->output_rfile.output; | 140 | substream = msynth->output_rfile.output; |
@@ -146,20 +146,16 @@ static int event_process_midi(snd_seq_event_t * ev, int direct, | |||
146 | snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); | 146 | snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); |
147 | return 0; | 147 | return 0; |
148 | } | 148 | } |
149 | res = snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream); | 149 | snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream); |
150 | snd_midi_event_reset_decode(msynth->parser); | 150 | snd_midi_event_reset_decode(msynth->parser); |
151 | if (res < 0) | ||
152 | return res; | ||
153 | } else { | 151 | } else { |
154 | if (msynth->parser == NULL) | 152 | if (msynth->parser == NULL) |
155 | return -EIO; | 153 | return -EIO; |
156 | res = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev); | 154 | len = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev); |
157 | if (res < 0) | 155 | if (len < 0) |
158 | return res; | 156 | return 0; |
159 | if ((res = dump_midi(substream, msg, res)) < 0) { | 157 | if (dump_midi(substream, msg, len) < 0) |
160 | snd_midi_event_reset_decode(msynth->parser); | 158 | snd_midi_event_reset_decode(msynth->parser); |
161 | return res; | ||
162 | } | ||
163 | } | 159 | } |
164 | return 0; | 160 | return 0; |
165 | } | 161 | } |
@@ -414,6 +410,8 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev) | |||
414 | if (newclient) | 410 | if (newclient) |
415 | synths[card->number] = client; | 411 | synths[card->number] = client; |
416 | up(®ister_mutex); | 412 | up(®ister_mutex); |
413 | kfree(info); | ||
414 | kfree(port); | ||
417 | return 0; /* success */ | 415 | return 0; /* success */ |
418 | 416 | ||
419 | __nomem: | 417 | __nomem: |
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 21e569062bc3..603b63716db6 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c | |||
@@ -146,7 +146,7 @@ void snd_midi_event_free(snd_midi_event_t *dev) | |||
146 | /* | 146 | /* |
147 | * initialize record | 147 | * initialize record |
148 | */ | 148 | */ |
149 | inline static void reset_encode(snd_midi_event_t *dev) | 149 | static inline void reset_encode(snd_midi_event_t *dev) |
150 | { | 150 | { |
151 | dev->read = 0; | 151 | dev->read = 0; |
152 | dev->qlen = 0; | 152 | dev->qlen = 0; |
@@ -171,11 +171,13 @@ void snd_midi_event_reset_decode(snd_midi_event_t *dev) | |||
171 | spin_unlock_irqrestore(&dev->lock, flags); | 171 | spin_unlock_irqrestore(&dev->lock, flags); |
172 | } | 172 | } |
173 | 173 | ||
174 | #if 0 | ||
174 | void snd_midi_event_init(snd_midi_event_t *dev) | 175 | void snd_midi_event_init(snd_midi_event_t *dev) |
175 | { | 176 | { |
176 | snd_midi_event_reset_encode(dev); | 177 | snd_midi_event_reset_encode(dev); |
177 | snd_midi_event_reset_decode(dev); | 178 | snd_midi_event_reset_decode(dev); |
178 | } | 179 | } |
180 | #endif /* 0 */ | ||
179 | 181 | ||
180 | void snd_midi_event_no_status(snd_midi_event_t *dev, int on) | 182 | void snd_midi_event_no_status(snd_midi_event_t *dev, int on) |
181 | { | 183 | { |
@@ -185,6 +187,7 @@ void snd_midi_event_no_status(snd_midi_event_t *dev, int on) | |||
185 | /* | 187 | /* |
186 | * resize buffer | 188 | * resize buffer |
187 | */ | 189 | */ |
190 | #if 0 | ||
188 | int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize) | 191 | int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize) |
189 | { | 192 | { |
190 | unsigned char *new_buf, *old_buf; | 193 | unsigned char *new_buf, *old_buf; |
@@ -204,6 +207,7 @@ int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize) | |||
204 | kfree(old_buf); | 207 | kfree(old_buf); |
205 | return 0; | 208 | return 0; |
206 | } | 209 | } |
210 | #endif /* 0 */ | ||
207 | 211 | ||
208 | /* | 212 | /* |
209 | * read bytes and encode to sequencer event if finished | 213 | * read bytes and encode to sequencer event if finished |
@@ -517,8 +521,6 @@ static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int coun | |||
517 | 521 | ||
518 | EXPORT_SYMBOL(snd_midi_event_new); | 522 | EXPORT_SYMBOL(snd_midi_event_new); |
519 | EXPORT_SYMBOL(snd_midi_event_free); | 523 | EXPORT_SYMBOL(snd_midi_event_free); |
520 | EXPORT_SYMBOL(snd_midi_event_resize_buffer); | ||
521 | EXPORT_SYMBOL(snd_midi_event_init); | ||
522 | EXPORT_SYMBOL(snd_midi_event_reset_encode); | 524 | EXPORT_SYMBOL(snd_midi_event_reset_encode); |
523 | EXPORT_SYMBOL(snd_midi_event_reset_decode); | 525 | EXPORT_SYMBOL(snd_midi_event_reset_decode); |
524 | EXPORT_SYMBOL(snd_midi_event_no_status); | 526 | EXPORT_SYMBOL(snd_midi_event_no_status); |
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c index 3afc7cc0c9a7..98de2e711fde 100644 --- a/sound/core/seq/seq_queue.c +++ b/sound/core/seq/seq_queue.c | |||
@@ -672,7 +672,8 @@ static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, i | |||
672 | * process a received queue-control event. | 672 | * process a received queue-control event. |
673 | * this function is exported for seq_sync.c. | 673 | * this function is exported for seq_sync.c. |
674 | */ | 674 | */ |
675 | void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop) | 675 | static void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, |
676 | int atomic, int hop) | ||
676 | { | 677 | { |
677 | switch (ev->type) { | 678 | switch (ev->type) { |
678 | case SNDRV_SEQ_EVENT_START: | 679 | case SNDRV_SEQ_EVENT_START: |
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h index b1bf5519fb3b..ea3c54216ea8 100644 --- a/sound/core/seq/seq_queue.h +++ b/sound/core/seq/seq_queue.h | |||
@@ -111,7 +111,6 @@ int snd_seq_queue_use(int queueid, int client, int use); | |||
111 | int snd_seq_queue_is_used(int queueid, int client); | 111 | int snd_seq_queue_is_used(int queueid, int client); |
112 | 112 | ||
113 | int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop); | 113 | int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop); |
114 | void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop); | ||
115 | 114 | ||
116 | /* | 115 | /* |
117 | * 64bit division - for sync stuff.. | 116 | * 64bit division - for sync stuff.. |
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index 753f1c0863cc..a7f76fc95280 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c | |||
@@ -36,7 +36,8 @@ extern int seq_default_timer_resolution; | |||
36 | 36 | ||
37 | #define SKEW_BASE 0x10000 /* 16bit shift */ | 37 | #define SKEW_BASE 0x10000 /* 16bit shift */ |
38 | 38 | ||
39 | void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks) | 39 | static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, |
40 | int tempo, int ppq, int nticks) | ||
40 | { | 41 | { |
41 | if (tempo < 1000000) | 42 | if (tempo < 1000000) |
42 | tick->resolution = (tempo * 1000) / ppq; | 43 | tick->resolution = (tempo * 1000) / ppq; |
diff --git a/sound/core/seq/seq_timer.h b/sound/core/seq/seq_timer.h index 4c0872df8931..287ed68591de 100644 --- a/sound/core/seq/seq_timer.h +++ b/sound/core/seq/seq_timer.h | |||
@@ -64,8 +64,6 @@ extern seq_timer_t *snd_seq_timer_new(void); | |||
64 | /* delete timer (destructor) */ | 64 | /* delete timer (destructor) */ |
65 | extern void snd_seq_timer_delete(seq_timer_t **tmr); | 65 | extern void snd_seq_timer_delete(seq_timer_t **tmr); |
66 | 66 | ||
67 | void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks); | ||
68 | |||
69 | /* */ | 67 | /* */ |
70 | static inline void snd_seq_timer_update_tick(seq_timer_tick_t *tick, unsigned long resolution) | 68 | static inline void snd_seq_timer_update_tick(seq_timer_tick_t *tick, unsigned long resolution) |
71 | { | 69 | { |
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 6b4e630ace54..a66484b5cf0e 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c | |||
@@ -110,7 +110,7 @@ static int snd_virmidi_dev_receive_event(snd_virmidi_dev_t *rdev, snd_seq_event_ | |||
110 | * handler of a remote port which is attached to the virmidi via | 110 | * handler of a remote port which is attached to the virmidi via |
111 | * SNDRV_VIRMIDI_SEQ_ATTACH. | 111 | * SNDRV_VIRMIDI_SEQ_ATTACH. |
112 | */ | 112 | */ |
113 | /* exported */ | 113 | #if 0 |
114 | int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev) | 114 | int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev) |
115 | { | 115 | { |
116 | snd_virmidi_dev_t *rdev; | 116 | snd_virmidi_dev_t *rdev; |
@@ -118,6 +118,7 @@ int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev) | |||
118 | rdev = rmidi->private_data; | 118 | rdev = rmidi->private_data; |
119 | return snd_virmidi_dev_receive_event(rdev, ev); | 119 | return snd_virmidi_dev_receive_event(rdev, ev); |
120 | } | 120 | } |
121 | #endif /* 0 */ | ||
121 | 122 | ||
122 | /* | 123 | /* |
123 | * event handler of virmidi port | 124 | * event handler of virmidi port |
@@ -384,7 +385,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev) | |||
384 | info->client = client; | 385 | info->client = client; |
385 | info->type = KERNEL_CLIENT; | 386 | info->type = KERNEL_CLIENT; |
386 | sprintf(info->name, "%s %d-%d", rdev->rmidi->name, rdev->card->number, rdev->device); | 387 | sprintf(info->name, "%s %d-%d", rdev->rmidi->name, rdev->card->number, rdev->device); |
387 | snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info); | 388 | snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info); |
388 | 389 | ||
389 | /* create a port */ | 390 | /* create a port */ |
390 | memset(pinfo, 0, sizeof(*pinfo)); | 391 | memset(pinfo, 0, sizeof(*pinfo)); |
@@ -405,7 +406,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev) | |||
405 | pcallbacks.unuse = snd_virmidi_unuse; | 406 | pcallbacks.unuse = snd_virmidi_unuse; |
406 | pcallbacks.event_input = snd_virmidi_event_input; | 407 | pcallbacks.event_input = snd_virmidi_event_input; |
407 | pinfo->kernel = &pcallbacks; | 408 | pinfo->kernel = &pcallbacks; |
408 | err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo); | 409 | err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, pinfo); |
409 | if (err < 0) { | 410 | if (err < 0) { |
410 | snd_seq_delete_kernel_client(client); | 411 | snd_seq_delete_kernel_client(client); |
411 | rdev->client = -1; | 412 | rdev->client = -1; |
@@ -548,4 +549,3 @@ module_init(alsa_virmidi_init) | |||
548 | module_exit(alsa_virmidi_exit) | 549 | module_exit(alsa_virmidi_exit) |
549 | 550 | ||
550 | EXPORT_SYMBOL(snd_virmidi_new); | 551 | EXPORT_SYMBOL(snd_virmidi_new); |
551 | EXPORT_SYMBOL(snd_virmidi_receive); | ||
diff --git a/sound/core/sound.c b/sound/core/sound.c index 88e052079f85..7612884f530b 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
@@ -64,7 +64,7 @@ static struct list_head snd_minors_hash[SNDRV_CARDS]; | |||
64 | 64 | ||
65 | static DECLARE_MUTEX(sound_mutex); | 65 | static DECLARE_MUTEX(sound_mutex); |
66 | 66 | ||
67 | extern struct class_simple *sound_class; | 67 | extern struct class *sound_class; |
68 | 68 | ||
69 | 69 | ||
70 | #ifdef CONFIG_KMOD | 70 | #ifdef CONFIG_KMOD |
@@ -231,7 +231,7 @@ int snd_register_device(int type, snd_card_t * card, int dev, snd_minor_t * reg, | |||
231 | devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name); | 231 | devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name); |
232 | if (card) | 232 | if (card) |
233 | device = card->dev; | 233 | device = card->dev; |
234 | class_simple_device_add(sound_class, MKDEV(major, minor), device, name); | 234 | class_device_create(sound_class, MKDEV(major, minor), device, "%s", name); |
235 | 235 | ||
236 | up(&sound_mutex); | 236 | up(&sound_mutex); |
237 | return 0; | 237 | return 0; |
@@ -263,7 +263,7 @@ int snd_unregister_device(int type, snd_card_t * card, int dev) | |||
263 | 263 | ||
264 | if (strncmp(mptr->name, "controlC", 8) || card->number >= cards_limit) /* created in sound.c */ | 264 | if (strncmp(mptr->name, "controlC", 8) || card->number >= cards_limit) /* created in sound.c */ |
265 | devfs_remove("snd/%s", mptr->name); | 265 | devfs_remove("snd/%s", mptr->name); |
266 | class_simple_device_remove(MKDEV(major, minor)); | 266 | class_device_destroy(sound_class, MKDEV(major, minor)); |
267 | 267 | ||
268 | list_del(&mptr->list); | 268 | list_del(&mptr->list); |
269 | up(&sound_mutex); | 269 | up(&sound_mutex); |
@@ -399,8 +399,8 @@ EXPORT_SYMBOL(snd_hidden_kcalloc); | |||
399 | EXPORT_SYMBOL(snd_hidden_kfree); | 399 | EXPORT_SYMBOL(snd_hidden_kfree); |
400 | EXPORT_SYMBOL(snd_hidden_vmalloc); | 400 | EXPORT_SYMBOL(snd_hidden_vmalloc); |
401 | EXPORT_SYMBOL(snd_hidden_vfree); | 401 | EXPORT_SYMBOL(snd_hidden_vfree); |
402 | EXPORT_SYMBOL(snd_hidden_kstrdup); | ||
402 | #endif | 403 | #endif |
403 | EXPORT_SYMBOL(snd_kmalloc_strdup); | ||
404 | EXPORT_SYMBOL(copy_to_user_fromio); | 404 | EXPORT_SYMBOL(copy_to_user_fromio); |
405 | EXPORT_SYMBOL(copy_from_user_toio); | 405 | EXPORT_SYMBOL(copy_from_user_toio); |
406 | /* init.c */ | 406 | /* init.c */ |
@@ -431,7 +431,6 @@ EXPORT_SYMBOL(snd_card_pci_resume); | |||
431 | EXPORT_SYMBOL(snd_device_new); | 431 | EXPORT_SYMBOL(snd_device_new); |
432 | EXPORT_SYMBOL(snd_device_register); | 432 | EXPORT_SYMBOL(snd_device_register); |
433 | EXPORT_SYMBOL(snd_device_free); | 433 | EXPORT_SYMBOL(snd_device_free); |
434 | EXPORT_SYMBOL(snd_device_free_all); | ||
435 | /* isadma.c */ | 434 | /* isadma.c */ |
436 | #ifdef CONFIG_ISA | 435 | #ifdef CONFIG_ISA |
437 | EXPORT_SYMBOL(snd_dma_program); | 436 | EXPORT_SYMBOL(snd_dma_program); |
diff --git a/sound/core/timer.c b/sound/core/timer.c index fa762ca439be..cfaccd415b3b 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/time.h> | 27 | #include <linux/time.h> |
28 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <linux/string.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/timer.h> | 31 | #include <sound/timer.h> |
31 | #include <sound/control.h> | 32 | #include <sound/control.h> |
@@ -69,6 +70,7 @@ typedef struct { | |||
69 | struct timespec tstamp; /* trigger tstamp */ | 70 | struct timespec tstamp; /* trigger tstamp */ |
70 | wait_queue_head_t qchange_sleep; | 71 | wait_queue_head_t qchange_sleep; |
71 | struct fasync_struct *fasync; | 72 | struct fasync_struct *fasync; |
73 | struct semaphore tread_sem; | ||
72 | } snd_timer_user_t; | 74 | } snd_timer_user_t; |
73 | 75 | ||
74 | /* list of timers */ | 76 | /* list of timers */ |
@@ -99,7 +101,7 @@ static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *ti | |||
99 | timeri = kcalloc(1, sizeof(*timeri), GFP_KERNEL); | 101 | timeri = kcalloc(1, sizeof(*timeri), GFP_KERNEL); |
100 | if (timeri == NULL) | 102 | if (timeri == NULL) |
101 | return NULL; | 103 | return NULL; |
102 | timeri->owner = snd_kmalloc_strdup(owner, GFP_KERNEL); | 104 | timeri->owner = kstrdup(owner, GFP_KERNEL); |
103 | if (! timeri->owner) { | 105 | if (! timeri->owner) { |
104 | kfree(timeri); | 106 | kfree(timeri); |
105 | return NULL; | 107 | return NULL; |
@@ -844,7 +846,7 @@ int snd_timer_dev_register(snd_device_t *dev) | |||
844 | return 0; | 846 | return 0; |
845 | } | 847 | } |
846 | 848 | ||
847 | int snd_timer_unregister(snd_timer_t *timer) | 849 | static int snd_timer_unregister(snd_timer_t *timer) |
848 | { | 850 | { |
849 | struct list_head *p, *n; | 851 | struct list_head *p, *n; |
850 | snd_timer_instance_t *ti; | 852 | snd_timer_instance_t *ti; |
@@ -945,11 +947,6 @@ struct snd_timer_system_private { | |||
945 | unsigned long correction; | 947 | unsigned long correction; |
946 | }; | 948 | }; |
947 | 949 | ||
948 | unsigned int snd_timer_system_resolution(void) | ||
949 | { | ||
950 | return 1000000000L / HZ; | ||
951 | } | ||
952 | |||
953 | static void snd_timer_s_function(unsigned long data) | 950 | static void snd_timer_s_function(unsigned long data) |
954 | { | 951 | { |
955 | snd_timer_t *timer = (snd_timer_t *)data; | 952 | snd_timer_t *timer = (snd_timer_t *)data; |
@@ -1208,6 +1205,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) | |||
1208 | return -ENOMEM; | 1205 | return -ENOMEM; |
1209 | spin_lock_init(&tu->qlock); | 1206 | spin_lock_init(&tu->qlock); |
1210 | init_waitqueue_head(&tu->qchange_sleep); | 1207 | init_waitqueue_head(&tu->qchange_sleep); |
1208 | init_MUTEX(&tu->tread_sem); | ||
1211 | tu->ticks = 1; | 1209 | tu->ticks = 1; |
1212 | tu->queue_size = 128; | 1210 | tu->queue_size = 128; |
1213 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1211 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); |
@@ -1454,46 +1452,51 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * | |||
1454 | snd_timer_user_t *tu; | 1452 | snd_timer_user_t *tu; |
1455 | snd_timer_select_t tselect; | 1453 | snd_timer_select_t tselect; |
1456 | char str[32]; | 1454 | char str[32]; |
1457 | int err; | 1455 | int err = 0; |
1458 | 1456 | ||
1459 | tu = file->private_data; | 1457 | tu = file->private_data; |
1460 | if (tu->timeri) | 1458 | down(&tu->tread_sem); |
1459 | if (tu->timeri) { | ||
1461 | snd_timer_close(tu->timeri); | 1460 | snd_timer_close(tu->timeri); |
1462 | if (copy_from_user(&tselect, _tselect, sizeof(tselect))) | 1461 | tu->timeri = NULL; |
1463 | return -EFAULT; | 1462 | } |
1463 | if (copy_from_user(&tselect, _tselect, sizeof(tselect))) { | ||
1464 | err = -EFAULT; | ||
1465 | goto __err; | ||
1466 | } | ||
1464 | sprintf(str, "application %i", current->pid); | 1467 | sprintf(str, "application %i", current->pid); |
1465 | if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) | 1468 | if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) |
1466 | tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; | 1469 | tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; |
1467 | if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) | 1470 | if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) |
1468 | return err; | 1471 | goto __err; |
1469 | 1472 | ||
1470 | if (tu->queue) { | 1473 | kfree(tu->queue); |
1471 | kfree(tu->queue); | 1474 | tu->queue = NULL; |
1472 | tu->queue = NULL; | 1475 | kfree(tu->tqueue); |
1473 | } | 1476 | tu->tqueue = NULL; |
1474 | if (tu->tqueue) { | ||
1475 | kfree(tu->tqueue); | ||
1476 | tu->tqueue = NULL; | ||
1477 | } | ||
1478 | if (tu->tread) { | 1477 | if (tu->tread) { |
1479 | tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); | 1478 | tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); |
1480 | if (tu->tqueue == NULL) { | 1479 | if (tu->tqueue == NULL) |
1481 | snd_timer_close(tu->timeri); | 1480 | err = -ENOMEM; |
1482 | return -ENOMEM; | ||
1483 | } | ||
1484 | } else { | 1481 | } else { |
1485 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1482 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); |
1486 | if (tu->queue == NULL) { | 1483 | if (tu->queue == NULL) |
1487 | snd_timer_close(tu->timeri); | 1484 | err = -ENOMEM; |
1488 | return -ENOMEM; | ||
1489 | } | ||
1490 | } | 1485 | } |
1491 | 1486 | ||
1492 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; | 1487 | if (err < 0) { |
1493 | tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | 1488 | snd_timer_close(tu->timeri); |
1494 | tu->timeri->ccallback = snd_timer_user_ccallback; | 1489 | tu->timeri = NULL; |
1495 | tu->timeri->callback_data = (void *)tu; | 1490 | } else { |
1496 | return 0; | 1491 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; |
1492 | tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | ||
1493 | tu->timeri->ccallback = snd_timer_user_ccallback; | ||
1494 | tu->timeri->callback_data = (void *)tu; | ||
1495 | } | ||
1496 | |||
1497 | __err: | ||
1498 | up(&tu->tread_sem); | ||
1499 | return err; | ||
1497 | } | 1500 | } |
1498 | 1501 | ||
1499 | static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) | 1502 | static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) |
@@ -1669,6 +1672,23 @@ static int snd_timer_user_continue(struct file *file) | |||
1669 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; | 1672 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; |
1670 | } | 1673 | } |
1671 | 1674 | ||
1675 | static int snd_timer_user_pause(struct file *file) | ||
1676 | { | ||
1677 | int err; | ||
1678 | snd_timer_user_t *tu; | ||
1679 | |||
1680 | tu = file->private_data; | ||
1681 | snd_assert(tu->timeri != NULL, return -ENXIO); | ||
1682 | return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; | ||
1683 | } | ||
1684 | |||
1685 | enum { | ||
1686 | SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20), | ||
1687 | SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21), | ||
1688 | SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22), | ||
1689 | SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), | ||
1690 | }; | ||
1691 | |||
1672 | static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1692 | static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1673 | { | 1693 | { |
1674 | snd_timer_user_t *tu; | 1694 | snd_timer_user_t *tu; |
@@ -1685,11 +1705,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l | |||
1685 | { | 1705 | { |
1686 | int xarg; | 1706 | int xarg; |
1687 | 1707 | ||
1688 | if (tu->timeri) /* too late */ | 1708 | down(&tu->tread_sem); |
1709 | if (tu->timeri) { /* too late */ | ||
1710 | up(&tu->tread_sem); | ||
1689 | return -EBUSY; | 1711 | return -EBUSY; |
1690 | if (get_user(xarg, p)) | 1712 | } |
1713 | if (get_user(xarg, p)) { | ||
1714 | up(&tu->tread_sem); | ||
1691 | return -EFAULT; | 1715 | return -EFAULT; |
1716 | } | ||
1692 | tu->tread = xarg ? 1 : 0; | 1717 | tu->tread = xarg ? 1 : 0; |
1718 | up(&tu->tread_sem); | ||
1693 | return 0; | 1719 | return 0; |
1694 | } | 1720 | } |
1695 | case SNDRV_TIMER_IOCTL_GINFO: | 1721 | case SNDRV_TIMER_IOCTL_GINFO: |
@@ -1707,11 +1733,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l | |||
1707 | case SNDRV_TIMER_IOCTL_STATUS: | 1733 | case SNDRV_TIMER_IOCTL_STATUS: |
1708 | return snd_timer_user_status(file, argp); | 1734 | return snd_timer_user_status(file, argp); |
1709 | case SNDRV_TIMER_IOCTL_START: | 1735 | case SNDRV_TIMER_IOCTL_START: |
1736 | case SNDRV_TIMER_IOCTL_START_OLD: | ||
1710 | return snd_timer_user_start(file); | 1737 | return snd_timer_user_start(file); |
1711 | case SNDRV_TIMER_IOCTL_STOP: | 1738 | case SNDRV_TIMER_IOCTL_STOP: |
1739 | case SNDRV_TIMER_IOCTL_STOP_OLD: | ||
1712 | return snd_timer_user_stop(file); | 1740 | return snd_timer_user_stop(file); |
1713 | case SNDRV_TIMER_IOCTL_CONTINUE: | 1741 | case SNDRV_TIMER_IOCTL_CONTINUE: |
1742 | case SNDRV_TIMER_IOCTL_CONTINUE_OLD: | ||
1714 | return snd_timer_user_continue(file); | 1743 | return snd_timer_user_continue(file); |
1744 | case SNDRV_TIMER_IOCTL_PAUSE: | ||
1745 | case SNDRV_TIMER_IOCTL_PAUSE_OLD: | ||
1746 | return snd_timer_user_pause(file); | ||
1715 | } | 1747 | } |
1716 | return -ENOTTY; | 1748 | return -ENOTTY; |
1717 | } | 1749 | } |
@@ -1898,4 +1930,3 @@ EXPORT_SYMBOL(snd_timer_global_free); | |||
1898 | EXPORT_SYMBOL(snd_timer_global_register); | 1930 | EXPORT_SYMBOL(snd_timer_global_register); |
1899 | EXPORT_SYMBOL(snd_timer_global_unregister); | 1931 | EXPORT_SYMBOL(snd_timer_global_unregister); |
1900 | EXPORT_SYMBOL(snd_timer_interrupt); | 1932 | EXPORT_SYMBOL(snd_timer_interrupt); |
1901 | EXPORT_SYMBOL(snd_timer_system_resolution); | ||
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c index 9fbc3957a22d..3de552dfe80f 100644 --- a/sound/core/timer_compat.c +++ b/sound/core/timer_compat.c | |||
@@ -106,8 +106,13 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns | |||
106 | case SNDRV_TIMER_IOCTL_SELECT: | 106 | case SNDRV_TIMER_IOCTL_SELECT: |
107 | case SNDRV_TIMER_IOCTL_PARAMS: | 107 | case SNDRV_TIMER_IOCTL_PARAMS: |
108 | case SNDRV_TIMER_IOCTL_START: | 108 | case SNDRV_TIMER_IOCTL_START: |
109 | case SNDRV_TIMER_IOCTL_START_OLD: | ||
109 | case SNDRV_TIMER_IOCTL_STOP: | 110 | case SNDRV_TIMER_IOCTL_STOP: |
111 | case SNDRV_TIMER_IOCTL_STOP_OLD: | ||
110 | case SNDRV_TIMER_IOCTL_CONTINUE: | 112 | case SNDRV_TIMER_IOCTL_CONTINUE: |
113 | case SNDRV_TIMER_IOCTL_CONTINUE_OLD: | ||
114 | case SNDRV_TIMER_IOCTL_PAUSE: | ||
115 | case SNDRV_TIMER_IOCTL_PAUSE_OLD: | ||
111 | case SNDRV_TIMER_IOCTL_NEXT_DEVICE: | 116 | case SNDRV_TIMER_IOCTL_NEXT_DEVICE: |
112 | return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); | 117 | return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); |
113 | case SNDRV_TIMER_IOCTL_INFO32: | 118 | case SNDRV_TIMER_IOCTL_INFO32: |
diff --git a/sound/core/wrappers.c b/sound/core/wrappers.c index 9f393023c327..508e6d67ee19 100644 --- a/sound/core/wrappers.c +++ b/sound/core/wrappers.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | 28 | ||
29 | #ifdef CONFIG_SND_DEBUG_MEMORY | 29 | #ifdef CONFIG_SND_DEBUG_MEMORY |
30 | void *snd_wrapper_kmalloc(size_t size, int flags) | 30 | void *snd_wrapper_kmalloc(size_t size, unsigned int __nocast flags) |
31 | { | 31 | { |
32 | return kmalloc(size, flags); | 32 | return kmalloc(size, flags); |
33 | } | 33 | } |
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 964b97e70c84..986df35fb829 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c | |||
@@ -168,7 +168,7 @@ typedef struct _snd_uart16550 { | |||
168 | 168 | ||
169 | static snd_card_t *snd_serial_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | 169 | static snd_card_t *snd_serial_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; |
170 | 170 | ||
171 | inline static void snd_uart16550_add_timer(snd_uart16550_t *uart) | 171 | static inline void snd_uart16550_add_timer(snd_uart16550_t *uart) |
172 | { | 172 | { |
173 | if (! uart->timer_running) { | 173 | if (! uart->timer_running) { |
174 | /* timer 38600bps * 10bit * 16byte */ | 174 | /* timer 38600bps * 10bit * 16byte */ |
@@ -178,7 +178,7 @@ inline static void snd_uart16550_add_timer(snd_uart16550_t *uart) | |||
178 | } | 178 | } |
179 | } | 179 | } |
180 | 180 | ||
181 | inline static void snd_uart16550_del_timer(snd_uart16550_t *uart) | 181 | static inline void snd_uart16550_del_timer(snd_uart16550_t *uart) |
182 | { | 182 | { |
183 | if (uart->timer_running) { | 183 | if (uart->timer_running) { |
184 | del_timer(&uart->buffer_timer); | 184 | del_timer(&uart->buffer_timer); |
@@ -187,7 +187,7 @@ inline static void snd_uart16550_del_timer(snd_uart16550_t *uart) | |||
187 | } | 187 | } |
188 | 188 | ||
189 | /* This macro is only used in snd_uart16550_io_loop */ | 189 | /* This macro is only used in snd_uart16550_io_loop */ |
190 | inline static void snd_uart16550_buffer_output(snd_uart16550_t *uart) | 190 | static inline void snd_uart16550_buffer_output(snd_uart16550_t *uart) |
191 | { | 191 | { |
192 | unsigned short buff_out = uart->buff_out; | 192 | unsigned short buff_out = uart->buff_out; |
193 | if( uart->buff_in_count > 0 ) { | 193 | if( uart->buff_in_count > 0 ) { |
@@ -579,7 +579,7 @@ static int snd_uart16550_output_close(snd_rawmidi_substream_t * substream) | |||
579 | return 0; | 579 | return 0; |
580 | }; | 580 | }; |
581 | 581 | ||
582 | inline static int snd_uart16550_buffer_can_write( snd_uart16550_t *uart, int Num ) | 582 | static inline int snd_uart16550_buffer_can_write( snd_uart16550_t *uart, int Num ) |
583 | { | 583 | { |
584 | if( uart->buff_in_count + Num < TX_BUFF_SIZE ) | 584 | if( uart->buff_in_count + Num < TX_BUFF_SIZE ) |
585 | return 1; | 585 | return 1; |
@@ -587,7 +587,7 @@ inline static int snd_uart16550_buffer_can_write( snd_uart16550_t *uart, int Num | |||
587 | return 0; | 587 | return 0; |
588 | } | 588 | } |
589 | 589 | ||
590 | inline static int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned char byte) | 590 | static inline int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned char byte) |
591 | { | 591 | { |
592 | unsigned short buff_in = uart->buff_in; | 592 | unsigned short buff_in = uart->buff_in; |
593 | if( uart->buff_in_count < TX_BUFF_SIZE ) { | 593 | if( uart->buff_in_count < TX_BUFF_SIZE ) { |
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index 98587176b327..af381b15fe5c 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c | |||
@@ -1264,14 +1264,10 @@ static void snd_vx_pcm_free(snd_pcm_t *pcm) | |||
1264 | { | 1264 | { |
1265 | vx_core_t *chip = pcm->private_data; | 1265 | vx_core_t *chip = pcm->private_data; |
1266 | chip->pcm[pcm->device] = NULL; | 1266 | chip->pcm[pcm->device] = NULL; |
1267 | if (chip->playback_pipes) { | 1267 | kfree(chip->playback_pipes); |
1268 | kfree(chip->playback_pipes); | 1268 | chip->playback_pipes = NULL; |
1269 | chip->playback_pipes = NULL; | 1269 | kfree(chip->capture_pipes); |
1270 | } | 1270 | chip->capture_pipes = NULL; |
1271 | if (chip->capture_pipes) { | ||
1272 | kfree(chip->capture_pipes); | ||
1273 | chip->capture_pipes = NULL; | ||
1274 | } | ||
1275 | } | 1271 | } |
1276 | 1272 | ||
1277 | /* | 1273 | /* |
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c index 18114713c3b3..4fc38bde34f4 100644 --- a/sound/drivers/vx/vx_uer.c +++ b/sound/drivers/vx/vx_uer.c | |||
@@ -162,34 +162,24 @@ static int vx_read_uer_status(vx_core_t *chip, int *mode) | |||
162 | 162 | ||
163 | static int vx_calc_clock_from_freq(vx_core_t *chip, int freq) | 163 | static int vx_calc_clock_from_freq(vx_core_t *chip, int freq) |
164 | { | 164 | { |
165 | #define XX_FECH48000 0x0000004B | 165 | int hexfreq; |
166 | #define XX_FECH32000 0x00000171 | 166 | |
167 | #define XX_FECH24000 0x0000024B | 167 | snd_assert(freq > 0, return 0); |
168 | #define XX_FECH16000 0x00000371 | 168 | |
169 | #define XX_FECH12000 0x0000044B | 169 | hexfreq = (28224000 * 10) / freq; |
170 | #define XX_FECH8000 0x00000571 | 170 | hexfreq = (hexfreq + 5) / 10; |
171 | #define XX_FECH44100 0x0000007F | 171 | |
172 | #define XX_FECH29400 0x0000016F | 172 | /* max freq = 55125 Hz */ |
173 | #define XX_FECH22050 0x0000027F | 173 | snd_assert(hexfreq > 0x00000200, return 0); |
174 | #define XX_FECH14000 0x000003EF | 174 | |
175 | #define XX_FECH11025 0x0000047F | 175 | if (hexfreq <= 0x03ff) |
176 | #define XX_FECH7350 0x000005BF | 176 | return hexfreq - 0x00000201; |
177 | 177 | if (hexfreq <= 0x07ff) | |
178 | switch (freq) { | 178 | return (hexfreq / 2) - 1; |
179 | case 48000: return XX_FECH48000; | 179 | if (hexfreq <= 0x0fff) |
180 | case 44100: return XX_FECH44100; | 180 | return (hexfreq / 4) + 0x000001ff; |
181 | case 32000: return XX_FECH32000; | 181 | |
182 | case 29400: return XX_FECH29400; | 182 | return 0x5fe; /* min freq = 6893 Hz */ |
183 | case 24000: return XX_FECH24000; | ||
184 | case 22050: return XX_FECH22050; | ||
185 | case 16000: return XX_FECH16000; | ||
186 | case 14000: return XX_FECH14000; | ||
187 | case 12000: return XX_FECH12000; | ||
188 | case 11025: return XX_FECH11025; | ||
189 | case 8000: return XX_FECH8000; | ||
190 | case 7350: return XX_FECH7350; | ||
191 | default: return freq; /* The value is already correct */ | ||
192 | } | ||
193 | } | 183 | } |
194 | 184 | ||
195 | 185 | ||
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index f5e6018ea3f4..5adde308a00f 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c | |||
@@ -554,7 +554,6 @@ int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags) | |||
554 | if (snd_pcm_running(ak4114->capture_substream)) { | 554 | if (snd_pcm_running(ak4114->capture_substream)) { |
555 | // printk("rate changed (%i <- %i)\n", runtime->rate, res); | 555 | // printk("rate changed (%i <- %i)\n", runtime->rate, res); |
556 | snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING); | 556 | snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING); |
557 | wake_up(&runtime->sleep); | ||
558 | res = 1; | 557 | res = 1; |
559 | } | 558 | } |
560 | snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags); | 559 | snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags); |
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c index bb503e70b664..2da8d7f157f4 100644 --- a/sound/i2c/tea6330t.c +++ b/sound/i2c/tea6330t.c | |||
@@ -266,8 +266,7 @@ TEA6330T_TREBLE("Tone Control - Treble", 0) | |||
266 | 266 | ||
267 | static void snd_tea6330_free(snd_i2c_device_t *device) | 267 | static void snd_tea6330_free(snd_i2c_device_t *device) |
268 | { | 268 | { |
269 | tea6330t_t *tea = device->private_data; | 269 | kfree(device->private_data); |
270 | kfree(tea); | ||
271 | } | 270 | } |
272 | 271 | ||
273 | int snd_tea6330t_update_mixer(snd_card_t * card, | 272 | int snd_tea6330t_update_mixer(snd_card_t * card, |
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 3a3228b18726..148a856a43ad 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig | |||
@@ -179,6 +179,7 @@ config SND_INTERWAVE_STB | |||
179 | select SND_RAWMIDI | 179 | select SND_RAWMIDI |
180 | select SND_CS4231_LIB | 180 | select SND_CS4231_LIB |
181 | select SND_GUS_SYNTH | 181 | select SND_GUS_SYNTH |
182 | select ISAPNP | ||
182 | help | 183 | help |
183 | Say Y here to include support for AMD InterWave based | 184 | Say Y here to include support for AMD InterWave based |
184 | soundcards with a TEA6330T bass and treble regulator | 185 | soundcards with a TEA6330T bass and treble regulator |
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 9fa7a78da6c3..563296d02894 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c | |||
@@ -83,6 +83,8 @@ struct snd_card_ad1816a { | |||
83 | static struct pnp_card_device_id snd_ad1816a_pnpids[] = { | 83 | static struct pnp_card_device_id snd_ad1816a_pnpids[] = { |
84 | /* Analog Devices AD1815 */ | 84 | /* Analog Devices AD1815 */ |
85 | { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } }, | 85 | { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } }, |
86 | /* Analog Device AD1816? */ | ||
87 | { .id = "ADS7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, | ||
86 | /* Analog Devices AD1816A - added by Kenneth Platz <kxp@atl.hp.com> */ | 88 | /* Analog Devices AD1816A - added by Kenneth Platz <kxp@atl.hp.com> */ |
87 | { .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, | 89 | { .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } }, |
88 | /* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */ | 90 | /* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */ |
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index e745a54e00a1..39f4eff44f5c 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c | |||
@@ -349,8 +349,7 @@ static int __devinit snd_card_cs4236_pnp(int dev, struct snd_card_cs4236 *acard, | |||
349 | pnp_init_resource_table(cfg); | 349 | pnp_init_resource_table(cfg); |
350 | if (mpu_port[dev] != SNDRV_AUTO_PORT) | 350 | if (mpu_port[dev] != SNDRV_AUTO_PORT) |
351 | pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2); | 351 | pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2); |
352 | if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0 && | 352 | if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0) |
353 | pnp_irq_valid(pdev, 0)) | ||
354 | pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1); | 353 | pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1); |
355 | err = pnp_manual_config_dev(pdev, cfg, 0); | 354 | err = pnp_manual_config_dev(pdev, cfg, 0); |
356 | if (err < 0) | 355 | if (err < 0) |
diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c index f0570f2bf75f..337b0e2a8a36 100644 --- a/sound/isa/gus/gus_io.c +++ b/sound/isa/gus/gus_io.c | |||
@@ -244,6 +244,8 @@ unsigned short snd_gf1_i_look16(snd_gus_card_t * gus, unsigned char reg) | |||
244 | return res; | 244 | return res; |
245 | } | 245 | } |
246 | 246 | ||
247 | #if 0 | ||
248 | |||
247 | void snd_gf1_i_adlib_write(snd_gus_card_t * gus, | 249 | void snd_gf1_i_adlib_write(snd_gus_card_t * gus, |
248 | unsigned char reg, | 250 | unsigned char reg, |
249 | unsigned char data) | 251 | unsigned char data) |
@@ -265,6 +267,8 @@ void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg, | |||
265 | spin_unlock_irqrestore(&gus->reg_lock, flags); | 267 | spin_unlock_irqrestore(&gus->reg_lock, flags); |
266 | } | 268 | } |
267 | 269 | ||
270 | #endif /* 0 */ | ||
271 | |||
268 | unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus, | 272 | unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus, |
269 | unsigned char reg, short w_16bit) | 273 | unsigned char reg, short w_16bit) |
270 | { | 274 | { |
@@ -329,6 +333,8 @@ unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr) | |||
329 | return res; | 333 | return res; |
330 | } | 334 | } |
331 | 335 | ||
336 | #if 0 | ||
337 | |||
332 | void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data) | 338 | void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data) |
333 | { | 339 | { |
334 | unsigned long flags; | 340 | unsigned long flags; |
@@ -405,9 +411,7 @@ void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr, | |||
405 | spin_unlock_irqrestore(&gus->reg_lock, flags); | 411 | spin_unlock_irqrestore(&gus->reg_lock, flags); |
406 | } | 412 | } |
407 | 413 | ||
408 | /* | 414 | #endif /* 0 */ |
409 | |||
410 | */ | ||
411 | 415 | ||
412 | void snd_gf1_select_active_voices(snd_gus_card_t * gus) | 416 | void snd_gf1_select_active_voices(snd_gus_card_t * gus) |
413 | { | 417 | { |
@@ -469,6 +473,8 @@ void snd_gf1_print_voice_registers(snd_gus_card_t * gus) | |||
469 | printk(" -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); | 473 | printk(" -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c)); |
470 | } | 474 | } |
471 | 475 | ||
476 | #if 0 | ||
477 | |||
472 | void snd_gf1_print_global_registers(snd_gus_card_t * gus) | 478 | void snd_gf1_print_global_registers(snd_gus_card_t * gus) |
473 | { | 479 | { |
474 | unsigned char global_mode = 0x00; | 480 | unsigned char global_mode = 0x00; |
@@ -528,4 +534,6 @@ void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count | |||
528 | } | 534 | } |
529 | } | 535 | } |
530 | 536 | ||
537 | #endif /* 0 */ | ||
538 | |||
531 | #endif | 539 | #endif |
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 73f81c14f768..a636d9ce3502 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c | |||
@@ -417,11 +417,13 @@ static int snd_gus_check_version(snd_gus_card_t * gus) | |||
417 | return 0; | 417 | return 0; |
418 | } | 418 | } |
419 | 419 | ||
420 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
420 | static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev) | 421 | static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev) |
421 | { | 422 | { |
422 | snd_gus_card_t *gus = seq_dev->private_data; | 423 | snd_gus_card_t *gus = seq_dev->private_data; |
423 | gus->seq_dev = NULL; | 424 | gus->seq_dev = NULL; |
424 | } | 425 | } |
426 | #endif | ||
425 | 427 | ||
426 | int snd_gus_initialize(snd_gus_card_t *gus) | 428 | int snd_gus_initialize(snd_gus_card_t *gus) |
427 | { | 429 | { |
@@ -459,7 +461,6 @@ EXPORT_SYMBOL(snd_gf1_write16); | |||
459 | EXPORT_SYMBOL(snd_gf1_look16); | 461 | EXPORT_SYMBOL(snd_gf1_look16); |
460 | EXPORT_SYMBOL(snd_gf1_i_write8); | 462 | EXPORT_SYMBOL(snd_gf1_i_write8); |
461 | EXPORT_SYMBOL(snd_gf1_i_look8); | 463 | EXPORT_SYMBOL(snd_gf1_i_look8); |
462 | EXPORT_SYMBOL(snd_gf1_i_write16); | ||
463 | EXPORT_SYMBOL(snd_gf1_i_look16); | 464 | EXPORT_SYMBOL(snd_gf1_i_look16); |
464 | EXPORT_SYMBOL(snd_gf1_dram_addr); | 465 | EXPORT_SYMBOL(snd_gf1_dram_addr); |
465 | EXPORT_SYMBOL(snd_gf1_write_addr); | 466 | EXPORT_SYMBOL(snd_gf1_write_addr); |
@@ -470,8 +471,6 @@ EXPORT_SYMBOL(snd_gf1_alloc_voice); | |||
470 | EXPORT_SYMBOL(snd_gf1_free_voice); | 471 | EXPORT_SYMBOL(snd_gf1_free_voice); |
471 | EXPORT_SYMBOL(snd_gf1_ctrl_stop); | 472 | EXPORT_SYMBOL(snd_gf1_ctrl_stop); |
472 | EXPORT_SYMBOL(snd_gf1_stop_voice); | 473 | EXPORT_SYMBOL(snd_gf1_stop_voice); |
473 | EXPORT_SYMBOL(snd_gf1_start); | ||
474 | EXPORT_SYMBOL(snd_gf1_stop); | ||
475 | /* gus_mixer.c */ | 474 | /* gus_mixer.c */ |
476 | EXPORT_SYMBOL(snd_gf1_new_mixer); | 475 | EXPORT_SYMBOL(snd_gf1_new_mixer); |
477 | /* gus_pcm.c */ | 476 | /* gus_pcm.c */ |
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index bfc2b91001d5..5eb766dd564b 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/string.h> | ||
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/gus.h> | 26 | #include <sound/gus.h> |
26 | #include <sound/info.h> | 27 | #include <sound/info.h> |
@@ -39,8 +40,8 @@ void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup) | |||
39 | } | 40 | } |
40 | } | 41 | } |
41 | 42 | ||
42 | snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc, | 43 | static snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc, |
43 | snd_gf1_mem_block_t * block) | 44 | snd_gf1_mem_block_t * block) |
44 | { | 45 | { |
45 | snd_gf1_mem_block_t *pblock, *nblock; | 46 | snd_gf1_mem_block_t *pblock, *nblock; |
46 | 47 | ||
@@ -105,8 +106,8 @@ int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block) | |||
105 | return 0; | 106 | return 0; |
106 | } | 107 | } |
107 | 108 | ||
108 | snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc, | 109 | static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc, |
109 | unsigned int address) | 110 | unsigned int address) |
110 | { | 111 | { |
111 | snd_gf1_mem_block_t *block; | 112 | snd_gf1_mem_block_t *block; |
112 | 113 | ||
@@ -118,8 +119,8 @@ snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc, | |||
118 | return NULL; | 119 | return NULL; |
119 | } | 120 | } |
120 | 121 | ||
121 | snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc, | 122 | static snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc, |
122 | unsigned int *share_id) | 123 | unsigned int *share_id) |
123 | { | 124 | { |
124 | snd_gf1_mem_block_t *block; | 125 | snd_gf1_mem_block_t *block; |
125 | 126 | ||
@@ -213,7 +214,7 @@ snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner, | |||
213 | if (share_id != NULL) | 214 | if (share_id != NULL) |
214 | memcpy(&block.share_id, share_id, sizeof(block.share_id)); | 215 | memcpy(&block.share_id, share_id, sizeof(block.share_id)); |
215 | block.owner = owner; | 216 | block.owner = owner; |
216 | block.name = snd_kmalloc_strdup(name, GFP_KERNEL); | 217 | block.name = kstrdup(name, GFP_KERNEL); |
217 | nblock = snd_gf1_mem_xalloc(alloc, &block); | 218 | nblock = snd_gf1_mem_xalloc(alloc, &block); |
218 | snd_gf1_mem_lock(alloc, 1); | 219 | snd_gf1_mem_lock(alloc, 1); |
219 | return nblock; | 220 | return nblock; |
@@ -253,13 +254,13 @@ int snd_gf1_mem_init(snd_gus_card_t * gus) | |||
253 | if (gus->gf1.enh_mode) { | 254 | if (gus->gf1.enh_mode) { |
254 | block.ptr = 0; | 255 | block.ptr = 0; |
255 | block.size = 1024; | 256 | block.size = 1024; |
256 | block.name = snd_kmalloc_strdup("InterWave LFOs", GFP_KERNEL); | 257 | block.name = kstrdup("InterWave LFOs", GFP_KERNEL); |
257 | if (snd_gf1_mem_xalloc(alloc, &block) == NULL) | 258 | if (snd_gf1_mem_xalloc(alloc, &block) == NULL) |
258 | return -ENOMEM; | 259 | return -ENOMEM; |
259 | } | 260 | } |
260 | block.ptr = gus->gf1.default_voice_address; | 261 | block.ptr = gus->gf1.default_voice_address; |
261 | block.size = 4; | 262 | block.size = 4; |
262 | block.name = snd_kmalloc_strdup("Voice default (NULL's)", GFP_KERNEL); | 263 | block.name = kstrdup("Voice default (NULL's)", GFP_KERNEL); |
263 | if (snd_gf1_mem_xalloc(alloc, &block) == NULL) | 264 | if (snd_gf1_mem_xalloc(alloc, &block) == NULL) |
264 | return -ENOMEM; | 265 | return -ENOMEM; |
265 | #ifdef CONFIG_SND_DEBUG | 266 | #ifdef CONFIG_SND_DEBUG |
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 8995ad9c516d..b75066ab46fc 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c | |||
@@ -656,8 +656,7 @@ static snd_pcm_hardware_t snd_gf1_pcm_capture = | |||
656 | 656 | ||
657 | static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime) | 657 | static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime) |
658 | { | 658 | { |
659 | gus_pcm_private_t * pcmp = runtime->private_data; | 659 | kfree(runtime->private_data); |
660 | kfree(pcmp); | ||
661 | } | 660 | } |
662 | 661 | ||
663 | static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream) | 662 | static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream) |
diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c index b4e66f6a10ae..ef687abc7070 100644 --- a/sound/isa/gus/gus_reset.c +++ b/sound/isa/gus/gus_reset.c | |||
@@ -161,7 +161,8 @@ void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice) | |||
161 | #endif | 161 | #endif |
162 | } | 162 | } |
163 | 163 | ||
164 | void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max) | 164 | static void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, |
165 | unsigned short v_max) | ||
165 | { | 166 | { |
166 | unsigned long flags; | 167 | unsigned long flags; |
167 | unsigned int daddr; | 168 | unsigned int daddr; |
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c index 66552e6013a4..f51c386ee192 100644 --- a/sound/isa/gus/gus_synth.c +++ b/sound/isa/gus/gus_synth.c | |||
@@ -99,7 +99,8 @@ static void snd_gus_synth_free_private_instruments(snd_gus_port_t *p, int client | |||
99 | snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0); | 99 | snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0); |
100 | } | 100 | } |
101 | 101 | ||
102 | int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int hop) | 102 | static int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct, |
103 | void *private_data, int atomic, int hop) | ||
103 | { | 104 | { |
104 | snd_gus_port_t * p = (snd_gus_port_t *) private_data; | 105 | snd_gus_port_t * p = (snd_gus_port_t *) private_data; |
105 | 106 | ||
diff --git a/sound/isa/gus/gus_tables.h b/sound/isa/gus/gus_tables.h index ed8e9d85ad31..4adf098d3269 100644 --- a/sound/isa/gus/gus_tables.h +++ b/sound/isa/gus/gus_tables.h | |||
@@ -23,6 +23,8 @@ | |||
23 | 23 | ||
24 | #ifdef __GUS_TABLES_ALLOC__ | 24 | #ifdef __GUS_TABLES_ALLOC__ |
25 | 25 | ||
26 | #if 0 | ||
27 | |||
26 | unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] = | 28 | unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] = |
27 | { | 29 | { |
28 | 8372, 8870, 9397, 9956, 10548, 11175, | 30 | 8372, 8870, 9397, 9956, 10548, 11175, |
@@ -49,6 +51,8 @@ unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] = | |||
49 | 12123977, 12844906 | 51 | 12123977, 12844906 |
50 | }; | 52 | }; |
51 | 53 | ||
54 | #endif /* 0 */ | ||
55 | |||
52 | unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE] = { | 56 | unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE] = { |
53 | 4095 /* 0 */,1789 /* 1 */,1533 /* 2 */,1383 /* 3 */,1277 /* 4 */, | 57 | 4095 /* 0 */,1789 /* 1 */,1533 /* 2 */,1383 /* 3 */,1277 /* 4 */, |
54 | 1195 /* 5 */,1127 /* 6 */,1070 /* 7 */,1021 /* 8 */,978 /* 9 */, | 58 | 1195 /* 5 */,1127 /* 6 */,1070 /* 7 */,1021 /* 8 */,978 /* 9 */, |
diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c index b72bcfb28617..3d36f6c8ee6a 100644 --- a/sound/isa/gus/gus_volume.c +++ b/sound/isa/gus/gus_volume.c | |||
@@ -55,6 +55,8 @@ unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol) | |||
55 | return (e << 8) | m; | 55 | return (e << 8) | m; |
56 | } | 56 | } |
57 | 57 | ||
58 | #if 0 | ||
59 | |||
58 | unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol) | 60 | unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol) |
59 | { | 61 | { |
60 | unsigned int rvol; | 62 | unsigned int rvol; |
@@ -108,6 +110,8 @@ unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus, | |||
108 | return (range << 6) | (increment & 0x3f); | 110 | return (range << 6) | (increment & 0x3f); |
109 | } | 111 | } |
110 | 112 | ||
113 | #endif /* 0 */ | ||
114 | |||
111 | unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16) | 115 | unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16) |
112 | { | 116 | { |
113 | freq16 >>= 3; | 117 | freq16 >>= 3; |
@@ -120,6 +124,8 @@ unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16) | |||
120 | return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq; | 124 | return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq; |
121 | } | 125 | } |
122 | 126 | ||
127 | #if 0 | ||
128 | |||
123 | short snd_gf1_compute_vibrato(short cents, unsigned short fc_register) | 129 | short snd_gf1_compute_vibrato(short cents, unsigned short fc_register) |
124 | { | 130 | { |
125 | static short vibrato_table[] = | 131 | static short vibrato_table[] = |
@@ -208,3 +214,5 @@ unsigned short snd_gf1_compute_freq(unsigned int freq, | |||
208 | } | 214 | } |
209 | return (unsigned short) fc; | 215 | return (unsigned short) fc; |
210 | } | 216 | } |
217 | |||
218 | #endif /* 0 */ | ||
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index 4afc4a1bc140..26e693078cb3 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c | |||
@@ -128,7 +128,7 @@ snd_emu8000_write_wait(emu8000_t *emu) | |||
128 | * This is therefore much slower than need be, but is at least | 128 | * This is therefore much slower than need be, but is at least |
129 | * working. | 129 | * working. |
130 | */ | 130 | */ |
131 | inline static void | 131 | static inline void |
132 | write_word(emu8000_t *emu, int *offset, unsigned short data) | 132 | write_word(emu8000_t *emu, int *offset, unsigned short data) |
133 | { | 133 | { |
134 | if (emu8000_reset_addr) { | 134 | if (emu8000_reset_addr) { |
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index cc5a2c6dec16..ff4b59968027 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c | |||
@@ -688,7 +688,7 @@ static struct sbmix_elem snd_als4000_ctl_3d_poweroff_switch = | |||
688 | SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01); | 688 | SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01); |
689 | static struct sbmix_elem snd_als4000_ctl_3d_delay = | 689 | static struct sbmix_elem snd_als4000_ctl_3d_delay = |
690 | SB_SINGLE("3D Delay", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f); | 690 | SB_SINGLE("3D Delay", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f); |
691 | #if NOT_AVAILABLE | 691 | #ifdef NOT_AVAILABLE |
692 | static struct sbmix_elem snd_als4000_ctl_fmdac = | 692 | static struct sbmix_elem snd_als4000_ctl_fmdac = |
693 | SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01); | 693 | SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01); |
694 | static struct sbmix_elem snd_als4000_ctl_qsound = | 694 | static struct sbmix_elem snd_als4000_ctl_qsound = |
@@ -723,7 +723,7 @@ static struct sbmix_elem *snd_als4000_controls[] = { | |||
723 | &snd_als4000_ctl_3d_output_ratio, | 723 | &snd_als4000_ctl_3d_output_ratio, |
724 | &snd_als4000_ctl_3d_delay, | 724 | &snd_als4000_ctl_3d_delay, |
725 | &snd_als4000_ctl_3d_poweroff_switch, | 725 | &snd_als4000_ctl_3d_poweroff_switch, |
726 | #if NOT_AVAILABLE | 726 | #ifdef NOT_AVAILABLE |
727 | &snd_als4000_ctl_fmdac, | 727 | &snd_als4000_ctl_fmdac, |
728 | &snd_als4000_ctl_qsound, | 728 | &snd_als4000_ctl_qsound, |
729 | #endif | 729 | #endif |
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c index 0e13623f69f0..32379688eed4 100644 --- a/sound/isa/wavefront/wavefront_fx.c +++ b/sound/isa/wavefront/wavefront_fx.c | |||
@@ -34,7 +34,7 @@ | |||
34 | 34 | ||
35 | /* weird stuff, derived from port I/O tracing with dosemu */ | 35 | /* weird stuff, derived from port I/O tracing with dosemu */ |
36 | 36 | ||
37 | unsigned char page_zero[] __initdata = { | 37 | static unsigned char page_zero[] __initdata = { |
38 | 0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00, | 38 | 0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00, |
39 | 0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00, | 39 | 0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00, |
40 | 0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00, | 40 | 0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00, |
@@ -61,7 +61,7 @@ unsigned char page_zero[] __initdata = { | |||
61 | 0x1d, 0x02, 0xdf | 61 | 0x1d, 0x02, 0xdf |
62 | }; | 62 | }; |
63 | 63 | ||
64 | unsigned char page_one[] __initdata = { | 64 | static unsigned char page_one[] __initdata = { |
65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00, | 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00, |
66 | 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00, | 66 | 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00, |
67 | 0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, | 67 | 0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, |
@@ -88,7 +88,7 @@ unsigned char page_one[] __initdata = { | |||
88 | 0x60, 0x00, 0x1b | 88 | 0x60, 0x00, 0x1b |
89 | }; | 89 | }; |
90 | 90 | ||
91 | unsigned char page_two[] __initdata = { | 91 | static unsigned char page_two[] __initdata = { |
92 | 0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4, | 92 | 0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4, |
93 | 0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, | 93 | 0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, |
94 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 94 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -103,7 +103,7 @@ unsigned char page_two[] __initdata = { | |||
103 | 0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44 | 103 | 0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44 |
104 | }; | 104 | }; |
105 | 105 | ||
106 | unsigned char page_three[] __initdata = { | 106 | static unsigned char page_three[] __initdata = { |
107 | 0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06, | 107 | 0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06, |
108 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 108 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -118,7 +118,7 @@ unsigned char page_three[] __initdata = { | |||
118 | 0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40 | 118 | 0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40 |
119 | }; | 119 | }; |
120 | 120 | ||
121 | unsigned char page_four[] __initdata = { | 121 | static unsigned char page_four[] __initdata = { |
122 | 0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02, | 122 | 0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02, |
123 | 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 123 | 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
124 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 124 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -133,7 +133,7 @@ unsigned char page_four[] __initdata = { | |||
133 | 0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01 | 133 | 0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01 |
134 | }; | 134 | }; |
135 | 135 | ||
136 | unsigned char page_six[] __initdata = { | 136 | static unsigned char page_six[] __initdata = { |
137 | 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, | 137 | 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, |
138 | 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e, | 138 | 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e, |
139 | 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00, | 139 | 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00, |
@@ -154,7 +154,7 @@ unsigned char page_six[] __initdata = { | |||
154 | 0x80, 0x00, 0x7e, 0x80, 0x80 | 154 | 0x80, 0x00, 0x7e, 0x80, 0x80 |
155 | }; | 155 | }; |
156 | 156 | ||
157 | unsigned char page_seven[] __initdata = { | 157 | static unsigned char page_seven[] __initdata = { |
158 | 0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, | 158 | 0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, |
159 | 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, | 159 | 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, |
160 | 0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, | 160 | 0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, |
@@ -181,7 +181,7 @@ unsigned char page_seven[] __initdata = { | |||
181 | 0x00, 0x02, 0x00 | 181 | 0x00, 0x02, 0x00 |
182 | }; | 182 | }; |
183 | 183 | ||
184 | unsigned char page_zero_v2[] __initdata = { | 184 | static unsigned char page_zero_v2[] __initdata = { |
185 | 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 185 | 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
186 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 186 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
187 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 187 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -193,7 +193,7 @@ unsigned char page_zero_v2[] __initdata = { | |||
193 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 193 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
194 | }; | 194 | }; |
195 | 195 | ||
196 | unsigned char page_one_v2[] __initdata = { | 196 | static unsigned char page_one_v2[] __initdata = { |
197 | 0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, | 197 | 0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, |
198 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 198 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
199 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 199 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -205,21 +205,21 @@ unsigned char page_one_v2[] __initdata = { | |||
205 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 205 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
206 | }; | 206 | }; |
207 | 207 | ||
208 | unsigned char page_two_v2[] __initdata = { | 208 | static unsigned char page_two_v2[] __initdata = { |
209 | 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 209 | 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
210 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 210 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
211 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 211 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
212 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 212 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
213 | 0x00, 0x00, 0x00, 0x00 | 213 | 0x00, 0x00, 0x00, 0x00 |
214 | }; | 214 | }; |
215 | unsigned char page_three_v2[] __initdata = { | 215 | static unsigned char page_three_v2[] __initdata = { |
216 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 216 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
217 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 217 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
218 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 218 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
219 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 219 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
220 | 0x00, 0x00, 0x00, 0x00 | 220 | 0x00, 0x00, 0x00, 0x00 |
221 | }; | 221 | }; |
222 | unsigned char page_four_v2[] __initdata = { | 222 | static unsigned char page_four_v2[] __initdata = { |
223 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 223 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
224 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 224 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
225 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 225 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -227,7 +227,7 @@ unsigned char page_four_v2[] __initdata = { | |||
227 | 0x00, 0x00, 0x00, 0x00 | 227 | 0x00, 0x00, 0x00, 0x00 |
228 | }; | 228 | }; |
229 | 229 | ||
230 | unsigned char page_seven_v2[] __initdata = { | 230 | static unsigned char page_seven_v2[] __initdata = { |
231 | 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 231 | 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
232 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 232 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
233 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 233 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -239,7 +239,7 @@ unsigned char page_seven_v2[] __initdata = { | |||
239 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 239 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
240 | }; | 240 | }; |
241 | 241 | ||
242 | unsigned char mod_v2[] __initdata = { | 242 | static unsigned char mod_v2[] __initdata = { |
243 | 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, | 243 | 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, |
244 | 0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05, | 244 | 0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05, |
245 | 0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0, | 245 | 0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0, |
@@ -269,7 +269,7 @@ unsigned char mod_v2[] __initdata = { | |||
269 | 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01, | 269 | 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01, |
270 | 0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01 | 270 | 0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01 |
271 | }; | 271 | }; |
272 | unsigned char coefficients[] __initdata = { | 272 | static unsigned char coefficients[] __initdata = { |
273 | 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03, | 273 | 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03, |
274 | 0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, | 274 | 0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, |
275 | 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01, | 275 | 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01, |
@@ -305,14 +305,14 @@ unsigned char coefficients[] __initdata = { | |||
305 | 0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02, | 305 | 0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02, |
306 | 0xba | 306 | 0xba |
307 | }; | 307 | }; |
308 | unsigned char coefficients2[] __initdata = { | 308 | static unsigned char coefficients2[] __initdata = { |
309 | 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f, | 309 | 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f, |
310 | 0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d, | 310 | 0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d, |
311 | 0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07, | 311 | 0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07, |
312 | 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, | 312 | 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, |
313 | 0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00 | 313 | 0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00 |
314 | }; | 314 | }; |
315 | unsigned char coefficients3[] __initdata = { | 315 | static unsigned char coefficients3[] __initdata = { |
316 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00, | 316 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00, |
317 | 0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc, | 317 | 0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc, |
318 | 0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01, | 318 | 0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01, |
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index e537bd66a707..7bd95ceab7cc 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig | |||
@@ -6,7 +6,7 @@ | |||
6 | # Prompt user for primary drivers. | 6 | # Prompt user for primary drivers. |
7 | config SOUND_BT878 | 7 | config SOUND_BT878 |
8 | tristate "BT878 audio dma" | 8 | tristate "BT878 audio dma" |
9 | depends on SOUND_PRIME!=n && SOUND | 9 | depends on SOUND_PRIME |
10 | ---help--- | 10 | ---help--- |
11 | Audio DMA support for bt878 based grabber boards. As you might have | 11 | Audio DMA support for bt878 based grabber boards. As you might have |
12 | already noticed, bt878 is listed with two functions in /proc/pci. | 12 | already noticed, bt878 is listed with two functions in /proc/pci. |
@@ -22,7 +22,7 @@ config SOUND_BT878 | |||
22 | 22 | ||
23 | config SOUND_CMPCI | 23 | config SOUND_CMPCI |
24 | tristate "C-Media PCI (CMI8338/8738)" | 24 | tristate "C-Media PCI (CMI8338/8738)" |
25 | depends on SOUND_PRIME!=n && SOUND && PCI | 25 | depends on SOUND_PRIME && PCI |
26 | help | 26 | help |
27 | Say Y or M if you have a PCI sound card using the CMI8338 | 27 | Say Y or M if you have a PCI sound card using the CMI8338 |
28 | or the CMI8738 chipset. Data on these chips are available at | 28 | or the CMI8738 chipset. Data on these chips are available at |
@@ -52,7 +52,7 @@ config SOUND_CMPCI_MIDI | |||
52 | 52 | ||
53 | config SOUND_CMPCI_JOYSTICK | 53 | config SOUND_CMPCI_JOYSTICK |
54 | bool "Enable joystick" | 54 | bool "Enable joystick" |
55 | depends on SOUND_CMPCI && X86 | 55 | depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT) |
56 | help | 56 | help |
57 | Say Y here in order to enable the joystick port on a sound card using | 57 | Say Y here in order to enable the joystick port on a sound card using |
58 | the CMI8338 or the CMI8738 chipset. You need to config the | 58 | the CMI8338 or the CMI8738 chipset. You need to config the |
@@ -61,7 +61,7 @@ config SOUND_CMPCI_JOYSTICK | |||
61 | 61 | ||
62 | config SOUND_EMU10K1 | 62 | config SOUND_EMU10K1 |
63 | tristate "Creative SBLive! (EMU10K1)" | 63 | tristate "Creative SBLive! (EMU10K1)" |
64 | depends on SOUND_PRIME!=n && SOUND && PCI | 64 | depends on SOUND_PRIME && PCI |
65 | ---help--- | 65 | ---help--- |
66 | Say Y or M if you have a PCI sound card using the EMU10K1 chipset, | 66 | Say Y or M if you have a PCI sound card using the EMU10K1 chipset, |
67 | such as the Creative SBLive!, SB PCI512 or Emu-APS. | 67 | such as the Creative SBLive!, SB PCI512 or Emu-APS. |
@@ -87,7 +87,7 @@ config MIDI_EMU10K1 | |||
87 | 87 | ||
88 | config SOUND_FUSION | 88 | config SOUND_FUSION |
89 | tristate "Crystal SoundFusion (CS4280/461x)" | 89 | tristate "Crystal SoundFusion (CS4280/461x)" |
90 | depends on SOUND_PRIME!=n && SOUND | 90 | depends on SOUND_PRIME |
91 | help | 91 | help |
92 | This module drives the Crystal SoundFusion devices (CS4280/46xx | 92 | This module drives the Crystal SoundFusion devices (CS4280/46xx |
93 | series) when wired as native sound drivers with AC97 codecs. If | 93 | series) when wired as native sound drivers with AC97 codecs. If |
@@ -95,14 +95,14 @@ config SOUND_FUSION | |||
95 | 95 | ||
96 | config SOUND_CS4281 | 96 | config SOUND_CS4281 |
97 | tristate "Crystal Sound CS4281" | 97 | tristate "Crystal Sound CS4281" |
98 | depends on SOUND_PRIME!=n && SOUND | 98 | depends on SOUND_PRIME |
99 | help | 99 | help |
100 | Picture and feature list at | 100 | Picture and feature list at |
101 | <http://www.pcbroker.com/crystal4281.html>. | 101 | <http://www.pcbroker.com/crystal4281.html>. |
102 | 102 | ||
103 | config SOUND_BCM_CS4297A | 103 | config SOUND_BCM_CS4297A |
104 | tristate "Crystal Sound CS4297a (for Swarm)" | 104 | tristate "Crystal Sound CS4297a (for Swarm)" |
105 | depends on SOUND_PRIME!=n && SIBYTE_SWARM && SOUND | 105 | depends on SOUND_PRIME && SIBYTE_SWARM |
106 | help | 106 | help |
107 | The BCM91250A has a Crystal CS4297a on synchronous serial | 107 | The BCM91250A has a Crystal CS4297a on synchronous serial |
108 | port B (in addition to the DB-9 serial port). Say Y or M | 108 | port B (in addition to the DB-9 serial port). Say Y or M |
@@ -112,7 +112,7 @@ config SOUND_BCM_CS4297A | |||
112 | 112 | ||
113 | config SOUND_ES1370 | 113 | config SOUND_ES1370 |
114 | tristate "Ensoniq AudioPCI (ES1370)" | 114 | tristate "Ensoniq AudioPCI (ES1370)" |
115 | depends on SOUND_PRIME!=n && SOUND && PCI | 115 | depends on SOUND_PRIME && PCI |
116 | help | 116 | help |
117 | Say Y or M if you have a PCI sound card utilizing the Ensoniq | 117 | Say Y or M if you have a PCI sound card utilizing the Ensoniq |
118 | ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find | 118 | ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find |
@@ -125,7 +125,7 @@ config SOUND_ES1370 | |||
125 | 125 | ||
126 | config SOUND_ES1371 | 126 | config SOUND_ES1371 |
127 | tristate "Creative Ensoniq AudioPCI 97 (ES1371)" | 127 | tristate "Creative Ensoniq AudioPCI 97 (ES1371)" |
128 | depends on SOUND_PRIME!=n && SOUND && PCI | 128 | depends on SOUND_PRIME && PCI |
129 | help | 129 | help |
130 | Say Y or M if you have a PCI sound card utilizing the Ensoniq | 130 | Say Y or M if you have a PCI sound card utilizing the Ensoniq |
131 | ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if | 131 | ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if |
@@ -138,7 +138,7 @@ config SOUND_ES1371 | |||
138 | 138 | ||
139 | config SOUND_ESSSOLO1 | 139 | config SOUND_ESSSOLO1 |
140 | tristate "ESS Technology Solo1" | 140 | tristate "ESS Technology Solo1" |
141 | depends on SOUND_PRIME!=n && SOUND && PCI | 141 | depends on SOUND_PRIME && PCI |
142 | help | 142 | help |
143 | Say Y or M if you have a PCI sound card utilizing the ESS Technology | 143 | Say Y or M if you have a PCI sound card utilizing the ESS Technology |
144 | Solo1 chip. To find out if your sound card uses a | 144 | Solo1 chip. To find out if your sound card uses a |
@@ -149,7 +149,7 @@ config SOUND_ESSSOLO1 | |||
149 | 149 | ||
150 | config SOUND_MAESTRO | 150 | config SOUND_MAESTRO |
151 | tristate "ESS Maestro, Maestro2, Maestro2E driver" | 151 | tristate "ESS Maestro, Maestro2, Maestro2E driver" |
152 | depends on SOUND_PRIME!=n && SOUND && PCI | 152 | depends on SOUND_PRIME && PCI |
153 | help | 153 | help |
154 | Say Y or M if you have a sound system driven by ESS's Maestro line | 154 | Say Y or M if you have a sound system driven by ESS's Maestro line |
155 | of PCI sound chips. These include the Maestro 1, Maestro 2, and | 155 | of PCI sound chips. These include the Maestro 1, Maestro 2, and |
@@ -158,28 +158,28 @@ config SOUND_MAESTRO | |||
158 | 158 | ||
159 | config SOUND_MAESTRO3 | 159 | config SOUND_MAESTRO3 |
160 | tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)" | 160 | tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)" |
161 | depends on SOUND_PRIME!=n && SOUND && PCI && EXPERIMENTAL | 161 | depends on SOUND_PRIME && PCI && EXPERIMENTAL |
162 | help | 162 | help |
163 | Say Y or M if you have a sound system driven by ESS's Maestro 3 | 163 | Say Y or M if you have a sound system driven by ESS's Maestro 3 |
164 | PCI sound chip. | 164 | PCI sound chip. |
165 | 165 | ||
166 | config SOUND_ICH | 166 | config SOUND_ICH |
167 | tristate "Intel ICH (i8xx) audio support" | 167 | tristate "Intel ICH (i8xx) audio support" |
168 | depends on SOUND_PRIME!=n && PCI | 168 | depends on SOUND_PRIME && PCI |
169 | help | 169 | help |
170 | Support for integral audio in Intel's I/O Controller Hub (ICH) | 170 | Support for integral audio in Intel's I/O Controller Hub (ICH) |
171 | chipset, as used on the 810/820/840 motherboards. | 171 | chipset, as used on the 810/820/840 motherboards. |
172 | 172 | ||
173 | config SOUND_HARMONY | 173 | config SOUND_HARMONY |
174 | tristate "PA Harmony audio driver" | 174 | tristate "PA Harmony audio driver" |
175 | depends on GSC_LASI && SOUND_PRIME!=n | 175 | depends on GSC_LASI && SOUND_PRIME |
176 | help | 176 | help |
177 | Say 'Y' or 'M' to include support for Harmony soundchip | 177 | Say 'Y' or 'M' to include support for Harmony soundchip |
178 | on HP 712, 715/new and many other GSC based machines. | 178 | on HP 712, 715/new and many other GSC based machines. |
179 | 179 | ||
180 | config SOUND_SONICVIBES | 180 | config SOUND_SONICVIBES |
181 | tristate "S3 SonicVibes" | 181 | tristate "S3 SonicVibes" |
182 | depends on SOUND_PRIME!=n && SOUND | 182 | depends on SOUND_PRIME |
183 | help | 183 | help |
184 | Say Y or M if you have a PCI sound card utilizing the S3 | 184 | Say Y or M if you have a PCI sound card utilizing the S3 |
185 | SonicVibes chipset. To find out if your sound card uses a | 185 | SonicVibes chipset. To find out if your sound card uses a |
@@ -190,7 +190,7 @@ config SOUND_SONICVIBES | |||
190 | 190 | ||
191 | config SOUND_VWSND | 191 | config SOUND_VWSND |
192 | tristate "SGI Visual Workstation Sound" | 192 | tristate "SGI Visual Workstation Sound" |
193 | depends on SOUND_PRIME!=n && X86_VISWS && SOUND | 193 | depends on SOUND_PRIME && X86_VISWS |
194 | help | 194 | help |
195 | Say Y or M if you have an SGI Visual Workstation and you want to be | 195 | Say Y or M if you have an SGI Visual Workstation and you want to be |
196 | able to use its on-board audio. Read | 196 | able to use its on-board audio. Read |
@@ -199,18 +199,18 @@ config SOUND_VWSND | |||
199 | 199 | ||
200 | config SOUND_HAL2 | 200 | config SOUND_HAL2 |
201 | tristate "SGI HAL2 sound (EXPERIMENTAL)" | 201 | tristate "SGI HAL2 sound (EXPERIMENTAL)" |
202 | depends on SOUND_PRIME!=n && SOUND && SGI_IP22 && EXPERIMENTAL | 202 | depends on SOUND_PRIME && SGI_IP22 && EXPERIMENTAL |
203 | help | 203 | help |
204 | Say Y or M if you have an SGI Indy system and want to be able to | 204 | Say Y or M if you have an SGI Indy system and want to be able to |
205 | use it's on-board A2 audio system. | 205 | use it's on-board A2 audio system. |
206 | 206 | ||
207 | config SOUND_IT8172 | 207 | config SOUND_IT8172 |
208 | tristate "IT8172G Sound" | 208 | tristate "IT8172G Sound" |
209 | depends on SOUND_PRIME!=n && (MIPS_ITE8172 || MIPS_IVR) && SOUND | 209 | depends on SOUND_PRIME && (MIPS_ITE8172 || MIPS_IVR) |
210 | 210 | ||
211 | config SOUND_VRC5477 | 211 | config SOUND_VRC5477 |
212 | tristate "NEC Vrc5477 AC97 sound" | 212 | tristate "NEC Vrc5477 AC97 sound" |
213 | depends on SOUND_PRIME!=n && DDB5477 && SOUND | 213 | depends on SOUND_PRIME && DDB5477 |
214 | help | 214 | help |
215 | Say Y here to enable sound support for the NEC Vrc5477 chip, an | 215 | Say Y here to enable sound support for the NEC Vrc5477 chip, an |
216 | integrated, multi-function controller chip for MIPS CPUs. Works | 216 | integrated, multi-function controller chip for MIPS CPUs. Works |
@@ -218,15 +218,15 @@ config SOUND_VRC5477 | |||
218 | 218 | ||
219 | config SOUND_AU1000 | 219 | config SOUND_AU1000 |
220 | tristate "Au1000 Sound" | 220 | tristate "Au1000 Sound" |
221 | depends on SOUND_PRIME!=n && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SOUND | 221 | depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) |
222 | 222 | ||
223 | config SOUND_AU1550_AC97 | 223 | config SOUND_AU1550_AC97 |
224 | tristate "Au1550 AC97 Sound" | 224 | tristate "Au1550 AC97 Sound" |
225 | depends on SOUND_PRIME!=n && SOC_AU1550 && SOUND | 225 | depends on SOUND_PRIME && SOC_AU1550 |
226 | 226 | ||
227 | config SOUND_TRIDENT | 227 | config SOUND_TRIDENT |
228 | tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core" | 228 | tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core" |
229 | depends on SOUND_PRIME!=n && SOUND | 229 | depends on SOUND_PRIME |
230 | ---help--- | 230 | ---help--- |
231 | Say Y or M if you have a PCI sound card utilizing the Trident | 231 | Say Y or M if you have a PCI sound card utilizing the Trident |
232 | 4DWave-DX/NX chipset or your mother board chipset has SiS 7018 | 232 | 4DWave-DX/NX chipset or your mother board chipset has SiS 7018 |
@@ -267,7 +267,7 @@ config SOUND_TRIDENT | |||
267 | 267 | ||
268 | config SOUND_MSNDCLAS | 268 | config SOUND_MSNDCLAS |
269 | tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" | 269 | tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" |
270 | depends on SOUND_PRIME!=n && SOUND && (m || !STANDALONE) | 270 | depends on SOUND_PRIME && (m || !STANDALONE) |
271 | help | 271 | help |
272 | Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or | 272 | Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or |
273 | Monterey (not for the Pinnacle or Fiji). | 273 | Monterey (not for the Pinnacle or Fiji). |
@@ -331,7 +331,7 @@ config MSNDCLAS_IO | |||
331 | 331 | ||
332 | config SOUND_MSNDPIN | 332 | config SOUND_MSNDPIN |
333 | tristate "Support for Turtle Beach MultiSound Pinnacle, Fiji" | 333 | tristate "Support for Turtle Beach MultiSound Pinnacle, Fiji" |
334 | depends on SOUND_PRIME!=n && SOUND && (m || !STANDALONE) | 334 | depends on SOUND_PRIME && (m || !STANDALONE) |
335 | help | 335 | help |
336 | Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji. | 336 | Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji. |
337 | See <file:Documentation/sound/oss/MultiSound> for important information | 337 | See <file:Documentation/sound/oss/MultiSound> for important information |
@@ -492,7 +492,7 @@ config MSND_FIFOSIZE | |||
492 | 492 | ||
493 | config SOUND_VIA82CXXX | 493 | config SOUND_VIA82CXXX |
494 | tristate "VIA 82C686 Audio Codec" | 494 | tristate "VIA 82C686 Audio Codec" |
495 | depends on SOUND_PRIME!=n && PCI | 495 | depends on SOUND_PRIME && PCI |
496 | help | 496 | help |
497 | Say Y here to include support for the audio codec found on VIA | 497 | Say Y here to include support for the audio codec found on VIA |
498 | 82Cxxx-based chips. Typically these are built into a motherboard. | 498 | 82Cxxx-based chips. Typically these are built into a motherboard. |
@@ -512,7 +512,7 @@ config MIDI_VIA82CXXX | |||
512 | 512 | ||
513 | config SOUND_OSS | 513 | config SOUND_OSS |
514 | tristate "OSS sound modules" | 514 | tristate "OSS sound modules" |
515 | depends on SOUND_PRIME!=n && SOUND | 515 | depends on SOUND_PRIME |
516 | help | 516 | help |
517 | OSS is the Open Sound System suite of sound card drivers. They make | 517 | OSS is the Open Sound System suite of sound card drivers. They make |
518 | sound programming easier since they provide a common API. Say Y or | 518 | sound programming easier since they provide a common API. Say Y or |
@@ -1077,7 +1077,7 @@ config SOUND_WAVEARTIST | |||
1077 | 1077 | ||
1078 | config SOUND_TVMIXER | 1078 | config SOUND_TVMIXER |
1079 | tristate "TV card (bt848) mixer support" | 1079 | tristate "TV card (bt848) mixer support" |
1080 | depends on SOUND_PRIME!=n && SOUND && I2C | 1080 | depends on SOUND_PRIME && I2C |
1081 | help | 1081 | help |
1082 | Support for audio mixer facilities on the BT848 TV frame-grabber | 1082 | Support for audio mixer facilities on the BT848 TV frame-grabber |
1083 | card. | 1083 | card. |
@@ -1088,11 +1088,11 @@ config SOUND_KAHLUA | |||
1088 | 1088 | ||
1089 | config SOUND_ALI5455 | 1089 | config SOUND_ALI5455 |
1090 | tristate "ALi5455 audio support" | 1090 | tristate "ALi5455 audio support" |
1091 | depends on SOUND_PRIME!=n && PCI | 1091 | depends on SOUND_PRIME && PCI |
1092 | 1092 | ||
1093 | config SOUND_FORTE | 1093 | config SOUND_FORTE |
1094 | tristate "ForteMedia FM801 driver" | 1094 | tristate "ForteMedia FM801 driver" |
1095 | depends on SOUND_PRIME!=n && PCI | 1095 | depends on SOUND_PRIME && PCI |
1096 | help | 1096 | help |
1097 | Say Y or M if you want driver support for the ForteMedia FM801 PCI | 1097 | Say Y or M if you want driver support for the ForteMedia FM801 PCI |
1098 | audio controller (Abit AU10, Genius Sound Maker, HP Workstation | 1098 | audio controller (Abit AU10, Genius Sound Maker, HP Workstation |
@@ -1100,7 +1100,7 @@ config SOUND_FORTE | |||
1100 | 1100 | ||
1101 | config SOUND_RME96XX | 1101 | config SOUND_RME96XX |
1102 | tristate "RME Hammerfall (RME96XX) support" | 1102 | tristate "RME Hammerfall (RME96XX) support" |
1103 | depends on SOUND_PRIME!=n && PCI | 1103 | depends on SOUND_PRIME && PCI |
1104 | help | 1104 | help |
1105 | Say Y or M if you have a Hammerfall or Hammerfall light | 1105 | Say Y or M if you have a Hammerfall or Hammerfall light |
1106 | multichannel card from RME. If you want to access advanced | 1106 | multichannel card from RME. If you want to access advanced |
@@ -1108,11 +1108,11 @@ config SOUND_RME96XX | |||
1108 | 1108 | ||
1109 | config SOUND_AD1980 | 1109 | config SOUND_AD1980 |
1110 | tristate "AD1980 front/back switch plugin" | 1110 | tristate "AD1980 front/back switch plugin" |
1111 | depends on SOUND_PRIME!=n | 1111 | depends on SOUND_PRIME |
1112 | 1112 | ||
1113 | config SOUND_SH_DAC_AUDIO | 1113 | config SOUND_SH_DAC_AUDIO |
1114 | tristate "SuperH DAC audio support" | 1114 | tristate "SuperH DAC audio support" |
1115 | depends on SOUND_PRIME!=n && SOUND && CPU_SH3 | 1115 | depends on SOUND_PRIME && CPU_SH3 |
1116 | 1116 | ||
1117 | config SOUND_SH_DAC_AUDIO_CHANNEL | 1117 | config SOUND_SH_DAC_AUDIO_CHANNEL |
1118 | int " DAC channel" | 1118 | int " DAC channel" |
diff --git a/sound/oss/ad1816.c b/sound/oss/ad1816.c index 22dae5d0fda3..95586de02028 100644 --- a/sound/oss/ad1816.c +++ b/sound/oss/ad1816.c | |||
@@ -592,7 +592,7 @@ typedef struct mixer_def mixer_ent; | |||
592 | {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}} | 592 | {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}} |
593 | 593 | ||
594 | 594 | ||
595 | mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = { | 595 | static mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = { |
596 | MIX_ENT(SOUND_MIXER_VOLUME, 14, 1, 8, 5, 14, 1, 0, 5), | 596 | MIX_ENT(SOUND_MIXER_VOLUME, 14, 1, 8, 5, 14, 1, 0, 5), |
597 | MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0), | 597 | MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0), |
598 | MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0), | 598 | MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0), |
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index 4384dac3f794..7c835abd99bc 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c | |||
@@ -2178,8 +2178,7 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int | |||
2178 | 2178 | ||
2179 | if (devc != NULL) | 2179 | if (devc != NULL) |
2180 | { | 2180 | { |
2181 | if(audio_devs[dev]->portc!=NULL) | 2181 | kfree(audio_devs[dev]->portc); |
2182 | kfree(audio_devs[dev]->portc); | ||
2183 | release_region(devc->base, 4); | 2182 | release_region(devc->base, 4); |
2184 | 2183 | ||
2185 | if (!share_dma) | 2184 | if (!share_dma) |
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c index b767c621fd09..2cfd214e4c2a 100644 --- a/sound/oss/ad1889.c +++ b/sound/oss/ad1889.c | |||
@@ -277,8 +277,7 @@ static void ad1889_free_dev(ad1889_dev_t *dev) | |||
277 | 277 | ||
278 | for (j = 0; j < AD_MAX_STATES; j++) { | 278 | for (j = 0; j < AD_MAX_STATES; j++) { |
279 | dmabuf = &dev->state[j].dmabuf; | 279 | dmabuf = &dev->state[j].dmabuf; |
280 | if (dmabuf->rawbuf != NULL) | 280 | kfree(dmabuf->rawbuf); |
281 | kfree(dmabuf->rawbuf); | ||
282 | } | 281 | } |
283 | 282 | ||
284 | kfree(dev); | 283 | kfree(dev); |
diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c index 34720e66dae1..74dcca78c6c0 100644 --- a/sound/oss/cmpci.c +++ b/sound/oss/cmpci.c | |||
@@ -123,6 +123,7 @@ | |||
123 | #include <linux/smp_lock.h> | 123 | #include <linux/smp_lock.h> |
124 | #include <linux/bitops.h> | 124 | #include <linux/bitops.h> |
125 | #include <linux/wait.h> | 125 | #include <linux/wait.h> |
126 | #include <linux/dma-mapping.h> | ||
126 | 127 | ||
127 | #include <asm/io.h> | 128 | #include <asm/io.h> |
128 | #include <asm/page.h> | 129 | #include <asm/page.h> |
@@ -3058,7 +3059,7 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id | |||
3058 | return -ENODEV; | 3059 | return -ENODEV; |
3059 | if (pcidev->irq == 0) | 3060 | if (pcidev->irq == 0) |
3060 | return -ENODEV; | 3061 | return -ENODEV; |
3061 | i = pci_set_dma_mask(pcidev, 0xffffffff); | 3062 | i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); |
3062 | if (i) { | 3063 | if (i) { |
3063 | printk(KERN_WARNING "cmpci: architecture does not support 32bit PCI busmaster DMA\n"); | 3064 | printk(KERN_WARNING "cmpci: architecture does not support 32bit PCI busmaster DMA\n"); |
3064 | return i; | 3065 | return i; |
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c index 9e42a1a67ca4..cb998e8c0fdd 100644 --- a/sound/oss/cs46xx.c +++ b/sound/oss/cs46xx.c | |||
@@ -4174,7 +4174,7 @@ static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int | |||
4174 | list_for_each(entry, &cs46xx_devs) | 4174 | list_for_each(entry, &cs46xx_devs) |
4175 | { | 4175 | { |
4176 | card = list_entry(entry, struct cs_card, list); | 4176 | card = list_entry(entry, struct cs_card, list); |
4177 | cs46xx_suspend(card, 0); | 4177 | cs46xx_suspend(card, PMSG_ON); |
4178 | } | 4178 | } |
4179 | 4179 | ||
4180 | } | 4180 | } |
@@ -5749,7 +5749,7 @@ static int cs46xx_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) | |||
5749 | case PM_SUSPEND: | 5749 | case PM_SUSPEND: |
5750 | CS_DBGOUT(CS_PM, 2, printk(KERN_INFO | 5750 | CS_DBGOUT(CS_PM, 2, printk(KERN_INFO |
5751 | "cs46xx: PM suspend request\n")); | 5751 | "cs46xx: PM suspend request\n")); |
5752 | if(cs46xx_suspend(card, 0)) | 5752 | if(cs46xx_suspend(card, PMSG_SUSPEND)) |
5753 | { | 5753 | { |
5754 | CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO | 5754 | CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO |
5755 | "cs46xx: PM suspend request refused\n")); | 5755 | "cs46xx: PM suspend request refused\n")); |
@@ -5779,7 +5779,7 @@ static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state) | |||
5779 | struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev); | 5779 | struct cs_card *s = PCI_GET_DRIVER_DATA(pcidev); |
5780 | CS_DBGOUT(CS_PM | CS_FUNCTION, 2, | 5780 | CS_DBGOUT(CS_PM | CS_FUNCTION, 2, |
5781 | printk(KERN_INFO "cs46xx: cs46xx_suspend_tbl request\n")); | 5781 | printk(KERN_INFO "cs46xx: cs46xx_suspend_tbl request\n")); |
5782 | cs46xx_suspend(s, 0); | 5782 | cs46xx_suspend(s, state); |
5783 | return 0; | 5783 | return 0; |
5784 | } | 5784 | } |
5785 | 5785 | ||
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index 5281b88987f3..2ceb46f1d40f 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c | |||
@@ -255,7 +255,7 @@ static int awacs_burgundy_read_mvolume(unsigned address); | |||
255 | 255 | ||
256 | static volatile struct dbdma_cmd *emergency_dbdma_cmd; | 256 | static volatile struct dbdma_cmd *emergency_dbdma_cmd; |
257 | 257 | ||
258 | #ifdef CONFIG_PMAC_PBOOK | 258 | #ifdef CONFIG_PM |
259 | /* | 259 | /* |
260 | * Stuff for restoring after a sleep. | 260 | * Stuff for restoring after a sleep. |
261 | */ | 261 | */ |
@@ -263,7 +263,7 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when); | |||
263 | struct pmu_sleep_notifier awacs_sleep_notifier = { | 263 | struct pmu_sleep_notifier awacs_sleep_notifier = { |
264 | awacs_sleep_notify, SLEEP_LEVEL_SOUND, | 264 | awacs_sleep_notify, SLEEP_LEVEL_SOUND, |
265 | }; | 265 | }; |
266 | #endif /* CONFIG_PMAC_PBOOK */ | 266 | #endif /* CONFIG_PM */ |
267 | 267 | ||
268 | /* for (soft) sample rate translations */ | 268 | /* for (soft) sample rate translations */ |
269 | int expand_bal; /* Balance factor for expanding (not volume!) */ | 269 | int expand_bal; /* Balance factor for expanding (not volume!) */ |
@@ -671,15 +671,11 @@ static void PMacIrqCleanup(void) | |||
671 | release_OF_resource(awacs_node, 1); | 671 | release_OF_resource(awacs_node, 1); |
672 | release_OF_resource(awacs_node, 2); | 672 | release_OF_resource(awacs_node, 2); |
673 | 673 | ||
674 | if (awacs_tx_cmd_space) | 674 | kfree(awacs_tx_cmd_space); |
675 | kfree(awacs_tx_cmd_space); | 675 | kfree(awacs_rx_cmd_space); |
676 | if (awacs_rx_cmd_space) | 676 | kfree(beep_dbdma_cmd_space); |
677 | kfree(awacs_rx_cmd_space); | 677 | kfree(beep_buf); |
678 | if (beep_dbdma_cmd_space) | 678 | #ifdef CONFIG_PM |
679 | kfree(beep_dbdma_cmd_space); | ||
680 | if (beep_buf) | ||
681 | kfree(beep_buf); | ||
682 | #ifdef CONFIG_PMAC_PBOOK | ||
683 | pmu_unregister_sleep_notifier(&awacs_sleep_notifier); | 679 | pmu_unregister_sleep_notifier(&awacs_sleep_notifier); |
684 | #endif | 680 | #endif |
685 | } | 681 | } |
@@ -1419,7 +1415,7 @@ load_awacs(void) | |||
1419 | } | 1415 | } |
1420 | } | 1416 | } |
1421 | 1417 | ||
1422 | #ifdef CONFIG_PMAC_PBOOK | 1418 | #ifdef CONFIG_PM |
1423 | /* | 1419 | /* |
1424 | * Save state when going to sleep, restore it afterwards. | 1420 | * Save state when going to sleep, restore it afterwards. |
1425 | */ | 1421 | */ |
@@ -1555,13 +1551,13 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) | |||
1555 | } | 1551 | } |
1556 | return PBOOK_SLEEP_OK; | 1552 | return PBOOK_SLEEP_OK; |
1557 | } | 1553 | } |
1558 | #endif /* CONFIG_PMAC_PBOOK */ | 1554 | #endif /* CONFIG_PM */ |
1559 | 1555 | ||
1560 | 1556 | ||
1561 | /* All the burgundy functions: */ | 1557 | /* All the burgundy functions: */ |
1562 | 1558 | ||
1563 | /* Waits for busy flag to clear */ | 1559 | /* Waits for busy flag to clear */ |
1564 | inline static void | 1560 | static inline void |
1565 | awacs_burgundy_busy_wait(void) | 1561 | awacs_burgundy_busy_wait(void) |
1566 | { | 1562 | { |
1567 | int count = 50; /* > 2 samples at 44k1 */ | 1563 | int count = 50; /* > 2 samples at 44k1 */ |
@@ -1569,7 +1565,7 @@ awacs_burgundy_busy_wait(void) | |||
1569 | udelay(1) ; | 1565 | udelay(1) ; |
1570 | } | 1566 | } |
1571 | 1567 | ||
1572 | inline static void | 1568 | static inline void |
1573 | awacs_burgundy_extend_wait(void) | 1569 | awacs_burgundy_extend_wait(void) |
1574 | { | 1570 | { |
1575 | int count = 50 ; /* > 2 samples at 44k1 */ | 1571 | int count = 50 ; /* > 2 samples at 44k1 */ |
@@ -2301,8 +2297,7 @@ if (count <= 0) | |||
2301 | #endif | 2297 | #endif |
2302 | 2298 | ||
2303 | if ((write_sq.max_count + 1) > number_of_tx_cmd_buffers) { | 2299 | if ((write_sq.max_count + 1) > number_of_tx_cmd_buffers) { |
2304 | if (awacs_tx_cmd_space) | 2300 | kfree(awacs_tx_cmd_space); |
2305 | kfree(awacs_tx_cmd_space); | ||
2306 | number_of_tx_cmd_buffers = 0; | 2301 | number_of_tx_cmd_buffers = 0; |
2307 | 2302 | ||
2308 | /* we need nbufs + 1 (for the loop) and we should request + 1 | 2303 | /* we need nbufs + 1 (for the loop) and we should request + 1 |
@@ -2360,8 +2355,7 @@ if (count <= 0) | |||
2360 | #endif | 2355 | #endif |
2361 | 2356 | ||
2362 | if ((read_sq.max_count+1) > number_of_rx_cmd_buffers ) { | 2357 | if ((read_sq.max_count+1) > number_of_rx_cmd_buffers ) { |
2363 | if (awacs_rx_cmd_space) | 2358 | kfree(awacs_rx_cmd_space); |
2364 | kfree(awacs_rx_cmd_space); | ||
2365 | number_of_rx_cmd_buffers = 0; | 2359 | number_of_rx_cmd_buffers = 0; |
2366 | 2360 | ||
2367 | /* we need nbufs + 1 (for the loop) and we should request + 1 again | 2361 | /* we need nbufs + 1 (for the loop) and we should request + 1 again |
@@ -2805,7 +2799,7 @@ __init setup_beep(void) | |||
2805 | beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); | 2799 | beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); |
2806 | if (beep_buf == NULL) { | 2800 | if (beep_buf == NULL) { |
2807 | printk(KERN_ERR "dmasound_pmac: no memory for beep buffer\n"); | 2801 | printk(KERN_ERR "dmasound_pmac: no memory for beep buffer\n"); |
2808 | if( beep_dbdma_cmd_space ) kfree(beep_dbdma_cmd_space) ; | 2802 | kfree(beep_dbdma_cmd_space) ; |
2809 | return -ENOMEM ; | 2803 | return -ENOMEM ; |
2810 | } | 2804 | } |
2811 | return 0 ; | 2805 | return 0 ; |
@@ -3059,9 +3053,9 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev); | |||
3059 | if ((res=setup_beep())) | 3053 | if ((res=setup_beep())) |
3060 | return res ; | 3054 | return res ; |
3061 | 3055 | ||
3062 | #ifdef CONFIG_PMAC_PBOOK | 3056 | #ifdef CONFIG_PM |
3063 | pmu_register_sleep_notifier(&awacs_sleep_notifier); | 3057 | pmu_register_sleep_notifier(&awacs_sleep_notifier); |
3064 | #endif /* CONFIG_PMAC_PBOOK */ | 3058 | #endif /* CONFIG_PM */ |
3065 | 3059 | ||
3066 | /* Powerbooks have odd ways of enabling inputs such as | 3060 | /* Powerbooks have odd ways of enabling inputs such as |
3067 | an expansion-bay CD or sound from an internal modem | 3061 | an expansion-bay CD or sound from an internal modem |
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c index 33dea3d56c1e..b40b5f97aace 100644 --- a/sound/oss/emu10k1/midi.c +++ b/sound/oss/emu10k1/midi.c | |||
@@ -523,10 +523,8 @@ void emu10k1_seq_midi_close(int dev) | |||
523 | card = midi_devs[dev]->devc; | 523 | card = midi_devs[dev]->devc; |
524 | emu10k1_mpuout_close(card); | 524 | emu10k1_mpuout_close(card); |
525 | 525 | ||
526 | if (card->seq_mididev) { | 526 | kfree(card->seq_mididev); |
527 | kfree(card->seq_mididev); | 527 | card->seq_mididev = NULL; |
528 | card->seq_mididev = NULL; | ||
529 | } | ||
530 | } | 528 | } |
531 | 529 | ||
532 | int emu10k1_seq_midi_out(int dev, unsigned char midi_byte) | 530 | int emu10k1_seq_midi_out(int dev, unsigned char midi_byte) |
diff --git a/sound/oss/emu10k1/passthrough.c b/sound/oss/emu10k1/passthrough.c index 4094be55f3be..4e3baca7d41f 100644 --- a/sound/oss/emu10k1/passthrough.c +++ b/sound/oss/emu10k1/passthrough.c | |||
@@ -213,8 +213,7 @@ void emu10k1_pt_stop(struct emu10k1_card *card) | |||
213 | sblive_writeptr(card, SPCS0 + i, 0, pt->old_spcs[i]); | 213 | sblive_writeptr(card, SPCS0 + i, 0, pt->old_spcs[i]); |
214 | } | 214 | } |
215 | pt->state = PT_STATE_INACTIVE; | 215 | pt->state = PT_STATE_INACTIVE; |
216 | if(pt->buf) | 216 | kfree(pt->buf); |
217 | kfree(pt->buf); | ||
218 | } | 217 | } |
219 | } | 218 | } |
220 | 219 | ||
diff --git a/sound/oss/es1370.c b/sound/oss/es1370.c index 056091cff266..8538085086e7 100644 --- a/sound/oss/es1370.c +++ b/sound/oss/es1370.c | |||
@@ -156,11 +156,16 @@ | |||
156 | #include <linux/spinlock.h> | 156 | #include <linux/spinlock.h> |
157 | #include <linux/gameport.h> | 157 | #include <linux/gameport.h> |
158 | #include <linux/wait.h> | 158 | #include <linux/wait.h> |
159 | #include <linux/dma-mapping.h> | ||
159 | 160 | ||
160 | #include <asm/io.h> | 161 | #include <asm/io.h> |
161 | #include <asm/page.h> | 162 | #include <asm/page.h> |
162 | #include <asm/uaccess.h> | 163 | #include <asm/uaccess.h> |
163 | 164 | ||
165 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
166 | #define SUPPORT_JOYSTICK | ||
167 | #endif | ||
168 | |||
164 | /* --------------------------------------------------------------------- */ | 169 | /* --------------------------------------------------------------------- */ |
165 | 170 | ||
166 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS | 171 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS |
@@ -384,7 +389,10 @@ struct es1370_state { | |||
384 | unsigned char obuf[MIDIOUTBUF]; | 389 | unsigned char obuf[MIDIOUTBUF]; |
385 | } midi; | 390 | } midi; |
386 | 391 | ||
392 | #ifdef SUPPORT_JOYSTICK | ||
387 | struct gameport *gameport; | 393 | struct gameport *gameport; |
394 | #endif | ||
395 | |||
388 | struct semaphore sem; | 396 | struct semaphore sem; |
389 | }; | 397 | }; |
390 | 398 | ||
@@ -2553,10 +2561,55 @@ static struct initvol { | |||
2553 | { SOUND_MIXER_WRITE_OGAIN, 0x4040 } | 2561 | { SOUND_MIXER_WRITE_OGAIN, 0x4040 } |
2554 | }; | 2562 | }; |
2555 | 2563 | ||
2564 | #ifdef SUPPORT_JOYSTICK | ||
2565 | |||
2566 | static int __devinit es1370_register_gameport(struct es1370_state *s) | ||
2567 | { | ||
2568 | struct gameport *gp; | ||
2569 | |||
2570 | if (!request_region(0x200, JOY_EXTENT, "es1370")) { | ||
2571 | printk(KERN_ERR "es1370: joystick io port 0x200 in use\n"); | ||
2572 | return -EBUSY; | ||
2573 | } | ||
2574 | |||
2575 | s->gameport = gp = gameport_allocate_port(); | ||
2576 | if (!gp) { | ||
2577 | printk(KERN_ERR "es1370: can not allocate memory for gameport\n"); | ||
2578 | release_region(0x200, JOY_EXTENT); | ||
2579 | return -ENOMEM; | ||
2580 | } | ||
2581 | |||
2582 | gameport_set_name(gp, "ESS1370"); | ||
2583 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); | ||
2584 | gp->dev.parent = &s->dev->dev; | ||
2585 | gp->io = 0x200; | ||
2586 | |||
2587 | s->ctrl |= CTRL_JYSTK_EN; | ||
2588 | outl(s->ctrl, s->io + ES1370_REG_CONTROL); | ||
2589 | |||
2590 | gameport_register_port(gp); | ||
2591 | |||
2592 | return 0; | ||
2593 | } | ||
2594 | |||
2595 | static inline void es1370_unregister_gameport(struct es1370_state *s) | ||
2596 | { | ||
2597 | if (s->gameport) { | ||
2598 | int gpio = s->gameport->io; | ||
2599 | gameport_unregister_port(s->gameport); | ||
2600 | release_region(gpio, JOY_EXTENT); | ||
2601 | |||
2602 | } | ||
2603 | } | ||
2604 | |||
2605 | #else | ||
2606 | static inline int es1370_register_gameport(struct es1370_state *s) { return -ENOSYS; } | ||
2607 | static inline void es1370_unregister_gameport(struct es1370_state *s) { } | ||
2608 | #endif /* SUPPORT_JOYSTICK */ | ||
2609 | |||
2556 | static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2610 | static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
2557 | { | 2611 | { |
2558 | struct es1370_state *s; | 2612 | struct es1370_state *s; |
2559 | struct gameport *gp = NULL; | ||
2560 | mm_segment_t fs; | 2613 | mm_segment_t fs; |
2561 | int i, val, ret; | 2614 | int i, val, ret; |
2562 | 2615 | ||
@@ -2569,7 +2622,7 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2569 | return -ENODEV; | 2622 | return -ENODEV; |
2570 | if (pcidev->irq == 0) | 2623 | if (pcidev->irq == 0) |
2571 | return -ENODEV; | 2624 | return -ENODEV; |
2572 | i = pci_set_dma_mask(pcidev, 0xffffffff); | 2625 | i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); |
2573 | if (i) { | 2626 | if (i) { |
2574 | printk(KERN_WARNING "es1370: architecture does not support 32bit PCI busmaster DMA\n"); | 2627 | printk(KERN_WARNING "es1370: architecture does not support 32bit PCI busmaster DMA\n"); |
2575 | return i; | 2628 | return i; |
@@ -2605,28 +2658,14 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2605 | /* note: setting CTRL_SERR_DIS is reported to break | 2658 | /* note: setting CTRL_SERR_DIS is reported to break |
2606 | * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */ | 2659 | * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */ |
2607 | s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL); | 2660 | s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL); |
2608 | if (!request_region(0x200, JOY_EXTENT, "es1370")) { | ||
2609 | printk(KERN_ERR "es1370: joystick io port 0x200 in use\n"); | ||
2610 | } else if (!(s->gameport = gp = gameport_allocate_port())) { | ||
2611 | printk(KERN_ERR "es1370: can not allocate memory for gameport\n"); | ||
2612 | release_region(0x200, JOY_EXTENT); | ||
2613 | } else { | ||
2614 | gameport_set_name(gp, "ESS1370"); | ||
2615 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); | ||
2616 | gp->dev.parent = &s->dev->dev; | ||
2617 | gp->io = 0x200; | ||
2618 | s->ctrl |= CTRL_JYSTK_EN; | ||
2619 | } | ||
2620 | if (lineout[devindex]) | 2661 | if (lineout[devindex]) |
2621 | s->ctrl |= CTRL_XCTL0; | 2662 | s->ctrl |= CTRL_XCTL0; |
2622 | if (micbias[devindex]) | 2663 | if (micbias[devindex]) |
2623 | s->ctrl |= CTRL_XCTL1; | 2664 | s->ctrl |= CTRL_XCTL1; |
2624 | s->sctrl = 0; | 2665 | s->sctrl = 0; |
2625 | printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n" | 2666 | printk(KERN_INFO "es1370: adapter at io %#lx irq %u, line %s, mic impedance %s\n", |
2626 | KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n", | 2667 | s->io, s->irq, (s->ctrl & CTRL_XCTL0) ? "out" : "in", |
2627 | s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off", | 2668 | (s->ctrl & CTRL_XCTL1) ? "1" : "0"); |
2628 | (s->ctrl & CTRL_XCTL0) ? "out" : "in", | ||
2629 | (s->ctrl & CTRL_XCTL1) ? "1" : "0"); | ||
2630 | /* register devices */ | 2669 | /* register devices */ |
2631 | if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) { | 2670 | if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) { |
2632 | ret = s->dev_audio; | 2671 | ret = s->dev_audio; |
@@ -2672,9 +2711,7 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2672 | } | 2711 | } |
2673 | set_fs(fs); | 2712 | set_fs(fs); |
2674 | 2713 | ||
2675 | /* register gameport */ | 2714 | es1370_register_gameport(s); |
2676 | if (gp) | ||
2677 | gameport_register_port(gp); | ||
2678 | 2715 | ||
2679 | /* store it in the driver field */ | 2716 | /* store it in the driver field */ |
2680 | pci_set_drvdata(pcidev, s); | 2717 | pci_set_drvdata(pcidev, s); |
@@ -2696,10 +2733,6 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2696 | err_dev1: | 2733 | err_dev1: |
2697 | printk(KERN_ERR "es1370: cannot register misc device\n"); | 2734 | printk(KERN_ERR "es1370: cannot register misc device\n"); |
2698 | free_irq(s->irq, s); | 2735 | free_irq(s->irq, s); |
2699 | if (s->gameport) { | ||
2700 | release_region(s->gameport->io, JOY_EXTENT); | ||
2701 | gameport_free_port(s->gameport); | ||
2702 | } | ||
2703 | err_irq: | 2736 | err_irq: |
2704 | release_region(s->io, ES1370_EXTENT); | 2737 | release_region(s->io, ES1370_EXTENT); |
2705 | err_region: | 2738 | err_region: |
@@ -2718,11 +2751,7 @@ static void __devexit es1370_remove(struct pci_dev *dev) | |||
2718 | outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */ | 2751 | outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */ |
2719 | synchronize_irq(s->irq); | 2752 | synchronize_irq(s->irq); |
2720 | free_irq(s->irq, s); | 2753 | free_irq(s->irq, s); |
2721 | if (s->gameport) { | 2754 | es1370_unregister_gameport(s); |
2722 | int gpio = s->gameport->io; | ||
2723 | gameport_unregister_port(s->gameport); | ||
2724 | release_region(gpio, JOY_EXTENT); | ||
2725 | } | ||
2726 | release_region(s->io, ES1370_EXTENT); | 2755 | release_region(s->io, ES1370_EXTENT); |
2727 | unregister_sound_dsp(s->dev_audio); | 2756 | unregister_sound_dsp(s->dev_audio); |
2728 | unregister_sound_mixer(s->dev_mixer); | 2757 | unregister_sound_mixer(s->dev_mixer); |
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c index a50fddaeea21..12a56d5ab498 100644 --- a/sound/oss/es1371.c +++ b/sound/oss/es1371.c | |||
@@ -128,11 +128,16 @@ | |||
128 | #include <linux/ac97_codec.h> | 128 | #include <linux/ac97_codec.h> |
129 | #include <linux/gameport.h> | 129 | #include <linux/gameport.h> |
130 | #include <linux/wait.h> | 130 | #include <linux/wait.h> |
131 | #include <linux/dma-mapping.h> | ||
131 | 132 | ||
132 | #include <asm/io.h> | 133 | #include <asm/io.h> |
133 | #include <asm/page.h> | 134 | #include <asm/page.h> |
134 | #include <asm/uaccess.h> | 135 | #include <asm/uaccess.h> |
135 | 136 | ||
137 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
138 | #define SUPPORT_JOYSTICK | ||
139 | #endif | ||
140 | |||
136 | /* --------------------------------------------------------------------- */ | 141 | /* --------------------------------------------------------------------- */ |
137 | 142 | ||
138 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS | 143 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS |
@@ -453,7 +458,10 @@ struct es1371_state { | |||
453 | unsigned char obuf[MIDIOUTBUF]; | 458 | unsigned char obuf[MIDIOUTBUF]; |
454 | } midi; | 459 | } midi; |
455 | 460 | ||
461 | #ifdef SUPPORT_JOYSTICK | ||
456 | struct gameport *gameport; | 462 | struct gameport *gameport; |
463 | #endif | ||
464 | |||
457 | struct semaphore sem; | 465 | struct semaphore sem; |
458 | }; | 466 | }; |
459 | 467 | ||
@@ -2786,12 +2794,63 @@ static struct | |||
2786 | { PCI_ANY_ID, PCI_ANY_ID } | 2794 | { PCI_ANY_ID, PCI_ANY_ID } |
2787 | }; | 2795 | }; |
2788 | 2796 | ||
2797 | #ifdef SUPPORT_JOYSTICK | ||
2798 | |||
2799 | static int __devinit es1371_register_gameport(struct es1371_state *s) | ||
2800 | { | ||
2801 | struct gameport *gp; | ||
2802 | int gpio; | ||
2803 | |||
2804 | for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08) | ||
2805 | if (request_region(gpio, JOY_EXTENT, "es1371")) | ||
2806 | break; | ||
2807 | |||
2808 | if (gpio < 0x200) { | ||
2809 | printk(KERN_ERR PFX "no free joystick address found\n"); | ||
2810 | return -EBUSY; | ||
2811 | } | ||
2812 | |||
2813 | s->gameport = gp = gameport_allocate_port(); | ||
2814 | if (!gp) { | ||
2815 | printk(KERN_ERR PFX "can not allocate memory for gameport\n"); | ||
2816 | release_region(gpio, JOY_EXTENT); | ||
2817 | return -ENOMEM; | ||
2818 | } | ||
2819 | |||
2820 | gameport_set_name(gp, "ESS1371 Gameport"); | ||
2821 | gameport_set_phys(gp, "isa%04x/gameport0", gpio); | ||
2822 | gp->dev.parent = &s->dev->dev; | ||
2823 | gp->io = gpio; | ||
2824 | |||
2825 | s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT); | ||
2826 | outl(s->ctrl, s->io + ES1371_REG_CONTROL); | ||
2827 | |||
2828 | gameport_register_port(gp); | ||
2829 | |||
2830 | return 0; | ||
2831 | } | ||
2832 | |||
2833 | static inline void es1371_unregister_gameport(struct es1371_state *s) | ||
2834 | { | ||
2835 | if (s->gameport) { | ||
2836 | int gpio = s->gameport->io; | ||
2837 | gameport_unregister_port(s->gameport); | ||
2838 | release_region(gpio, JOY_EXTENT); | ||
2839 | |||
2840 | } | ||
2841 | } | ||
2842 | |||
2843 | #else | ||
2844 | static inline int es1371_register_gameport(struct es1371_state *s) { return -ENOSYS; } | ||
2845 | static inline void es1371_unregister_gameport(struct es1371_state *s) { } | ||
2846 | #endif /* SUPPORT_JOYSTICK */ | ||
2847 | |||
2848 | |||
2789 | static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2849 | static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
2790 | { | 2850 | { |
2791 | struct es1371_state *s; | 2851 | struct es1371_state *s; |
2792 | struct gameport *gp; | ||
2793 | mm_segment_t fs; | 2852 | mm_segment_t fs; |
2794 | int i, gpio, val, res = -1; | 2853 | int i, val, res = -1; |
2795 | int idx; | 2854 | int idx; |
2796 | unsigned long tmo; | 2855 | unsigned long tmo; |
2797 | signed long tmo2; | 2856 | signed long tmo2; |
@@ -2804,7 +2863,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2804 | return -ENODEV; | 2863 | return -ENODEV; |
2805 | if (pcidev->irq == 0) | 2864 | if (pcidev->irq == 0) |
2806 | return -ENODEV; | 2865 | return -ENODEV; |
2807 | i = pci_set_dma_mask(pcidev, 0xffffffff); | 2866 | i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); |
2808 | if (i) { | 2867 | if (i) { |
2809 | printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n"); | 2868 | printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n"); |
2810 | return i; | 2869 | return i; |
@@ -2882,23 +2941,6 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2882 | } | 2941 | } |
2883 | } | 2942 | } |
2884 | 2943 | ||
2885 | for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08) | ||
2886 | if (request_region(gpio, JOY_EXTENT, "es1371")) | ||
2887 | break; | ||
2888 | |||
2889 | if (gpio < 0x200) { | ||
2890 | printk(KERN_ERR PFX "no free joystick address found\n"); | ||
2891 | } else if (!(s->gameport = gp = gameport_allocate_port())) { | ||
2892 | printk(KERN_ERR PFX "can not allocate memory for gameport\n"); | ||
2893 | release_region(gpio, JOY_EXTENT); | ||
2894 | } else { | ||
2895 | gameport_set_name(gp, "ESS1371 Gameport"); | ||
2896 | gameport_set_phys(gp, "isa%04x/gameport0", gpio); | ||
2897 | gp->dev.parent = &s->dev->dev; | ||
2898 | gp->io = gpio; | ||
2899 | s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT); | ||
2900 | } | ||
2901 | |||
2902 | s->sctrl = 0; | 2944 | s->sctrl = 0; |
2903 | cssr = 0; | 2945 | cssr = 0; |
2904 | s->spdif_volume = -1; | 2946 | s->spdif_volume = -1; |
@@ -2968,9 +3010,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2968 | /* turn on S/PDIF output driver if requested */ | 3010 | /* turn on S/PDIF output driver if requested */ |
2969 | outl(cssr, s->io+ES1371_REG_STATUS); | 3011 | outl(cssr, s->io+ES1371_REG_STATUS); |
2970 | 3012 | ||
2971 | /* register gameport */ | 3013 | es1371_register_gameport(s); |
2972 | if (s->gameport) | ||
2973 | gameport_register_port(s->gameport); | ||
2974 | 3014 | ||
2975 | /* store it in the driver field */ | 3015 | /* store it in the driver field */ |
2976 | pci_set_drvdata(pcidev, s); | 3016 | pci_set_drvdata(pcidev, s); |
@@ -2979,13 +3019,9 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic | |||
2979 | /* increment devindex */ | 3019 | /* increment devindex */ |
2980 | if (devindex < NR_DEVICE-1) | 3020 | if (devindex < NR_DEVICE-1) |
2981 | devindex++; | 3021 | devindex++; |
2982 | return 0; | 3022 | return 0; |
2983 | 3023 | ||
2984 | err_gp: | 3024 | err_gp: |
2985 | if (s->gameport) { | ||
2986 | release_region(s->gameport->io, JOY_EXTENT); | ||
2987 | gameport_free_port(s->gameport); | ||
2988 | } | ||
2989 | #ifdef ES1371_DEBUG | 3025 | #ifdef ES1371_DEBUG |
2990 | if (s->ps) | 3026 | if (s->ps) |
2991 | remove_proc_entry("es1371", NULL); | 3027 | remove_proc_entry("es1371", NULL); |
@@ -3024,11 +3060,7 @@ static void __devexit es1371_remove(struct pci_dev *dev) | |||
3024 | outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */ | 3060 | outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */ |
3025 | synchronize_irq(s->irq); | 3061 | synchronize_irq(s->irq); |
3026 | free_irq(s->irq, s); | 3062 | free_irq(s->irq, s); |
3027 | if (s->gameport) { | 3063 | es1371_unregister_gameport(s); |
3028 | int gpio = s->gameport->io; | ||
3029 | gameport_unregister_port(s->gameport); | ||
3030 | release_region(gpio, JOY_EXTENT); | ||
3031 | } | ||
3032 | release_region(s->io, ES1371_EXTENT); | 3064 | release_region(s->io, ES1371_EXTENT); |
3033 | unregister_sound_dsp(s->dev_audio); | 3065 | unregister_sound_dsp(s->dev_audio); |
3034 | unregister_sound_mixer(s->codec->dev_mixer); | 3066 | unregister_sound_mixer(s->codec->dev_mixer); |
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c index 6b3b9a99579d..a4ecab2f0522 100644 --- a/sound/oss/esssolo1.c +++ b/sound/oss/esssolo1.c | |||
@@ -104,6 +104,7 @@ | |||
104 | #include <linux/smp_lock.h> | 104 | #include <linux/smp_lock.h> |
105 | #include <linux/gameport.h> | 105 | #include <linux/gameport.h> |
106 | #include <linux/wait.h> | 106 | #include <linux/wait.h> |
107 | #include <linux/dma-mapping.h> | ||
107 | 108 | ||
108 | #include <asm/io.h> | 109 | #include <asm/io.h> |
109 | #include <asm/page.h> | 110 | #include <asm/page.h> |
@@ -149,6 +150,10 @@ | |||
149 | 150 | ||
150 | #define FMODE_DMFM 0x10 | 151 | #define FMODE_DMFM 0x10 |
151 | 152 | ||
153 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
154 | #define SUPPORT_JOYSTICK 1 | ||
155 | #endif | ||
156 | |||
152 | static struct pci_driver solo1_driver; | 157 | static struct pci_driver solo1_driver; |
153 | 158 | ||
154 | /* --------------------------------------------------------------------- */ | 159 | /* --------------------------------------------------------------------- */ |
@@ -226,7 +231,9 @@ struct solo1_state { | |||
226 | unsigned char obuf[MIDIOUTBUF]; | 231 | unsigned char obuf[MIDIOUTBUF]; |
227 | } midi; | 232 | } midi; |
228 | 233 | ||
234 | #if SUPPORT_JOYSTICK | ||
229 | struct gameport *gameport; | 235 | struct gameport *gameport; |
236 | #endif | ||
230 | }; | 237 | }; |
231 | 238 | ||
232 | /* --------------------------------------------------------------------- */ | 239 | /* --------------------------------------------------------------------- */ |
@@ -2280,6 +2287,7 @@ solo1_resume(struct pci_dev *pci_dev) { | |||
2280 | return 0; | 2287 | return 0; |
2281 | } | 2288 | } |
2282 | 2289 | ||
2290 | #ifdef SUPPORT_JOYSTICK | ||
2283 | static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) | 2291 | static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) |
2284 | { | 2292 | { |
2285 | struct gameport *gp; | 2293 | struct gameport *gp; |
@@ -2306,6 +2314,19 @@ static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) | |||
2306 | return 0; | 2314 | return 0; |
2307 | } | 2315 | } |
2308 | 2316 | ||
2317 | static inline void solo1_unregister_gameport(struct solo1_state *s) | ||
2318 | { | ||
2319 | if (s->gameport) { | ||
2320 | int gpio = s->gameport->io; | ||
2321 | gameport_unregister_port(s->gameport); | ||
2322 | release_region(gpio, GAMEPORT_EXTENT); | ||
2323 | } | ||
2324 | } | ||
2325 | #else | ||
2326 | static inline int solo1_register_gameport(struct solo1_state *s, int io_port) { return -ENOSYS; } | ||
2327 | static inline void solo1_unregister_gameport(struct solo1_state *s) { } | ||
2328 | #endif /* SUPPORT_JOYSTICK */ | ||
2329 | |||
2309 | static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2330 | static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
2310 | { | 2331 | { |
2311 | struct solo1_state *s; | 2332 | struct solo1_state *s; |
@@ -2326,7 +2347,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device | |||
2326 | * to 24 bits first, then 32 bits (playback only) if that fails. | 2347 | * to 24 bits first, then 32 bits (playback only) if that fails. |
2327 | */ | 2348 | */ |
2328 | if (pci_set_dma_mask(pcidev, 0x00ffffff) && | 2349 | if (pci_set_dma_mask(pcidev, 0x00ffffff) && |
2329 | pci_set_dma_mask(pcidev, 0xffffffff)) { | 2350 | pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) { |
2330 | printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n"); | 2351 | printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n"); |
2331 | return -ENODEV; | 2352 | return -ENODEV; |
2332 | } | 2353 | } |
@@ -2437,11 +2458,7 @@ static void __devexit solo1_remove(struct pci_dev *dev) | |||
2437 | synchronize_irq(s->irq); | 2458 | synchronize_irq(s->irq); |
2438 | pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */ | 2459 | pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */ |
2439 | free_irq(s->irq, s); | 2460 | free_irq(s->irq, s); |
2440 | if (s->gameport) { | 2461 | solo1_unregister_gameport(s); |
2441 | int gpio = s->gameport->io; | ||
2442 | gameport_unregister_port(s->gameport); | ||
2443 | release_region(gpio, GAMEPORT_EXTENT); | ||
2444 | } | ||
2445 | release_region(s->iobase, IOBASE_EXTENT); | 2462 | release_region(s->iobase, IOBASE_EXTENT); |
2446 | release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT); | 2463 | release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT); |
2447 | release_region(s->ddmabase, DDMABASE_EXTENT); | 2464 | release_region(s->ddmabase, DDMABASE_EXTENT); |
diff --git a/sound/oss/mad16.c b/sound/oss/mad16.c index a7067f169919..aa3c50db66c4 100644 --- a/sound/oss/mad16.c +++ b/sound/oss/mad16.c | |||
@@ -50,9 +50,12 @@ | |||
50 | #include "sb.h" | 50 | #include "sb.h" |
51 | #include "mpu401.h" | 51 | #include "mpu401.h" |
52 | 52 | ||
53 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
54 | #define SUPPORT_JOYSTICK 1 | ||
55 | #endif | ||
56 | |||
53 | static int mad16_conf; | 57 | static int mad16_conf; |
54 | static int mad16_cdsel; | 58 | static int mad16_cdsel; |
55 | static struct gameport *gameport; | ||
56 | static DEFINE_SPINLOCK(lock); | 59 | static DEFINE_SPINLOCK(lock); |
57 | 60 | ||
58 | #define C928 1 | 61 | #define C928 1 |
@@ -902,6 +905,10 @@ static int __initdata irq_map[16] = | |||
902 | -1, -1, -1, -1 | 905 | -1, -1, -1, -1 |
903 | }; | 906 | }; |
904 | 907 | ||
908 | #ifdef SUPPORT_JOYSTICK | ||
909 | |||
910 | static struct gameport *gameport; | ||
911 | |||
905 | static int __devinit mad16_register_gameport(int io_port) | 912 | static int __devinit mad16_register_gameport(int io_port) |
906 | { | 913 | { |
907 | if (!request_region(io_port, 1, "mad16 gameport")) { | 914 | if (!request_region(io_port, 1, "mad16 gameport")) { |
@@ -925,6 +932,20 @@ static int __devinit mad16_register_gameport(int io_port) | |||
925 | return 0; | 932 | return 0; |
926 | } | 933 | } |
927 | 934 | ||
935 | static inline void mad16_unregister_gameport(void) | ||
936 | { | ||
937 | if (gameport) { | ||
938 | /* the gameport was initialized so we must free it up */ | ||
939 | gameport_unregister_port(gameport); | ||
940 | gameport = NULL; | ||
941 | release_region(0x201, 1); | ||
942 | } | ||
943 | } | ||
944 | #else | ||
945 | static inline int mad16_register_gameport(int io_port) { return -ENOSYS; } | ||
946 | static inline void mad16_unregister_gameport(void) { } | ||
947 | #endif | ||
948 | |||
928 | static int __devinit init_mad16(void) | 949 | static int __devinit init_mad16(void) |
929 | { | 950 | { |
930 | int dmatype = 0; | 951 | int dmatype = 0; |
@@ -1060,12 +1081,7 @@ static void __exit cleanup_mad16(void) | |||
1060 | { | 1081 | { |
1061 | if (found_mpu) | 1082 | if (found_mpu) |
1062 | unload_mad16_mpu(&cfg_mpu); | 1083 | unload_mad16_mpu(&cfg_mpu); |
1063 | if (gameport) { | 1084 | mad16_unregister_gameport(); |
1064 | /* the gameport was initialized so we must free it up */ | ||
1065 | gameport_unregister_port(gameport); | ||
1066 | gameport = NULL; | ||
1067 | release_region(0x201, 1); | ||
1068 | } | ||
1069 | unload_mad16(&cfg); | 1085 | unload_mad16(&cfg); |
1070 | release_region(MC0_PORT, 12); | 1086 | release_region(MC0_PORT, 12); |
1071 | } | 1087 | } |
diff --git a/sound/oss/maestro.c b/sound/oss/maestro.c index 52d2db4bc312..3dce504e6d6d 100644 --- a/sound/oss/maestro.c +++ b/sound/oss/maestro.c | |||
@@ -2356,7 +2356,7 @@ ess_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | |||
2356 | } | 2356 | } |
2357 | 2357 | ||
2358 | rec_return_free: | 2358 | rec_return_free: |
2359 | if(combbuf) kfree(combbuf); | 2359 | kfree(combbuf); |
2360 | return ret; | 2360 | return ret; |
2361 | } | 2361 | } |
2362 | 2362 | ||
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c index b66f53fa8db0..0aac54c68f01 100644 --- a/sound/oss/mpu401.c +++ b/sound/oss/mpu401.c | |||
@@ -1240,8 +1240,7 @@ void unload_mpu401(struct address_info *hw_config) | |||
1240 | p=mpu401_synth_operations[n]; | 1240 | p=mpu401_synth_operations[n]; |
1241 | sound_unload_mididev(n); | 1241 | sound_unload_mididev(n); |
1242 | sound_unload_timerdev(hw_config->slots[2]); | 1242 | sound_unload_timerdev(hw_config->slots[2]); |
1243 | if(p) | 1243 | kfree(p); |
1244 | kfree(p); | ||
1245 | } | 1244 | } |
1246 | } | 1245 | } |
1247 | 1246 | ||
diff --git a/sound/oss/nm256.h b/sound/oss/nm256.h index eae7d99d6826..21e07b5081f2 100644 --- a/sound/oss/nm256.h +++ b/sound/oss/nm256.h | |||
@@ -128,9 +128,6 @@ struct nm256_info | |||
128 | struct nm256_info *next_card; | 128 | struct nm256_info *next_card; |
129 | }; | 129 | }; |
130 | 130 | ||
131 | /* Debug flag--bigger numbers mean more output. */ | ||
132 | extern int nm256_debug; | ||
133 | |||
134 | /* The BIOS signature. */ | 131 | /* The BIOS signature. */ |
135 | #define NM_SIGNATURE 0x4e4d0000 | 132 | #define NM_SIGNATURE 0x4e4d0000 |
136 | /* Signature mask. */ | 133 | /* Signature mask. */ |
@@ -284,7 +281,7 @@ nm256_readBuffer8 (struct nm256_info *card, u8 *dst, int port, int offset, | |||
284 | } | 281 | } |
285 | 282 | ||
286 | /* Returns a non-zero value if we should use the coefficient cache. */ | 283 | /* Returns a non-zero value if we should use the coefficient cache. */ |
287 | extern int nm256_cachedCoefficients (struct nm256_info *card); | 284 | static int nm256_cachedCoefficients (struct nm256_info *card); |
288 | 285 | ||
289 | #endif | 286 | #endif |
290 | 287 | ||
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c index f9166e135192..66970062eb36 100644 --- a/sound/oss/nm256_audio.c +++ b/sound/oss/nm256_audio.c | |||
@@ -28,12 +28,13 @@ | |||
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
30 | #include "sound_config.h" | 30 | #include "sound_config.h" |
31 | #include "nm256.h" | ||
32 | #include "nm256_coeff.h" | ||
33 | 31 | ||
34 | int nm256_debug; | 32 | static int nm256_debug; |
35 | static int force_load; | 33 | static int force_load; |
36 | 34 | ||
35 | #include "nm256.h" | ||
36 | #include "nm256_coeff.h" | ||
37 | |||
37 | /* | 38 | /* |
38 | * The size of the playback reserve. When the playback buffer has less | 39 | * The size of the playback reserve. When the playback buffer has less |
39 | * than NM256_PLAY_WMARK_SIZE bytes to output, we request a new | 40 | * than NM256_PLAY_WMARK_SIZE bytes to output, we request a new |
@@ -138,7 +139,7 @@ static int usecache; | |||
138 | static int buffertop; | 139 | static int buffertop; |
139 | 140 | ||
140 | /* Check to see if we're using the bank of cached coefficients. */ | 141 | /* Check to see if we're using the bank of cached coefficients. */ |
141 | int | 142 | static int |
142 | nm256_cachedCoefficients (struct nm256_info *card) | 143 | nm256_cachedCoefficients (struct nm256_info *card) |
143 | { | 144 | { |
144 | return usecache; | 145 | return usecache; |
diff --git a/sound/oss/nm256_coeff.h b/sound/oss/nm256_coeff.h index 0ceecc20077b..6fc07f3cb33b 100644 --- a/sound/oss/nm256_coeff.h +++ b/sound/oss/nm256_coeff.h | |||
@@ -4650,7 +4650,7 @@ nm256_loadAllCoefficients (struct nm256_info *card) | |||
4650 | card->coeffsCurrent = 1; | 4650 | card->coeffsCurrent = 1; |
4651 | } | 4651 | } |
4652 | 4652 | ||
4653 | void | 4653 | static void |
4654 | nm256_loadCoefficient (struct nm256_info *card, int which, int number) | 4654 | nm256_loadCoefficient (struct nm256_info *card, int which, int number) |
4655 | { | 4655 | { |
4656 | static u16 addrs[3] = { 0x1c, 0x21c, 0x408 }; | 4656 | static u16 addrs[3] = { 0x1c, 0x21c, 0x408 }; |
diff --git a/sound/oss/pss.c b/sound/oss/pss.c index 3ed38765dcc4..a617ccb40e00 100644 --- a/sound/oss/pss.c +++ b/sound/oss/pss.c | |||
@@ -714,7 +714,7 @@ static int __init attach_pss(struct address_info *hw_config) | |||
714 | 714 | ||
715 | disable_all_emulations(); | 715 | disable_all_emulations(); |
716 | 716 | ||
717 | #if YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES | 717 | #ifdef YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES |
718 | if (sound_alloc_dma(hw_config->dma, "PSS")) | 718 | if (sound_alloc_dma(hw_config->dma, "PSS")) |
719 | { | 719 | { |
720 | printk("pss.c: Can't allocate DMA channel.\n"); | 720 | printk("pss.c: Can't allocate DMA channel.\n"); |
diff --git a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c index 76774bbc1436..7609c68a89f4 100644 --- a/sound/oss/rme96xx.c +++ b/sound/oss/rme96xx.c | |||
@@ -807,7 +807,7 @@ static void* busmaster_malloc(int size) { | |||
807 | struct page* page, *last_page; | 807 | struct page* page, *last_page; |
808 | 808 | ||
809 | page = virt_to_page(buf); | 809 | page = virt_to_page(buf); |
810 | last_page = virt_to_page(buf + (1 << pg)); | 810 | last_page = page + (1 << pg); |
811 | DBG(printk("setting reserved bit\n")); | 811 | DBG(printk("setting reserved bit\n")); |
812 | while (page < last_page) { | 812 | while (page < last_page) { |
813 | SetPageReserved(page); | 813 | SetPageReserved(page); |
@@ -1750,9 +1750,7 @@ static unsigned int rme96xx_poll(struct file *file, struct poll_table_struct *wa | |||
1750 | 1750 | ||
1751 | 1751 | ||
1752 | static struct file_operations rme96xx_audio_fops = { | 1752 | static struct file_operations rme96xx_audio_fops = { |
1753 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) | ||
1754 | .owner = THIS_MODULE, | 1753 | .owner = THIS_MODULE, |
1755 | #endif | ||
1756 | .read = rme96xx_read, | 1754 | .read = rme96xx_read, |
1757 | .write = rme96xx_write, | 1755 | .write = rme96xx_write, |
1758 | .poll = rme96xx_poll, | 1756 | .poll = rme96xx_poll, |
@@ -1852,9 +1850,7 @@ static int rme96xx_mixer_release(struct inode *inode, struct file *file) | |||
1852 | } | 1850 | } |
1853 | 1851 | ||
1854 | static /*const*/ struct file_operations rme96xx_mixer_fops = { | 1852 | static /*const*/ struct file_operations rme96xx_mixer_fops = { |
1855 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) | ||
1856 | .owner = THIS_MODULE, | 1853 | .owner = THIS_MODULE, |
1857 | #endif | ||
1858 | .ioctl = rme96xx_mixer_ioctl, | 1854 | .ioctl = rme96xx_mixer_ioctl, |
1859 | .open = rme96xx_mixer_open, | 1855 | .open = rme96xx_mixer_open, |
1860 | .release = rme96xx_mixer_release, | 1856 | .release = rme96xx_mixer_release, |
diff --git a/sound/oss/sb_common.c b/sound/oss/sb_common.c index ce359e6c933a..5f955e3d2e26 100644 --- a/sound/oss/sb_common.c +++ b/sound/oss/sb_common.c | |||
@@ -915,8 +915,8 @@ void sb_dsp_unload(struct address_info *hw_config, int sbmpu) | |||
915 | } | 915 | } |
916 | else | 916 | else |
917 | release_region(hw_config->io_base, 16); | 917 | release_region(hw_config->io_base, 16); |
918 | if(detected_devc) | 918 | |
919 | kfree(detected_devc); | 919 | kfree(detected_devc); |
920 | } | 920 | } |
921 | 921 | ||
922 | /* | 922 | /* |
diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c index 06047e7979af..17d0e461f8d8 100644 --- a/sound/oss/sonicvibes.c +++ b/sound/oss/sonicvibes.c | |||
@@ -122,6 +122,9 @@ | |||
122 | 122 | ||
123 | #include "dm.h" | 123 | #include "dm.h" |
124 | 124 | ||
125 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
126 | #define SUPPORT_JOYSTICK 1 | ||
127 | #endif | ||
125 | 128 | ||
126 | /* --------------------------------------------------------------------- */ | 129 | /* --------------------------------------------------------------------- */ |
127 | 130 | ||
@@ -365,7 +368,9 @@ struct sv_state { | |||
365 | unsigned char obuf[MIDIOUTBUF]; | 368 | unsigned char obuf[MIDIOUTBUF]; |
366 | } midi; | 369 | } midi; |
367 | 370 | ||
371 | #if SUPPORT_JOYSTICK | ||
368 | struct gameport *gameport; | 372 | struct gameport *gameport; |
373 | #endif | ||
369 | }; | 374 | }; |
370 | 375 | ||
371 | /* --------------------------------------------------------------------- */ | 376 | /* --------------------------------------------------------------------- */ |
@@ -2485,6 +2490,7 @@ static struct initvol { | |||
2485 | #define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ | 2490 | #define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ |
2486 | (pci_resource_flags((dev), (num)) & IORESOURCE_IO)) | 2491 | (pci_resource_flags((dev), (num)) & IORESOURCE_IO)) |
2487 | 2492 | ||
2493 | #ifdef SUPPORT_JOYSTICK | ||
2488 | static int __devinit sv_register_gameport(struct sv_state *s, int io_port) | 2494 | static int __devinit sv_register_gameport(struct sv_state *s, int io_port) |
2489 | { | 2495 | { |
2490 | struct gameport *gp; | 2496 | struct gameport *gp; |
@@ -2511,6 +2517,19 @@ static int __devinit sv_register_gameport(struct sv_state *s, int io_port) | |||
2511 | return 0; | 2517 | return 0; |
2512 | } | 2518 | } |
2513 | 2519 | ||
2520 | static inline void sv_unregister_gameport(struct sv_state *s) | ||
2521 | { | ||
2522 | if (s->gameport) { | ||
2523 | int gpio = s->gameport->io; | ||
2524 | gameport_unregister_port(s->gameport); | ||
2525 | release_region(gpio, SV_EXTENT_GAME); | ||
2526 | } | ||
2527 | } | ||
2528 | #else | ||
2529 | static inline int sv_register_gameport(struct sv_state *s, int io_port) { return -ENOSYS; } | ||
2530 | static inline void sv_unregister_gameport(struct sv_state *s) { } | ||
2531 | #endif /* SUPPORT_JOYSTICK */ | ||
2532 | |||
2514 | static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2533 | static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
2515 | { | 2534 | { |
2516 | static char __devinitdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller"; | 2535 | static char __devinitdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller"; |
@@ -2711,11 +2730,7 @@ static void __devexit sv_remove(struct pci_dev *dev) | |||
2711 | /*outb(0, s->iodmaa + SV_DMA_RESET);*/ | 2730 | /*outb(0, s->iodmaa + SV_DMA_RESET);*/ |
2712 | /*outb(0, s->iodmac + SV_DMA_RESET);*/ | 2731 | /*outb(0, s->iodmac + SV_DMA_RESET);*/ |
2713 | free_irq(s->irq, s); | 2732 | free_irq(s->irq, s); |
2714 | if (s->gameport) { | 2733 | sv_unregister_gameport(s); |
2715 | int gpio = s->gameport->io; | ||
2716 | gameport_unregister_port(s->gameport); | ||
2717 | release_region(gpio, SV_EXTENT_GAME); | ||
2718 | } | ||
2719 | release_region(s->iodmac, SV_EXTENT_DMA); | 2734 | release_region(s->iodmac, SV_EXTENT_DMA); |
2720 | release_region(s->iodmaa, SV_EXTENT_DMA); | 2735 | release_region(s->iodmaa, SV_EXTENT_DMA); |
2721 | release_region(s->ioenh, SV_EXTENT_ENH); | 2736 | release_region(s->ioenh, SV_EXTENT_ENH); |
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index de91c90a0112..a686be936aff 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c | |||
@@ -73,7 +73,7 @@ static char dma_alloc_map[MAX_DMA_CHANNELS]; | |||
73 | 73 | ||
74 | 74 | ||
75 | unsigned long seq_time = 0; /* Time for /dev/sequencer */ | 75 | unsigned long seq_time = 0; /* Time for /dev/sequencer */ |
76 | extern struct class_simple *sound_class; | 76 | extern struct class *sound_class; |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * Table for configurable mixer volume handling | 79 | * Table for configurable mixer volume handling |
@@ -567,9 +567,9 @@ static int __init oss_init(void) | |||
567 | devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor), | 567 | devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor), |
568 | S_IFCHR | dev_list[i].mode, | 568 | S_IFCHR | dev_list[i].mode, |
569 | "sound/%s", dev_list[i].name); | 569 | "sound/%s", dev_list[i].name); |
570 | class_simple_device_add(sound_class, | 570 | class_device_create(sound_class, |
571 | MKDEV(SOUND_MAJOR, dev_list[i].minor), | 571 | MKDEV(SOUND_MAJOR, dev_list[i].minor), |
572 | NULL, "%s", dev_list[i].name); | 572 | NULL, "%s", dev_list[i].name); |
573 | 573 | ||
574 | if (!dev_list[i].num) | 574 | if (!dev_list[i].num) |
575 | continue; | 575 | continue; |
@@ -579,10 +579,9 @@ static int __init oss_init(void) | |||
579 | dev_list[i].minor + (j*0x10)), | 579 | dev_list[i].minor + (j*0x10)), |
580 | S_IFCHR | dev_list[i].mode, | 580 | S_IFCHR | dev_list[i].mode, |
581 | "sound/%s%d", dev_list[i].name, j); | 581 | "sound/%s%d", dev_list[i].name, j); |
582 | class_simple_device_add(sound_class, | 582 | class_device_create(sound_class, |
583 | MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)), | 583 | MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)), |
584 | NULL, | 584 | NULL, "%s%d", dev_list[i].name, j); |
585 | "%s%d", dev_list[i].name, j); | ||
586 | } | 585 | } |
587 | } | 586 | } |
588 | 587 | ||
@@ -598,12 +597,12 @@ static void __exit oss_cleanup(void) | |||
598 | 597 | ||
599 | for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { | 598 | for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { |
600 | devfs_remove("sound/%s", dev_list[i].name); | 599 | devfs_remove("sound/%s", dev_list[i].name); |
601 | class_simple_device_remove(MKDEV(SOUND_MAJOR, dev_list[i].minor)); | 600 | class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor)); |
602 | if (!dev_list[i].num) | 601 | if (!dev_list[i].num) |
603 | continue; | 602 | continue; |
604 | for (j = 1; j < *dev_list[i].num; j++) { | 603 | for (j = 1; j < *dev_list[i].num; j++) { |
605 | devfs_remove("sound/%s%d", dev_list[i].name, j); | 604 | devfs_remove("sound/%s%d", dev_list[i].name, j); |
606 | class_simple_device_remove(MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10))); | 605 | class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10))); |
607 | } | 606 | } |
608 | } | 607 | } |
609 | 608 | ||
diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c index 50ca64629450..9ed5211c3168 100644 --- a/sound/oss/sscape.c +++ b/sound/oss/sscape.c | |||
@@ -991,7 +991,6 @@ static void __init sscape_pnp_init_hw(sscape_info* devc) | |||
991 | unsigned i; | 991 | unsigned i; |
992 | static char code_file_name[23] = "/sndscape/sndscape.cox"; | 992 | static char code_file_name[23] = "/sndscape/sndscape.cox"; |
993 | 993 | ||
994 | int sscape_sb_enable = 0; | ||
995 | int sscape_joystic_enable = 0x7f; | 994 | int sscape_joystic_enable = 0x7f; |
996 | int sscape_mic_enable = 0; | 995 | int sscape_mic_enable = 0; |
997 | int sscape_ext_midi = 0; | 996 | int sscape_ext_midi = 0; |
@@ -1015,14 +1014,9 @@ static void __init sscape_pnp_init_hw(sscape_info* devc) | |||
1015 | sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40); | 1014 | sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40); |
1016 | sscape_write( devc, 3, ( devc -> dma << 4) | 0x80); | 1015 | sscape_write( devc, 3, ( devc -> dma << 4) | 0x80); |
1017 | 1016 | ||
1018 | if ( sscape_sb_enable ) | 1017 | sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq); |
1019 | sscape_write (devc, 4, 0xF0 | (sb_irq << 2) | midi_irq); | ||
1020 | else | ||
1021 | sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq); | ||
1022 | 1018 | ||
1023 | i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0); | 1019 | i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0); |
1024 | if ( sscape_sb_enable ) | ||
1025 | i |= devc->ic_type == IC_ODIE ? 0x05 : 0x07; | ||
1026 | if (sscape_joystic_enable) i |= 8; | 1020 | if (sscape_joystic_enable) i |= 8; |
1027 | 1021 | ||
1028 | sscape_write (devc, 9, i); | 1022 | sscape_write (devc, 9, i); |
diff --git a/sound/oss/trident.c b/sound/oss/trident.c index 47537f0a5b05..5f0ad6bb43b9 100644 --- a/sound/oss/trident.c +++ b/sound/oss/trident.c | |||
@@ -228,6 +228,10 @@ | |||
228 | 228 | ||
229 | #define DRIVER_VERSION "0.14.10j-2.6" | 229 | #define DRIVER_VERSION "0.14.10j-2.6" |
230 | 230 | ||
231 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
232 | #define SUPPORT_JOYSTICK 1 | ||
233 | #endif | ||
234 | |||
231 | /* magic numbers to protect our data structures */ | 235 | /* magic numbers to protect our data structures */ |
232 | #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ | 236 | #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ |
233 | #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ | 237 | #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ |
@@ -4252,24 +4256,25 @@ trident_ac97_init(struct trident_card *card) | |||
4252 | return num_ac97 + 1; | 4256 | return num_ac97 + 1; |
4253 | } | 4257 | } |
4254 | 4258 | ||
4259 | #ifdef SUPPORT_JOYSTICK | ||
4255 | /* Gameport functions for the cards ADC gameport */ | 4260 | /* Gameport functions for the cards ADC gameport */ |
4256 | 4261 | ||
4257 | static unsigned char | 4262 | static unsigned char trident_game_read(struct gameport *gameport) |
4258 | trident_game_read(struct gameport *gameport) | ||
4259 | { | 4263 | { |
4260 | struct trident_card *card = gameport->port_data; | 4264 | struct trident_card *card = gameport->port_data; |
4265 | |||
4261 | return inb(TRID_REG(card, T4D_GAME_LEG)); | 4266 | return inb(TRID_REG(card, T4D_GAME_LEG)); |
4262 | } | 4267 | } |
4263 | 4268 | ||
4264 | static void | 4269 | static void trident_game_trigger(struct gameport *gameport) |
4265 | trident_game_trigger(struct gameport *gameport) | ||
4266 | { | 4270 | { |
4267 | struct trident_card *card = gameport->port_data; | 4271 | struct trident_card *card = gameport->port_data; |
4272 | |||
4268 | outb(0xff, TRID_REG(card, T4D_GAME_LEG)); | 4273 | outb(0xff, TRID_REG(card, T4D_GAME_LEG)); |
4269 | } | 4274 | } |
4270 | 4275 | ||
4271 | static int | 4276 | static int trident_game_cooked_read(struct gameport *gameport, |
4272 | trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) | 4277 | int *axes, int *buttons) |
4273 | { | 4278 | { |
4274 | struct trident_card *card = gameport->port_data; | 4279 | struct trident_card *card = gameport->port_data; |
4275 | int i; | 4280 | int i; |
@@ -4285,8 +4290,7 @@ trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) | |||
4285 | return 0; | 4290 | return 0; |
4286 | } | 4291 | } |
4287 | 4292 | ||
4288 | static int | 4293 | static int trident_game_open(struct gameport *gameport, int mode) |
4289 | trident_game_open(struct gameport *gameport, int mode) | ||
4290 | { | 4294 | { |
4291 | struct trident_card *card = gameport->port_data; | 4295 | struct trident_card *card = gameport->port_data; |
4292 | 4296 | ||
@@ -4305,8 +4309,7 @@ trident_game_open(struct gameport *gameport, int mode) | |||
4305 | return 0; | 4309 | return 0; |
4306 | } | 4310 | } |
4307 | 4311 | ||
4308 | static int __devinit | 4312 | static int __devinit trident_register_gameport(struct trident_card *card) |
4309 | trident_register_gameport(struct trident_card *card) | ||
4310 | { | 4313 | { |
4311 | struct gameport *gp; | 4314 | struct gameport *gp; |
4312 | 4315 | ||
@@ -4330,6 +4333,17 @@ trident_register_gameport(struct trident_card *card) | |||
4330 | return 0; | 4333 | return 0; |
4331 | } | 4334 | } |
4332 | 4335 | ||
4336 | static inline void trident_unregister_gameport(struct trident_card *card) | ||
4337 | { | ||
4338 | if (card->gameport) | ||
4339 | gameport_unregister_port(card->gameport); | ||
4340 | } | ||
4341 | |||
4342 | #else | ||
4343 | static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; } | ||
4344 | static inline void trident_unregister_gameport(struct trident_card *card) { } | ||
4345 | #endif /* SUPPORT_JOYSTICK */ | ||
4346 | |||
4333 | /* install the driver, we do not allocate hardware channel nor DMA buffer */ | 4347 | /* install the driver, we do not allocate hardware channel nor DMA buffer */ |
4334 | /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ | 4348 | /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ |
4335 | /* open/read/write/ioctl/mmap) */ | 4349 | /* open/read/write/ioctl/mmap) */ |
@@ -4569,8 +4583,7 @@ trident_remove(struct pci_dev *pci_dev) | |||
4569 | } | 4583 | } |
4570 | 4584 | ||
4571 | /* Unregister gameport */ | 4585 | /* Unregister gameport */ |
4572 | if (card->gameport) | 4586 | trident_unregister_gameport(card); |
4573 | gameport_unregister_port(card->gameport); | ||
4574 | 4587 | ||
4575 | /* Kill interrupts, and SP/DIF */ | 4588 | /* Kill interrupts, and SP/DIF */ |
4576 | trident_disable_loop_interrupts(card); | 4589 | trident_disable_loop_interrupts(card); |
diff --git a/sound/oss/v_midi.c b/sound/oss/v_midi.c index 077b76797665..a7ef04fab075 100644 --- a/sound/oss/v_midi.c +++ b/sound/oss/v_midi.c | |||
@@ -39,8 +39,6 @@ static void *midi_mem = NULL; | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | 41 | ||
42 | void (*midi_input_intr) (int dev, unsigned char data); | ||
43 | |||
44 | static int v_midi_open (int dev, int mode, | 42 | static int v_midi_open (int dev, int mode, |
45 | void (*input) (int dev, unsigned char data), | 43 | void (*input) (int dev, unsigned char data), |
46 | void (*output) (int dev) | 44 | void (*output) (int dev) |
diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c index b387e1e52485..83edda93f0b4 100644 --- a/sound/oss/via82cxxx_audio.c +++ b/sound/oss/via82cxxx_audio.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/smp_lock.h> | 35 | #include <linux/smp_lock.h> |
36 | #include <linux/ioport.h> | 36 | #include <linux/ioport.h> |
37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
38 | #include <linux/dma-mapping.h> | ||
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | #include <asm/semaphore.h> | 41 | #include <asm/semaphore.h> |
@@ -3391,10 +3392,10 @@ static int __devinit via_init_one (struct pci_dev *pdev, const struct pci_device | |||
3391 | if (rc) | 3392 | if (rc) |
3392 | goto err_out_disable; | 3393 | goto err_out_disable; |
3393 | 3394 | ||
3394 | rc = pci_set_dma_mask(pdev, 0xffffffffULL); | 3395 | rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
3395 | if (rc) | 3396 | if (rc) |
3396 | goto err_out_res; | 3397 | goto err_out_res; |
3397 | rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL); | 3398 | rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); |
3398 | if (rc) | 3399 | if (rc) |
3399 | goto err_out_res; | 3400 | goto err_out_res; |
3400 | 3401 | ||
diff --git a/sound/oss/wavfront.c b/sound/oss/wavfront.c index cce1278dc487..b92ba8921638 100644 --- a/sound/oss/wavfront.c +++ b/sound/oss/wavfront.c | |||
@@ -151,11 +151,11 @@ static int (*midi_load_patch) (int devno, int format, const char __user *addr, | |||
151 | 151 | ||
152 | /*** Module-accessible parameters ***************************************/ | 152 | /*** Module-accessible parameters ***************************************/ |
153 | 153 | ||
154 | int wf_raw; /* we normally check for "raw state" to firmware | 154 | static int wf_raw; /* we normally check for "raw state" to firmware |
155 | loading. if set, then during driver loading, the | 155 | loading. if set, then during driver loading, the |
156 | state of the board is ignored, and we reset the | 156 | state of the board is ignored, and we reset the |
157 | board and load the firmware anyway. | 157 | board and load the firmware anyway. |
158 | */ | 158 | */ |
159 | 159 | ||
160 | static int fx_raw = 1; /* if this is zero, we'll leave the FX processor in | 160 | static int fx_raw = 1; /* if this is zero, we'll leave the FX processor in |
161 | whatever state it is when the driver is loaded. | 161 | whatever state it is when the driver is loaded. |
@@ -2911,7 +2911,7 @@ int __init detect_wffx (void) | |||
2911 | return 0; | 2911 | return 0; |
2912 | } | 2912 | } |
2913 | 2913 | ||
2914 | void | 2914 | static void |
2915 | wffx_mute (int onoff) | 2915 | wffx_mute (int onoff) |
2916 | 2916 | ||
2917 | { | 2917 | { |
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 428efdbd70a1..6d7a00f34d82 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -274,6 +274,19 @@ config SND_HDSP | |||
274 | To compile this driver as a module, choose M here: the module | 274 | To compile this driver as a module, choose M here: the module |
275 | will be called snd-hdsp. | 275 | will be called snd-hdsp. |
276 | 276 | ||
277 | config SND_HDSPM | ||
278 | tristate "RME Hammerfall DSP MADI" | ||
279 | depends on SND | ||
280 | select SND_HWDEP | ||
281 | select SND_RAWMIDI | ||
282 | select SND_PCM | ||
283 | help | ||
284 | Say Y here to include support for RME Hammerfall DSP MADI | ||
285 | soundcards. | ||
286 | |||
287 | To compile this driver as a module, choose M here: the module | ||
288 | will be called snd-hdspm. | ||
289 | |||
277 | config SND_TRIDENT | 290 | config SND_TRIDENT |
278 | tristate "Trident 4D-Wave DX/NX; SiS 7018" | 291 | tristate "Trident 4D-Wave DX/NX; SiS 7018" |
279 | depends on SND | 292 | depends on SND |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 0b024ec1f709..6983eea226da 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -120,6 +120,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { | |||
120 | { 0x414c4770, 0xfffffff0, "ALC203", NULL, NULL }, | 120 | { 0x414c4770, 0xfffffff0, "ALC203", NULL, NULL }, |
121 | { 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL }, | 121 | { 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL }, |
122 | { 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL }, | 122 | { 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL }, |
123 | { 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL }, | ||
123 | { 0x434d4978, 0xffffffff, "CMI9761", patch_cm9761, NULL }, | 124 | { 0x434d4978, 0xffffffff, "CMI9761", patch_cm9761, NULL }, |
124 | { 0x434d4982, 0xffffffff, "CMI9761", patch_cm9761, NULL }, | 125 | { 0x434d4982, 0xffffffff, "CMI9761", patch_cm9761, NULL }, |
125 | { 0x434d4983, 0xffffffff, "CMI9761", patch_cm9761, NULL }, | 126 | { 0x434d4983, 0xffffffff, "CMI9761", patch_cm9761, NULL }, |
@@ -149,7 +150,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = { | |||
149 | { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, | 150 | { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, |
150 | { 0x4e534350, 0xffffffff, "LM4550", NULL, NULL }, | 151 | { 0x4e534350, 0xffffffff, "LM4550", NULL, NULL }, |
151 | { 0x50534304, 0xffffffff, "UCB1400", NULL, NULL }, | 152 | { 0x50534304, 0xffffffff, "UCB1400", NULL, NULL }, |
152 | { 0x53494c20, 0xffffffe0, "Si3036,8", NULL, mpatch_si3036 }, | 153 | { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, |
153 | { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, | 154 | { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, |
154 | { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, | 155 | { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, |
155 | { 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028, NULL }, // added by xin jin [07/09/99] | 156 | { 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028, NULL }, // added by xin jin [07/09/99] |
@@ -366,6 +367,7 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value) | |||
366 | ac97->regs[reg] = value; | 367 | ac97->regs[reg] = value; |
367 | ac97->bus->ops->write(ac97, reg, value); | 368 | ac97->bus->ops->write(ac97, reg, value); |
368 | } | 369 | } |
370 | set_bit(reg, ac97->reg_accessed); | ||
369 | up(&ac97->reg_mutex); | 371 | up(&ac97->reg_mutex); |
370 | return change; | 372 | return change; |
371 | } | 373 | } |
@@ -409,6 +411,7 @@ int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg, | |||
409 | ac97->regs[reg] = new; | 411 | ac97->regs[reg] = new; |
410 | ac97->bus->ops->write(ac97, reg, new); | 412 | ac97->bus->ops->write(ac97, reg, new); |
411 | } | 413 | } |
414 | set_bit(reg, ac97->reg_accessed); | ||
412 | return change; | 415 | return change; |
413 | } | 416 | } |
414 | 417 | ||
@@ -462,12 +465,14 @@ int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u | |||
462 | { | 465 | { |
463 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 466 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); |
464 | struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; | 467 | struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; |
465 | unsigned short val; | 468 | unsigned short val, bitmask; |
466 | 469 | ||
470 | for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) | ||
471 | ; | ||
467 | val = snd_ac97_read_cache(ac97, e->reg); | 472 | val = snd_ac97_read_cache(ac97, e->reg); |
468 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (e->mask - 1); | 473 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); |
469 | if (e->shift_l != e->shift_r) | 474 | if (e->shift_l != e->shift_r) |
470 | ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (e->mask - 1); | 475 | ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1); |
471 | 476 | ||
472 | return 0; | 477 | return 0; |
473 | } | 478 | } |
@@ -477,17 +482,19 @@ int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u | |||
477 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 482 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); |
478 | struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; | 483 | struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; |
479 | unsigned short val; | 484 | unsigned short val; |
480 | unsigned short mask; | 485 | unsigned short mask, bitmask; |
481 | 486 | ||
487 | for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) | ||
488 | ; | ||
482 | if (ucontrol->value.enumerated.item[0] > e->mask - 1) | 489 | if (ucontrol->value.enumerated.item[0] > e->mask - 1) |
483 | return -EINVAL; | 490 | return -EINVAL; |
484 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | 491 | val = ucontrol->value.enumerated.item[0] << e->shift_l; |
485 | mask = (e->mask - 1) << e->shift_l; | 492 | mask = (bitmask - 1) << e->shift_l; |
486 | if (e->shift_l != e->shift_r) { | 493 | if (e->shift_l != e->shift_r) { |
487 | if (ucontrol->value.enumerated.item[1] > e->mask - 1) | 494 | if (ucontrol->value.enumerated.item[1] > e->mask - 1) |
488 | return -EINVAL; | 495 | return -EINVAL; |
489 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 496 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
490 | mask |= (e->mask - 1) << e->shift_r; | 497 | mask |= (bitmask - 1) << e->shift_r; |
491 | } | 498 | } |
492 | return snd_ac97_update_bits(ac97, e->reg, mask, val); | 499 | return snd_ac97_update_bits(ac97, e->reg, mask, val); |
493 | } | 500 | } |
@@ -658,14 +665,14 @@ AC97_SINGLE("LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 1, 1), | |||
658 | AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1) | 665 | AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1) |
659 | }; | 666 | }; |
660 | 667 | ||
661 | static const snd_kcontrol_new_t snd_ac97_controls_surround[2] = { | ||
662 | AC97_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1), | ||
663 | AC97_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1), | ||
664 | }; | ||
665 | |||
666 | static const snd_kcontrol_new_t snd_ac97_control_eapd = | 668 | static const snd_kcontrol_new_t snd_ac97_control_eapd = |
667 | AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1); | 669 | AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1); |
668 | 670 | ||
671 | static const snd_kcontrol_new_t snd_ac97_controls_modem_switches[2] = { | ||
672 | AC97_SINGLE("Off-hook Switch", AC97_GPIO_STATUS, 0, 1, 0), | ||
673 | AC97_SINGLE("Caller ID Switch", AC97_GPIO_STATUS, 2, 1, 0) | ||
674 | }; | ||
675 | |||
669 | /* change the existing EAPD control as inverted */ | 676 | /* change the existing EAPD control as inverted */ |
670 | static void set_inv_eapd(ac97_t *ac97, snd_kcontrol_t *kctl) | 677 | static void set_inv_eapd(ac97_t *ac97, snd_kcontrol_t *kctl) |
671 | { | 678 | { |
@@ -1071,10 +1078,15 @@ static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max | |||
1071 | for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { | 1078 | for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { |
1072 | unsigned short val; | 1079 | unsigned short val; |
1073 | snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8)); | 1080 | snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8)); |
1081 | /* Do the read twice due to buffers on some ac97 codecs. | ||
1082 | * e.g. The STAC9704 returns exactly what you wrote the the register | ||
1083 | * if you read it immediately. This causes the detect routine to fail. | ||
1084 | */ | ||
1074 | val = snd_ac97_read(ac97, reg); | 1085 | val = snd_ac97_read(ac97, reg); |
1075 | if (! *lo_max && (val & cbit[i])) | 1086 | val = snd_ac97_read(ac97, reg); |
1087 | if (! *lo_max && (val & 0x7f) == cbit[i]) | ||
1076 | *lo_max = max[i]; | 1088 | *lo_max = max[i]; |
1077 | if (! *hi_max && (val & (cbit[i] << 8))) | 1089 | if (! *hi_max && ((val >> 8) & 0x7f) == cbit[i]) |
1078 | *hi_max = max[i]; | 1090 | *hi_max = max[i]; |
1079 | if (*lo_max && *hi_max) | 1091 | if (*lo_max && *hi_max) |
1080 | break; | 1092 | break; |
@@ -1526,13 +1538,25 @@ static int snd_ac97_mixer_build(ac97_t * ac97) | |||
1526 | 1538 | ||
1527 | static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97) | 1539 | static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97) |
1528 | { | 1540 | { |
1529 | /* TODO */ | 1541 | int err, idx; |
1542 | |||
1530 | //printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG)); | 1543 | //printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG)); |
1531 | snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH)); | 1544 | snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH)); |
1532 | snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH)); | 1545 | snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH)); |
1533 | snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff); | 1546 | snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff); |
1534 | snd_ac97_write(ac97, AC97_GPIO_WAKEUP, 0x0); | 1547 | snd_ac97_write(ac97, AC97_GPIO_WAKEUP, 0x0); |
1535 | snd_ac97_write(ac97, AC97_MISC_AFE, 0x0); | 1548 | snd_ac97_write(ac97, AC97_MISC_AFE, 0x0); |
1549 | |||
1550 | /* build modem switches */ | ||
1551 | for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++) | ||
1552 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_modem_switches[idx], ac97))) < 0) | ||
1553 | return err; | ||
1554 | |||
1555 | /* build chip specific controls */ | ||
1556 | if (ac97->build_ops->build_specific) | ||
1557 | if ((err = ac97->build_ops->build_specific(ac97)) < 0) | ||
1558 | return err; | ||
1559 | |||
1536 | return 0; | 1560 | return 0; |
1537 | } | 1561 | } |
1538 | 1562 | ||
@@ -1872,7 +1896,11 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) | |||
1872 | goto __access_ok; | 1896 | goto __access_ok; |
1873 | } | 1897 | } |
1874 | 1898 | ||
1875 | snd_ac97_write(ac97, AC97_RESET, 0); /* reset to defaults */ | 1899 | /* reset to defaults */ |
1900 | if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO)) | ||
1901 | snd_ac97_write(ac97, AC97_RESET, 0); | ||
1902 | if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM)) | ||
1903 | snd_ac97_write(ac97, AC97_EXTENDED_MID, 0); | ||
1876 | if (bus->ops->wait) | 1904 | if (bus->ops->wait) |
1877 | bus->ops->wait(ac97); | 1905 | bus->ops->wait(ac97); |
1878 | else { | 1906 | else { |
@@ -1964,21 +1992,21 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) | |||
1964 | /* note: it's important to set the rate at first */ | 1992 | /* note: it's important to set the rate at first */ |
1965 | tmp = AC97_MEA_GPIO; | 1993 | tmp = AC97_MEA_GPIO; |
1966 | if (ac97->ext_mid & AC97_MEI_LINE1) { | 1994 | if (ac97->ext_mid & AC97_MEI_LINE1) { |
1967 | snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 12000); | 1995 | snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 8000); |
1968 | tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1; | 1996 | tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1; |
1969 | } | 1997 | } |
1970 | if (ac97->ext_mid & AC97_MEI_LINE2) { | 1998 | if (ac97->ext_mid & AC97_MEI_LINE2) { |
1971 | snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 12000); | 1999 | snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 8000); |
1972 | tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2; | 2000 | tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2; |
1973 | } | 2001 | } |
1974 | if (ac97->ext_mid & AC97_MEI_HANDSET) { | 2002 | if (ac97->ext_mid & AC97_MEI_HANDSET) { |
1975 | snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 12000); | 2003 | snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 8000); |
1976 | tmp |= AC97_MEA_HADC | AC97_MEA_HDAC; | 2004 | tmp |= AC97_MEA_HADC | AC97_MEA_HDAC; |
1977 | } | 2005 | } |
1978 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8)); | 2006 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); |
1979 | udelay(100); | 2007 | udelay(100); |
1980 | /* nothing should be in powerdown mode */ | 2008 | /* nothing should be in powerdown mode */ |
1981 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8)); | 2009 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); |
1982 | end_time = jiffies + (HZ / 10); | 2010 | end_time = jiffies + (HZ / 10); |
1983 | do { | 2011 | do { |
1984 | if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) | 2012 | if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) |
@@ -2203,7 +2231,7 @@ void snd_ac97_restore_iec958(ac97_t *ac97) | |||
2203 | */ | 2231 | */ |
2204 | void snd_ac97_resume(ac97_t *ac97) | 2232 | void snd_ac97_resume(ac97_t *ac97) |
2205 | { | 2233 | { |
2206 | int i; | 2234 | unsigned long end_time; |
2207 | 2235 | ||
2208 | if (ac97->bus->ops->reset) { | 2236 | if (ac97->bus->ops->reset) { |
2209 | ac97->bus->ops->reset(ac97); | 2237 | ac97->bus->ops->reset(ac97); |
@@ -2221,26 +2249,26 @@ void snd_ac97_resume(ac97_t *ac97) | |||
2221 | snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]); | 2249 | snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]); |
2222 | if (ac97_is_audio(ac97)) { | 2250 | if (ac97_is_audio(ac97)) { |
2223 | ac97->bus->ops->write(ac97, AC97_MASTER, 0x8101); | 2251 | ac97->bus->ops->write(ac97, AC97_MASTER, 0x8101); |
2224 | for (i = HZ/10; i >= 0; i--) { | 2252 | end_time = jiffies + msecs_to_jiffies(100); |
2253 | do { | ||
2225 | if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101) | 2254 | if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101) |
2226 | break; | 2255 | break; |
2227 | set_current_state(TASK_UNINTERRUPTIBLE); | 2256 | set_current_state(TASK_UNINTERRUPTIBLE); |
2228 | schedule_timeout(1); | 2257 | schedule_timeout(1); |
2229 | } | 2258 | } while (time_after_eq(end_time, jiffies)); |
2230 | /* FIXME: extra delay */ | 2259 | /* FIXME: extra delay */ |
2231 | ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000); | 2260 | ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000); |
2232 | if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) { | 2261 | if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) |
2233 | set_current_state(TASK_UNINTERRUPTIBLE); | 2262 | msleep(250); |
2234 | schedule_timeout(HZ/4); | ||
2235 | } | ||
2236 | } else { | 2263 | } else { |
2237 | for (i = HZ/10; i >= 0; i--) { | 2264 | end_time = jiffies + msecs_to_jiffies(100); |
2265 | do { | ||
2238 | unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID); | 2266 | unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID); |
2239 | if (val != 0xffff && (val & 1) != 0) | 2267 | if (val != 0xffff && (val & 1) != 0) |
2240 | break; | 2268 | break; |
2241 | set_current_state(TASK_UNINTERRUPTIBLE); | 2269 | set_current_state(TASK_UNINTERRUPTIBLE); |
2242 | schedule_timeout(1); | 2270 | schedule_timeout(1); |
2243 | } | 2271 | } while (time_after_eq(end_time, jiffies)); |
2244 | } | 2272 | } |
2245 | __reset_ready: | 2273 | __reset_ready: |
2246 | 2274 | ||
@@ -2521,11 +2549,11 @@ int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *o | |||
2521 | return result; | 2549 | return result; |
2522 | } | 2550 | } |
2523 | 2551 | ||
2524 | for (; quirk->vendor; quirk++) { | 2552 | for (; quirk->subvendor; quirk++) { |
2525 | if (quirk->vendor != ac97->subsystem_vendor) | 2553 | if (quirk->subvendor != ac97->subsystem_vendor) |
2526 | continue; | 2554 | continue; |
2527 | if ((! quirk->mask && quirk->device == ac97->subsystem_device) || | 2555 | if ((! quirk->mask && quirk->subdevice == ac97->subsystem_device) || |
2528 | quirk->device == (quirk->mask & ac97->subsystem_device)) { | 2556 | quirk->subdevice == (quirk->mask & ac97->subsystem_device)) { |
2529 | if (quirk->codec_id && quirk->codec_id != ac97->id) | 2557 | if (quirk->codec_id && quirk->codec_id != ac97->id) |
2530 | continue; | 2558 | continue; |
2531 | snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device); | 2559 | snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device); |
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 13c34a5d8206..66edc857d3e6 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -64,6 +64,116 @@ static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned shor | |||
64 | return ret; | 64 | return ret; |
65 | } | 65 | } |
66 | 66 | ||
67 | /* | ||
68 | * shared line-in/mic controls | ||
69 | */ | ||
70 | static int ac97_enum_text_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo, | ||
71 | const char **texts, unsigned int nums) | ||
72 | { | ||
73 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
74 | uinfo->count = 1; | ||
75 | uinfo->value.enumerated.items = nums; | ||
76 | if (uinfo->value.enumerated.item > nums - 1) | ||
77 | uinfo->value.enumerated.item = nums - 1; | ||
78 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int ac97_surround_jack_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
83 | { | ||
84 | static const char *texts[] = { "Shared", "Independent" }; | ||
85 | return ac97_enum_text_info(kcontrol, uinfo, texts, 2); | ||
86 | } | ||
87 | |||
88 | static int ac97_surround_jack_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
89 | { | ||
90 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
91 | |||
92 | ucontrol->value.enumerated.item[0] = ac97->indep_surround; | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int ac97_surround_jack_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
97 | { | ||
98 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
99 | unsigned char indep = !!ucontrol->value.enumerated.item[0]; | ||
100 | |||
101 | if (indep != ac97->indep_surround) { | ||
102 | ac97->indep_surround = indep; | ||
103 | if (ac97->build_ops->update_jacks) | ||
104 | ac97->build_ops->update_jacks(ac97); | ||
105 | return 1; | ||
106 | } | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int ac97_channel_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
111 | { | ||
112 | static const char *texts[] = { "2ch", "4ch", "6ch" }; | ||
113 | if (kcontrol->private_value) | ||
114 | return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */ | ||
115 | return ac97_enum_text_info(kcontrol, uinfo, texts, 3); | ||
116 | } | ||
117 | |||
118 | static int ac97_channel_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
119 | { | ||
120 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
121 | |||
122 | ucontrol->value.enumerated.item[0] = ac97->channel_mode; | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int ac97_channel_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
127 | { | ||
128 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
129 | unsigned char mode = ucontrol->value.enumerated.item[0]; | ||
130 | |||
131 | if (mode != ac97->channel_mode) { | ||
132 | ac97->channel_mode = mode; | ||
133 | if (ac97->build_ops->update_jacks) | ||
134 | ac97->build_ops->update_jacks(ac97); | ||
135 | return 1; | ||
136 | } | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | #define AC97_SURROUND_JACK_MODE_CTL \ | ||
141 | { \ | ||
142 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
143 | .name = "Surround Jack Mode", \ | ||
144 | .info = ac97_surround_jack_mode_info, \ | ||
145 | .get = ac97_surround_jack_mode_get, \ | ||
146 | .put = ac97_surround_jack_mode_put, \ | ||
147 | } | ||
148 | #define AC97_CHANNEL_MODE_CTL \ | ||
149 | { \ | ||
150 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
151 | .name = "Channel Mode", \ | ||
152 | .info = ac97_channel_mode_info, \ | ||
153 | .get = ac97_channel_mode_get, \ | ||
154 | .put = ac97_channel_mode_put, \ | ||
155 | } | ||
156 | #define AC97_CHANNEL_MODE_4CH_CTL \ | ||
157 | { \ | ||
158 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
159 | .name = "Channel Mode", \ | ||
160 | .info = ac97_channel_mode_info, \ | ||
161 | .get = ac97_channel_mode_get, \ | ||
162 | .put = ac97_channel_mode_put, \ | ||
163 | .private_value = 1, \ | ||
164 | } | ||
165 | |||
166 | static inline int is_shared_linein(ac97_t *ac97) | ||
167 | { | ||
168 | return ! ac97->indep_surround && ac97->channel_mode >= 1; | ||
169 | } | ||
170 | |||
171 | static inline int is_shared_micin(ac97_t *ac97) | ||
172 | { | ||
173 | return ! ac97->indep_surround && ac97->channel_mode >= 2; | ||
174 | } | ||
175 | |||
176 | |||
67 | /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ | 177 | /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ |
68 | 178 | ||
69 | /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */ | 179 | /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */ |
@@ -1390,6 +1500,16 @@ static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va | |||
1390 | AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val); | 1500 | AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val); |
1391 | } | 1501 | } |
1392 | 1502 | ||
1503 | static void ad1888_update_jacks(ac97_t *ac97) | ||
1504 | { | ||
1505 | /* shared Line-In */ | ||
1506 | snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12, | ||
1507 | is_shared_linein(ac97) ? 0 : 1 << 12); | ||
1508 | /* shared Mic */ | ||
1509 | snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11, | ||
1510 | is_shared_micin(ac97) ? 0 : 1 << 11); | ||
1511 | } | ||
1512 | |||
1393 | static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = { | 1513 | static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = { |
1394 | { | 1514 | { |
1395 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1515 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -1406,8 +1526,11 @@ static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = { | |||
1406 | .get = snd_ac97_ad1888_downmix_get, | 1526 | .get = snd_ac97_ad1888_downmix_get, |
1407 | .put = snd_ac97_ad1888_downmix_put | 1527 | .put = snd_ac97_ad1888_downmix_put |
1408 | }, | 1528 | }, |
1409 | AC97_SINGLE("Surround Jack as Input", AC97_AD_MISC, 12, 1, 0), | 1529 | AC97_SURROUND_JACK_MODE_CTL, |
1410 | AC97_SINGLE("Center/LFE Jack as Input", AC97_AD_MISC, 11, 1, 0), | 1530 | AC97_CHANNEL_MODE_CTL, |
1531 | |||
1532 | AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0), | ||
1533 | AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0), | ||
1411 | }; | 1534 | }; |
1412 | 1535 | ||
1413 | static int patch_ad1888_specific(ac97_t *ac97) | 1536 | static int patch_ad1888_specific(ac97_t *ac97) |
@@ -1422,8 +1545,9 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = { | |||
1422 | .build_post_spdif = patch_ad198x_post_spdif, | 1545 | .build_post_spdif = patch_ad198x_post_spdif, |
1423 | .build_specific = patch_ad1888_specific, | 1546 | .build_specific = patch_ad1888_specific, |
1424 | #ifdef CONFIG_PM | 1547 | #ifdef CONFIG_PM |
1425 | .resume = ad18xx_resume | 1548 | .resume = ad18xx_resume, |
1426 | #endif | 1549 | #endif |
1550 | .update_jacks = ad1888_update_jacks, | ||
1427 | }; | 1551 | }; |
1428 | 1552 | ||
1429 | int patch_ad1888(ac97_t * ac97) | 1553 | int patch_ad1888(ac97_t * ac97) |
@@ -1459,8 +1583,9 @@ static struct snd_ac97_build_ops patch_ad1980_build_ops = { | |||
1459 | .build_post_spdif = patch_ad198x_post_spdif, | 1583 | .build_post_spdif = patch_ad198x_post_spdif, |
1460 | .build_specific = patch_ad1980_specific, | 1584 | .build_specific = patch_ad1980_specific, |
1461 | #ifdef CONFIG_PM | 1585 | #ifdef CONFIG_PM |
1462 | .resume = ad18xx_resume | 1586 | .resume = ad18xx_resume, |
1463 | #endif | 1587 | #endif |
1588 | .update_jacks = ad1888_update_jacks, | ||
1464 | }; | 1589 | }; |
1465 | 1590 | ||
1466 | int patch_ad1980(ac97_t * ac97) | 1591 | int patch_ad1980(ac97_t * ac97) |
@@ -1471,10 +1596,21 @@ int patch_ad1980(ac97_t * ac97) | |||
1471 | } | 1596 | } |
1472 | 1597 | ||
1473 | static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = { | 1598 | static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = { |
1474 | AC97_SINGLE("Center/LFE Jack as Mic", AC97_AD_SERIAL_CFG, 9, 1, 0), | ||
1475 | AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0) | 1599 | AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0) |
1476 | }; | 1600 | }; |
1477 | 1601 | ||
1602 | static void ad1985_update_jacks(ac97_t *ac97) | ||
1603 | { | ||
1604 | /* shared Line-In */ | ||
1605 | snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12, | ||
1606 | is_shared_linein(ac97) ? 0 : 1 << 12); | ||
1607 | /* shared Mic */ | ||
1608 | snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11, | ||
1609 | is_shared_micin(ac97) ? 0 : 1 << 11); | ||
1610 | snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9, | ||
1611 | is_shared_micin(ac97) ? 0 : 1 << 9); | ||
1612 | } | ||
1613 | |||
1478 | static int patch_ad1985_specific(ac97_t *ac97) | 1614 | static int patch_ad1985_specific(ac97_t *ac97) |
1479 | { | 1615 | { |
1480 | int err; | 1616 | int err; |
@@ -1488,8 +1624,9 @@ static struct snd_ac97_build_ops patch_ad1985_build_ops = { | |||
1488 | .build_post_spdif = patch_ad198x_post_spdif, | 1624 | .build_post_spdif = patch_ad198x_post_spdif, |
1489 | .build_specific = patch_ad1985_specific, | 1625 | .build_specific = patch_ad1985_specific, |
1490 | #ifdef CONFIG_PM | 1626 | #ifdef CONFIG_PM |
1491 | .resume = ad18xx_resume | 1627 | .resume = ad18xx_resume, |
1492 | #endif | 1628 | #endif |
1629 | .update_jacks = ad1985_update_jacks, | ||
1493 | }; | 1630 | }; |
1494 | 1631 | ||
1495 | int patch_ad1985(ac97_t * ac97) | 1632 | int patch_ad1985(ac97_t * ac97) |
@@ -1521,31 +1658,25 @@ int patch_ad1985(ac97_t * ac97) | |||
1521 | /* | 1658 | /* |
1522 | * realtek ALC65x/850 codecs | 1659 | * realtek ALC65x/850 codecs |
1523 | */ | 1660 | */ |
1524 | static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | 1661 | static void alc650_update_jacks(ac97_t *ac97) |
1525 | { | ||
1526 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
1527 | ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1; | ||
1528 | return 0; | ||
1529 | } | ||
1530 | |||
1531 | static int snd_ac97_alc650_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
1532 | { | 1662 | { |
1533 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 1663 | int shared; |
1534 | int change, val; | 1664 | |
1535 | val = !!(snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10)); | 1665 | /* shared Line-In */ |
1536 | change = (ucontrol->value.integer.value[0] != val); | 1666 | shared = is_shared_linein(ac97); |
1537 | if (change) { | 1667 | snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9, |
1538 | /* disable/enable vref */ | 1668 | shared ? (1 << 9) : 0); |
1539 | snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, | 1669 | /* update shared Mic */ |
1540 | ucontrol->value.integer.value[0] ? (1 << 12) : 0); | 1670 | shared = is_shared_micin(ac97); |
1541 | /* turn on/off center-on-mic */ | 1671 | /* disable/enable vref */ |
1542 | snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10, | 1672 | snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, |
1543 | ucontrol->value.integer.value[0] ? (1 << 10) : 0); | 1673 | shared ? (1 << 12) : 0); |
1544 | /* GPIO0 high for mic */ | 1674 | /* turn on/off center-on-mic */ |
1545 | snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100, | 1675 | snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10, |
1546 | ucontrol->value.integer.value[0] ? 0 : 0x100); | 1676 | shared ? (1 << 10) : 0); |
1547 | } | 1677 | /* GPIO0 high for mic */ |
1548 | return change; | 1678 | snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100, |
1679 | shared ? 0 : 0x100); | ||
1549 | } | 1680 | } |
1550 | 1681 | ||
1551 | static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { | 1682 | static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { |
@@ -1558,8 +1689,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { | |||
1558 | /* 6: Independent Master Volume Right */ | 1689 | /* 6: Independent Master Volume Right */ |
1559 | /* 7: Independent Master Volume Left */ | 1690 | /* 7: Independent Master Volume Left */ |
1560 | /* 8: reserved */ | 1691 | /* 8: reserved */ |
1561 | AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0), | 1692 | /* 9: Line-In/Surround share */ |
1562 | /* 10: mic, see below */ | 1693 | /* 10: Mic/CLFE share */ |
1563 | /* 11-13: in IEC958 controls */ | 1694 | /* 11-13: in IEC958 controls */ |
1564 | AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0), | 1695 | AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0), |
1565 | #if 0 /* always set in patch_alc650 */ | 1696 | #if 0 /* always set in patch_alc650 */ |
@@ -1570,14 +1701,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { | |||
1570 | AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1), | 1701 | AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1), |
1571 | AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1), | 1702 | AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1), |
1572 | #endif | 1703 | #endif |
1573 | { | 1704 | AC97_SURROUND_JACK_MODE_CTL, |
1574 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1705 | AC97_CHANNEL_MODE_CTL, |
1575 | .name = "Mic As Center/LFE", | ||
1576 | .info = snd_ac97_info_volsw, | ||
1577 | .get = snd_ac97_alc650_mic_get, | ||
1578 | .put = snd_ac97_alc650_mic_put, | ||
1579 | .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ | ||
1580 | }, | ||
1581 | }; | 1706 | }; |
1582 | 1707 | ||
1583 | static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = { | 1708 | static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = { |
@@ -1601,7 +1726,8 @@ static int patch_alc650_specific(ac97_t * ac97) | |||
1601 | } | 1726 | } |
1602 | 1727 | ||
1603 | static struct snd_ac97_build_ops patch_alc650_ops = { | 1728 | static struct snd_ac97_build_ops patch_alc650_ops = { |
1604 | .build_specific = patch_alc650_specific | 1729 | .build_specific = patch_alc650_specific, |
1730 | .update_jacks = alc650_update_jacks | ||
1605 | }; | 1731 | }; |
1606 | 1732 | ||
1607 | int patch_alc650(ac97_t * ac97) | 1733 | int patch_alc650(ac97_t * ac97) |
@@ -1659,37 +1785,27 @@ int patch_alc650(ac97_t * ac97) | |||
1659 | return 0; | 1785 | return 0; |
1660 | } | 1786 | } |
1661 | 1787 | ||
1662 | static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | 1788 | static void alc655_update_jacks(ac97_t *ac97) |
1663 | { | ||
1664 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
1665 | ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1; | ||
1666 | return 0; | ||
1667 | } | ||
1668 | |||
1669 | static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
1670 | { | 1789 | { |
1671 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 1790 | int shared; |
1672 | 1791 | ||
1792 | /* shared Line-In */ | ||
1793 | shared = is_shared_linein(ac97); | ||
1794 | ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9, | ||
1795 | shared ? (1 << 9) : 0, 0); | ||
1796 | /* update shared mic */ | ||
1797 | shared = is_shared_micin(ac97); | ||
1673 | /* misc control; vrefout disable */ | 1798 | /* misc control; vrefout disable */ |
1674 | snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, | 1799 | snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, |
1675 | ucontrol->value.integer.value[0] ? (1 << 12) : 0); | 1800 | shared ? (1 << 12) : 0); |
1676 | return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10, | 1801 | ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10, |
1677 | ucontrol->value.integer.value[0] ? (1 << 10) : 0, | 1802 | shared ? (1 << 10) : 0, 0); |
1678 | 0); | ||
1679 | } | 1803 | } |
1680 | 1804 | ||
1681 | |||
1682 | static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = { | 1805 | static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = { |
1683 | AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), | 1806 | AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), |
1684 | AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0), | 1807 | AC97_SURROUND_JACK_MODE_CTL, |
1685 | { | 1808 | AC97_CHANNEL_MODE_CTL, |
1686 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1687 | .name = "Mic As Center/LFE", | ||
1688 | .info = snd_ac97_info_volsw, | ||
1689 | .get = snd_ac97_alc655_mic_get, | ||
1690 | .put = snd_ac97_alc655_mic_put, | ||
1691 | .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ | ||
1692 | }, | ||
1693 | }; | 1809 | }; |
1694 | 1810 | ||
1695 | static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | 1811 | static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) |
@@ -1759,7 +1875,8 @@ static int patch_alc655_specific(ac97_t * ac97) | |||
1759 | } | 1875 | } |
1760 | 1876 | ||
1761 | static struct snd_ac97_build_ops patch_alc655_ops = { | 1877 | static struct snd_ac97_build_ops patch_alc655_ops = { |
1762 | .build_specific = patch_alc655_specific | 1878 | .build_specific = patch_alc655_specific, |
1879 | .update_jacks = alc655_update_jacks | ||
1763 | }; | 1880 | }; |
1764 | 1881 | ||
1765 | int patch_alc655(ac97_t * ac97) | 1882 | int patch_alc655(ac97_t * ac97) |
@@ -1798,63 +1915,33 @@ int patch_alc655(ac97_t * ac97) | |||
1798 | #define AC97_ALC850_JACK_SELECT 0x76 | 1915 | #define AC97_ALC850_JACK_SELECT 0x76 |
1799 | #define AC97_ALC850_MISC1 0x7a | 1916 | #define AC97_ALC850_MISC1 0x7a |
1800 | 1917 | ||
1801 | static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | 1918 | static void alc850_update_jacks(ac97_t *ac97) |
1802 | { | ||
1803 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
1804 | ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2; | ||
1805 | return 0; | ||
1806 | } | ||
1807 | |||
1808 | static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
1809 | { | 1919 | { |
1810 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 1920 | int shared; |
1811 | 1921 | ||
1922 | /* shared Line-In */ | ||
1923 | shared = is_shared_linein(ac97); | ||
1812 | /* SURR 1kOhm (bit4), Amp (bit5) */ | 1924 | /* SURR 1kOhm (bit4), Amp (bit5) */ |
1813 | snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5), | 1925 | snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5), |
1814 | ucontrol->value.integer.value[0] ? (1<<5) : (1<<4)); | 1926 | shared ? (1<<5) : (1<<4)); |
1815 | /* LINE-IN = 0, SURROUND = 2 */ | 1927 | /* LINE-IN = 0, SURROUND = 2 */ |
1816 | return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12, | 1928 | snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12, |
1817 | ucontrol->value.integer.value[0] ? (2<<12) : (0<<12)); | 1929 | shared ? (2<<12) : (0<<12)); |
1818 | } | 1930 | /* update shared mic */ |
1819 | 1931 | shared = is_shared_micin(ac97); | |
1820 | static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
1821 | { | ||
1822 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
1823 | ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2; | ||
1824 | return 0; | ||
1825 | } | ||
1826 | |||
1827 | static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
1828 | { | ||
1829 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
1830 | |||
1831 | /* Vref disable (bit12), 1kOhm (bit13) */ | 1932 | /* Vref disable (bit12), 1kOhm (bit13) */ |
1832 | snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13), | 1933 | snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13), |
1833 | ucontrol->value.integer.value[0] ? (1<<12) : (1<<13)); | 1934 | shared ? (1<<12) : (1<<13)); |
1834 | /* MIC-IN = 1, CENTER-LFE = 2 */ | 1935 | /* MIC-IN = 1, CENTER-LFE = 2 */ |
1835 | return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, | 1936 | snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, |
1836 | ucontrol->value.integer.value[0] ? (2<<4) : (1<<4)); | 1937 | shared ? (2<<4) : (1<<4)); |
1837 | } | 1938 | } |
1838 | 1939 | ||
1839 | static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = { | 1940 | static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = { |
1840 | AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), | 1941 | AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), |
1841 | { | 1942 | AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1), |
1842 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1943 | AC97_SURROUND_JACK_MODE_CTL, |
1843 | .name = "Line-In As Surround", | 1944 | AC97_CHANNEL_MODE_CTL, |
1844 | .info = snd_ac97_info_volsw, | ||
1845 | .get = ac97_alc850_surround_get, | ||
1846 | .put = ac97_alc850_surround_put, | ||
1847 | .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ | ||
1848 | }, | ||
1849 | { | ||
1850 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1851 | .name = "Mic As Center/LFE", | ||
1852 | .info = snd_ac97_info_volsw, | ||
1853 | .get = ac97_alc850_mic_get, | ||
1854 | .put = ac97_alc850_mic_put, | ||
1855 | .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ | ||
1856 | }, | ||
1857 | |||
1858 | }; | 1945 | }; |
1859 | 1946 | ||
1860 | static int patch_alc850_specific(ac97_t *ac97) | 1947 | static int patch_alc850_specific(ac97_t *ac97) |
@@ -1871,7 +1958,8 @@ static int patch_alc850_specific(ac97_t *ac97) | |||
1871 | } | 1958 | } |
1872 | 1959 | ||
1873 | static struct snd_ac97_build_ops patch_alc850_ops = { | 1960 | static struct snd_ac97_build_ops patch_alc850_ops = { |
1874 | .build_specific = patch_alc850_specific | 1961 | .build_specific = patch_alc850_specific, |
1962 | .update_jacks = alc850_update_jacks | ||
1875 | }; | 1963 | }; |
1876 | 1964 | ||
1877 | int patch_alc850(ac97_t *ac97) | 1965 | int patch_alc850(ac97_t *ac97) |
@@ -1911,9 +1999,17 @@ int patch_alc850(ac97_t *ac97) | |||
1911 | /* | 1999 | /* |
1912 | * C-Media CM97xx codecs | 2000 | * C-Media CM97xx codecs |
1913 | */ | 2001 | */ |
2002 | static void cm9738_update_jacks(ac97_t *ac97) | ||
2003 | { | ||
2004 | /* shared Line-In */ | ||
2005 | snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10, | ||
2006 | is_shared_linein(ac97) ? (1 << 10) : 0); | ||
2007 | } | ||
2008 | |||
1914 | static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = { | 2009 | static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = { |
1915 | AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0), | ||
1916 | AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0), | 2010 | AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0), |
2011 | AC97_SURROUND_JACK_MODE_CTL, | ||
2012 | AC97_CHANNEL_MODE_4CH_CTL, | ||
1917 | }; | 2013 | }; |
1918 | 2014 | ||
1919 | static int patch_cm9738_specific(ac97_t * ac97) | 2015 | static int patch_cm9738_specific(ac97_t * ac97) |
@@ -1922,7 +2018,8 @@ static int patch_cm9738_specific(ac97_t * ac97) | |||
1922 | } | 2018 | } |
1923 | 2019 | ||
1924 | static struct snd_ac97_build_ops patch_cm9738_ops = { | 2020 | static struct snd_ac97_build_ops patch_cm9738_ops = { |
1925 | .build_specific = patch_cm9738_specific | 2021 | .build_specific = patch_cm9738_specific, |
2022 | .update_jacks = cm9738_update_jacks | ||
1926 | }; | 2023 | }; |
1927 | 2024 | ||
1928 | int patch_cm9738(ac97_t * ac97) | 2025 | int patch_cm9738(ac97_t * ac97) |
@@ -1986,34 +2083,19 @@ static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = { | |||
1986 | /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */ | 2083 | /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */ |
1987 | }; | 2084 | }; |
1988 | 2085 | ||
1989 | static int snd_ac97_cm9739_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 2086 | static void cm9739_update_jacks(ac97_t *ac97) |
1990 | { | ||
1991 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
1992 | if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000) | ||
1993 | ucontrol->value.integer.value[0] = 1; | ||
1994 | else | ||
1995 | ucontrol->value.integer.value[0] = 0; | ||
1996 | return 0; | ||
1997 | } | ||
1998 | |||
1999 | static int snd_ac97_cm9739_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
2000 | { | 2087 | { |
2001 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 2088 | /* shared Line-In */ |
2002 | return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000, | 2089 | snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10, |
2003 | ucontrol->value.integer.value[0] ? | 2090 | is_shared_linein(ac97) ? (1 << 10) : 0); |
2004 | 0x1000 : 0x2000); | 2091 | /* shared Mic */ |
2092 | snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000, | ||
2093 | is_shared_micin(ac97) ? 0x1000 : 0x2000); | ||
2005 | } | 2094 | } |
2006 | 2095 | ||
2007 | static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = { | 2096 | static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = { |
2008 | AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0), | 2097 | AC97_SURROUND_JACK_MODE_CTL, |
2009 | { | 2098 | AC97_CHANNEL_MODE_CTL, |
2010 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2011 | .name = "Mic As Center/LFE", | ||
2012 | .info = snd_ac97_info_volsw, | ||
2013 | .get = snd_ac97_cm9739_center_mic_get, | ||
2014 | .put = snd_ac97_cm9739_center_mic_put, | ||
2015 | .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ | ||
2016 | }, | ||
2017 | }; | 2099 | }; |
2018 | 2100 | ||
2019 | static int patch_cm9739_specific(ac97_t * ac97) | 2101 | static int patch_cm9739_specific(ac97_t * ac97) |
@@ -2028,7 +2110,8 @@ static int patch_cm9739_post_spdif(ac97_t * ac97) | |||
2028 | 2110 | ||
2029 | static struct snd_ac97_build_ops patch_cm9739_ops = { | 2111 | static struct snd_ac97_build_ops patch_cm9739_ops = { |
2030 | .build_specific = patch_cm9739_specific, | 2112 | .build_specific = patch_cm9739_specific, |
2031 | .build_post_spdif = patch_cm9739_post_spdif | 2113 | .build_post_spdif = patch_cm9739_post_spdif, |
2114 | .update_jacks = cm9739_update_jacks | ||
2032 | }; | 2115 | }; |
2033 | 2116 | ||
2034 | int patch_cm9739(ac97_t * ac97) | 2117 | int patch_cm9739(ac97_t * ac97) |
@@ -2087,71 +2170,97 @@ int patch_cm9739(ac97_t * ac97) | |||
2087 | } | 2170 | } |
2088 | 2171 | ||
2089 | #define AC97_CM9761_MULTI_CHAN 0x64 | 2172 | #define AC97_CM9761_MULTI_CHAN 0x64 |
2173 | #define AC97_CM9761_FUNC 0x66 | ||
2090 | #define AC97_CM9761_SPDIF_CTRL 0x6c | 2174 | #define AC97_CM9761_SPDIF_CTRL 0x6c |
2091 | 2175 | ||
2092 | static int snd_ac97_cm9761_linein_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 2176 | static void cm9761_update_jacks(ac97_t *ac97) |
2093 | { | ||
2094 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
2095 | if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x0400) | ||
2096 | ucontrol->value.integer.value[0] = 1; | ||
2097 | else | ||
2098 | ucontrol->value.integer.value[0] = 0; | ||
2099 | return 0; | ||
2100 | } | ||
2101 | |||
2102 | static int snd_ac97_cm9761_linein_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
2103 | { | 2177 | { |
2104 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 2178 | unsigned short surr_vals[2][2] = { |
2105 | unsigned short vals[2][2] = { | ||
2106 | { 0x0008, 0x0400 }, /* off, on */ | 2179 | { 0x0008, 0x0400 }, /* off, on */ |
2107 | { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */ | 2180 | { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */ |
2108 | }; | 2181 | }; |
2109 | return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x0408, | 2182 | unsigned short clfe_vals[2][2] = { |
2110 | vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]); | 2183 | { 0x2000, 0x1880 }, /* off, on */ |
2184 | { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */ | ||
2185 | }; | ||
2186 | |||
2187 | /* shared Line-In */ | ||
2188 | snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x0408, | ||
2189 | surr_vals[ac97->spec.dev_flags][is_shared_linein(ac97)]); | ||
2190 | /* shared Mic */ | ||
2191 | snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3880, | ||
2192 | clfe_vals[ac97->spec.dev_flags][is_shared_micin(ac97)]); | ||
2193 | } | ||
2194 | |||
2195 | static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = { | ||
2196 | AC97_SURROUND_JACK_MODE_CTL, | ||
2197 | AC97_CHANNEL_MODE_CTL, | ||
2198 | }; | ||
2199 | |||
2200 | static int cm9761_spdif_out_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
2201 | { | ||
2202 | static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" }; | ||
2203 | |||
2204 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2205 | uinfo->count = 1; | ||
2206 | uinfo->value.enumerated.items = 3; | ||
2207 | if (uinfo->value.enumerated.item > 2) | ||
2208 | uinfo->value.enumerated.item = 2; | ||
2209 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
2210 | return 0; | ||
2111 | } | 2211 | } |
2112 | 2212 | ||
2113 | static int snd_ac97_cm9761_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 2213 | static int cm9761_spdif_out_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
2114 | { | 2214 | { |
2115 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 2215 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); |
2116 | if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000) | 2216 | |
2117 | ucontrol->value.integer.value[0] = 1; | 2217 | if (ac97->regs[AC97_CM9761_FUNC] & 0x1) |
2218 | ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */ | ||
2219 | else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2) | ||
2220 | ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */ | ||
2118 | else | 2221 | else |
2119 | ucontrol->value.integer.value[0] = 0; | 2222 | ucontrol->value.enumerated.item[0] = 0; /* AC-link */ |
2120 | if (ac97->spec.dev_flags) /* 9761-82 rev.B */ | ||
2121 | ucontrol->value.integer.value[0] = !ucontrol->value.integer.value[0]; | ||
2122 | return 0; | 2223 | return 0; |
2123 | } | 2224 | } |
2124 | 2225 | ||
2125 | static int snd_ac97_cm9761_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 2226 | static int cm9761_spdif_out_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
2126 | { | 2227 | { |
2127 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 2228 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); |
2128 | unsigned short vals[2][2] = { | 2229 | |
2129 | { 0x2000, 0x1880 }, /* off, on */ | 2230 | if (ucontrol->value.enumerated.item[0] == 2) |
2130 | { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */ | 2231 | return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1); |
2131 | }; | 2232 | snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0); |
2132 | return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3880, | 2233 | return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2, |
2133 | vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]); | 2234 | ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0); |
2134 | } | 2235 | } |
2135 | 2236 | ||
2136 | static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = { | 2237 | static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" }; |
2137 | { | 2238 | static const struct ac97_enum cm9761_dac_clock_enum = |
2138 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2239 | AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock); |
2139 | .name = "Line-In As Surround", | 2240 | |
2140 | .info = snd_ac97_info_volsw, | 2241 | static const snd_kcontrol_new_t snd_ac97_cm9761_controls_spdif[] = { |
2141 | .get = snd_ac97_cm9761_linein_rear_get, | 2242 | { /* BIT 1: SPDIFS */ |
2142 | .put = snd_ac97_cm9761_linein_rear_put, | 2243 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2143 | .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ | 2244 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", |
2144 | }, | 2245 | .info = cm9761_spdif_out_source_info, |
2145 | { | 2246 | .get = cm9761_spdif_out_source_get, |
2146 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2247 | .put = cm9761_spdif_out_source_put, |
2147 | .name = "Mic As Center/LFE", | ||
2148 | .info = snd_ac97_info_volsw, | ||
2149 | .get = snd_ac97_cm9761_center_mic_get, | ||
2150 | .put = snd_ac97_cm9761_center_mic_put, | ||
2151 | .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ | ||
2152 | }, | 2248 | }, |
2249 | /* BIT 2: IG_SPIV */ | ||
2250 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0), | ||
2251 | /* BIT 3: SPI2F */ | ||
2252 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0), | ||
2253 | /* BIT 4: SPI2SDI */ | ||
2254 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0), | ||
2255 | /* BIT 9-10: DAC_CTL */ | ||
2256 | AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum), | ||
2153 | }; | 2257 | }; |
2154 | 2258 | ||
2259 | static int patch_cm9761_post_spdif(ac97_t * ac97) | ||
2260 | { | ||
2261 | return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif)); | ||
2262 | } | ||
2263 | |||
2155 | static int patch_cm9761_specific(ac97_t * ac97) | 2264 | static int patch_cm9761_specific(ac97_t * ac97) |
2156 | { | 2265 | { |
2157 | return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls)); | 2266 | return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls)); |
@@ -2159,7 +2268,8 @@ static int patch_cm9761_specific(ac97_t * ac97) | |||
2159 | 2268 | ||
2160 | static struct snd_ac97_build_ops patch_cm9761_ops = { | 2269 | static struct snd_ac97_build_ops patch_cm9761_ops = { |
2161 | .build_specific = patch_cm9761_specific, | 2270 | .build_specific = patch_cm9761_specific, |
2162 | .build_post_spdif = patch_cm9739_post_spdif /* hope it's identical... */ | 2271 | .build_post_spdif = patch_cm9761_post_spdif, |
2272 | .update_jacks = cm9761_update_jacks | ||
2163 | }; | 2273 | }; |
2164 | 2274 | ||
2165 | int patch_cm9761(ac97_t *ac97) | 2275 | int patch_cm9761(ac97_t *ac97) |
@@ -2193,24 +2303,25 @@ int patch_cm9761(ac97_t *ac97) | |||
2193 | /* to be sure: we overwrite the ext status bits */ | 2303 | /* to be sure: we overwrite the ext status bits */ |
2194 | snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0); | 2304 | snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0); |
2195 | /* Don't set 0x0200 here. This results in the silent analog output */ | 2305 | /* Don't set 0x0200 here. This results in the silent analog output */ |
2196 | snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009); | 2306 | snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */ |
2197 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ | 2307 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ |
2198 | 2308 | ||
2199 | /* set-up multi channel */ | 2309 | /* set-up multi channel */ |
2200 | /* bit 15: pc master beep off | 2310 | /* bit 15: pc master beep off |
2201 | * bit 14: ?? | 2311 | * bit 14: pin47 = EAPD/SPDIF |
2202 | * bit 13: vref ctl [= cm9739] | 2312 | * bit 13: vref ctl [= cm9739] |
2203 | * bit 12: center/mic [= cm9739] (reverted on rev B) | 2313 | * bit 12: CLFE control (reverted on rev B) |
2204 | * bit 11: ?? (mic/center/lfe) (reverted on rev B) | 2314 | * bit 11: Mic/center share (reverted on rev B) |
2205 | * bit 10: suddound/line [= cm9739] | 2315 | * bit 10: suddound/line share |
2206 | * bit 9: mix 2 surround | 2316 | * bit 9: Analog-in mix -> surround |
2207 | * bit 8: ? | 2317 | * bit 8: Analog-in mix -> CLFE |
2208 | * bit 7: ?? (mic/center/lfe) | 2318 | * bit 7: Mic/LFE share (mic/center/lfe) |
2209 | * bit 4: ?? (front) | 2319 | * bit 5: vref select (9761A) |
2210 | * bit 3: ?? (line-in/rear share) (revereted with rev B) | 2320 | * bit 4: front control |
2211 | * bit 2: ?? (surround) | 2321 | * bit 3: surround control (revereted with rev B) |
2212 | * bit 1: front mic | 2322 | * bit 2: front mic |
2213 | * bit 0: mic boost | 2323 | * bit 1: stereo mic |
2324 | * bit 0: mic boost level (0=20dB, 1=30dB) | ||
2214 | */ | 2325 | */ |
2215 | 2326 | ||
2216 | #if 0 | 2327 | #if 0 |
@@ -2230,6 +2341,47 @@ int patch_cm9761(ac97_t *ac97) | |||
2230 | return 0; | 2341 | return 0; |
2231 | } | 2342 | } |
2232 | 2343 | ||
2344 | #define AC97_CM9780_SIDE 0x60 | ||
2345 | #define AC97_CM9780_JACK 0x62 | ||
2346 | #define AC97_CM9780_MIXER 0x64 | ||
2347 | #define AC97_CM9780_MULTI_CHAN 0x66 | ||
2348 | #define AC97_CM9780_SPDIF 0x6c | ||
2349 | |||
2350 | static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" }; | ||
2351 | static const struct ac97_enum cm9780_ch_select_enum = | ||
2352 | AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select); | ||
2353 | static const snd_kcontrol_new_t cm9780_controls[] = { | ||
2354 | AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1), | ||
2355 | AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0), | ||
2356 | AC97_ENUM("Side Playback Route", cm9780_ch_select_enum), | ||
2357 | }; | ||
2358 | |||
2359 | static int patch_cm9780_specific(ac97_t *ac97) | ||
2360 | { | ||
2361 | return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls)); | ||
2362 | } | ||
2363 | |||
2364 | static struct snd_ac97_build_ops patch_cm9780_ops = { | ||
2365 | .build_specific = patch_cm9780_specific, | ||
2366 | .build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */ | ||
2367 | }; | ||
2368 | |||
2369 | int patch_cm9780(ac97_t *ac97) | ||
2370 | { | ||
2371 | unsigned short val; | ||
2372 | |||
2373 | ac97->build_ops = &patch_cm9780_ops; | ||
2374 | |||
2375 | /* enable spdif */ | ||
2376 | if (ac97->ext_id & AC97_EI_SPDIF) { | ||
2377 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ | ||
2378 | val = snd_ac97_read(ac97, AC97_CM9780_SPDIF); | ||
2379 | val |= 0x1; /* SPDI_EN */ | ||
2380 | snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val); | ||
2381 | } | ||
2382 | |||
2383 | return 0; | ||
2384 | } | ||
2233 | 2385 | ||
2234 | /* | 2386 | /* |
2235 | * VIA VT1616 codec | 2387 | * VIA VT1616 codec |
@@ -2263,9 +2415,21 @@ int patch_vt1616(ac97_t * ac97) | |||
2263 | return 0; | 2415 | return 0; |
2264 | } | 2416 | } |
2265 | 2417 | ||
2418 | /* | ||
2419 | */ | ||
2420 | static void it2646_update_jacks(ac97_t *ac97) | ||
2421 | { | ||
2422 | /* shared Line-In */ | ||
2423 | snd_ac97_update_bits(ac97, 0x76, 1 << 9, | ||
2424 | is_shared_linein(ac97) ? (1<<9) : 0); | ||
2425 | /* shared Mic */ | ||
2426 | snd_ac97_update_bits(ac97, 0x76, 1 << 10, | ||
2427 | is_shared_micin(ac97) ? (1<<10) : 0); | ||
2428 | } | ||
2429 | |||
2266 | static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = { | 2430 | static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = { |
2267 | AC97_SINGLE("Line-In As Surround", 0x76, 9, 1, 0), | 2431 | AC97_SURROUND_JACK_MODE_CTL, |
2268 | AC97_SINGLE("Mic As Center/LFE", 0x76, 10, 1, 0), | 2432 | AC97_CHANNEL_MODE_CTL, |
2269 | }; | 2433 | }; |
2270 | 2434 | ||
2271 | static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = { | 2435 | static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = { |
@@ -2285,7 +2449,8 @@ static int patch_it2646_specific(ac97_t * ac97) | |||
2285 | } | 2449 | } |
2286 | 2450 | ||
2287 | static struct snd_ac97_build_ops patch_it2646_ops = { | 2451 | static struct snd_ac97_build_ops patch_it2646_ops = { |
2288 | .build_specific = patch_it2646_specific | 2452 | .build_specific = patch_it2646_specific, |
2453 | .update_jacks = it2646_update_jacks | ||
2289 | }; | 2454 | }; |
2290 | 2455 | ||
2291 | int patch_it2646(ac97_t * ac97) | 2456 | int patch_it2646(ac97_t * ac97) |
@@ -2297,12 +2462,29 @@ int patch_it2646(ac97_t * ac97) | |||
2297 | return 0; | 2462 | return 0; |
2298 | } | 2463 | } |
2299 | 2464 | ||
2300 | /* Si3036/8 specific registers */ | 2465 | /* |
2466 | * Si3036 codec | ||
2467 | */ | ||
2468 | |||
2301 | #define AC97_SI3036_CHIP_ID 0x5a | 2469 | #define AC97_SI3036_CHIP_ID 0x5a |
2470 | #define AC97_SI3036_LINE_CFG 0x5c | ||
2471 | |||
2472 | static const snd_kcontrol_new_t snd_ac97_controls_si3036[] = { | ||
2473 | AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1) | ||
2474 | }; | ||
2475 | |||
2476 | static int patch_si3036_specific(ac97_t * ac97) | ||
2477 | { | ||
2478 | return patch_build_controls(ac97, snd_ac97_controls_si3036, ARRAY_SIZE(snd_ac97_controls_si3036)); | ||
2479 | } | ||
2480 | |||
2481 | static struct snd_ac97_build_ops patch_si3036_ops = { | ||
2482 | .build_specific = patch_si3036_specific, | ||
2483 | }; | ||
2302 | 2484 | ||
2303 | int mpatch_si3036(ac97_t * ac97) | 2485 | int mpatch_si3036(ac97_t * ac97) |
2304 | { | 2486 | { |
2305 | //printk("mpatch_si3036: chip id = %x\n", snd_ac97_read(ac97, 0x5a)); | 2487 | ac97->build_ops = &patch_si3036_ops; |
2306 | snd_ac97_write_cache(ac97, 0x5c, 0xf210 ); | 2488 | snd_ac97_write_cache(ac97, 0x5c, 0xf210 ); |
2307 | snd_ac97_write_cache(ac97, 0x68, 0); | 2489 | snd_ac97_write_cache(ac97, 0x68, 0); |
2308 | return 0; | 2490 | return 0; |
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h index 6db51c96f5d0..7b7377d0f2ae 100644 --- a/sound/pci/ac97/ac97_patch.h +++ b/sound/pci/ac97/ac97_patch.h | |||
@@ -54,6 +54,7 @@ int patch_alc850(ac97_t * ac97); | |||
54 | int patch_cm9738(ac97_t * ac97); | 54 | int patch_cm9738(ac97_t * ac97); |
55 | int patch_cm9739(ac97_t * ac97); | 55 | int patch_cm9739(ac97_t * ac97); |
56 | int patch_cm9761(ac97_t * ac97); | 56 | int patch_cm9761(ac97_t * ac97); |
57 | int patch_cm9780(ac97_t * ac97); | ||
57 | int patch_vt1616(ac97_t * ac97); | 58 | int patch_vt1616(ac97_t * ac97); |
58 | int patch_it2646(ac97_t * ac97); | 59 | int patch_it2646(ac97_t * ac97); |
59 | int mpatch_si3036(ac97_t * ac97); | 60 | int mpatch_si3036(ac97_t * ac97); |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 984d5d4ba4e1..f08ae71f902d 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -98,6 +98,8 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O"); | |||
98 | #define ALI_LEF_CHANNEL 23 | 98 | #define ALI_LEF_CHANNEL 23 |
99 | #define ALI_SURR_LEFT_CHANNEL 26 | 99 | #define ALI_SURR_LEFT_CHANNEL 26 |
100 | #define ALI_SURR_RIGHT_CHANNEL 25 | 100 | #define ALI_SURR_RIGHT_CHANNEL 25 |
101 | #define ALI_MODEM_IN_CHANNEL 21 | ||
102 | #define ALI_MODEM_OUT_CHANNEL 20 | ||
101 | 103 | ||
102 | #define SNDRV_ALI_VOICE_TYPE_PCM 01 | 104 | #define SNDRV_ALI_VOICE_TYPE_PCM 01 |
103 | #define SNDRV_ALI_VOICE_TYPE_OTH 02 | 105 | #define SNDRV_ALI_VOICE_TYPE_OTH 02 |
@@ -122,7 +124,15 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O"); | |||
122 | 124 | ||
123 | #define ALI_SCTRL 0x48 | 125 | #define ALI_SCTRL 0x48 |
124 | #define ALI_SPDIF_OUT_ENABLE 0x20 | 126 | #define ALI_SPDIF_OUT_ENABLE 0x20 |
127 | #define ALI_SCTRL_LINE_IN2 (1 << 9) | ||
128 | #define ALI_SCTRL_GPIO_IN2 (1 << 13) | ||
129 | #define ALI_SCTRL_LINE_OUT_EN (1 << 20) | ||
130 | #define ALI_SCTRL_GPIO_OUT_EN (1 << 23) | ||
131 | #define ALI_SCTRL_CODEC1_READY (1 << 24) | ||
132 | #define ALI_SCTRL_CODEC2_READY (1 << 25) | ||
125 | #define ALI_AC97_GPIO 0x4c | 133 | #define ALI_AC97_GPIO 0x4c |
134 | #define ALI_AC97_GPIO_ENABLE 0x8000 | ||
135 | #define ALI_AC97_GPIO_DATA_SHIFT 16 | ||
126 | #define ALI_SPDIF_CS 0x70 | 136 | #define ALI_SPDIF_CS 0x70 |
127 | #define ALI_SPDIF_CTRL 0x74 | 137 | #define ALI_SPDIF_CTRL 0x74 |
128 | #define ALI_SPDIF_IN_FUNC_ENABLE 0x02 | 138 | #define ALI_SPDIF_IN_FUNC_ENABLE 0x02 |
@@ -143,6 +153,7 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O"); | |||
143 | #define TARGET_REACHED 0x00008000 | 153 | #define TARGET_REACHED 0x00008000 |
144 | #define MIXER_OVERFLOW 0x00000800 | 154 | #define MIXER_OVERFLOW 0x00000800 |
145 | #define MIXER_UNDERFLOW 0x00000400 | 155 | #define MIXER_UNDERFLOW 0x00000400 |
156 | #define GPIO_IRQ 0x01000000 | ||
146 | #define ALI_SBBL_SBCL 0xc0 | 157 | #define ALI_SBBL_SBCL 0xc0 |
147 | #define ALI_SBCTRL_SBE2R_SBDD 0xc4 | 158 | #define ALI_SBCTRL_SBE2R_SBDD 0xc4 |
148 | #define ALI_STIMER 0xc8 | 159 | #define ALI_STIMER 0xc8 |
@@ -162,6 +173,9 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O"); | |||
162 | 173 | ||
163 | #define ALI_REG(codec, x) ((codec)->port + x) | 174 | #define ALI_REG(codec, x) ((codec)->port + x) |
164 | 175 | ||
176 | #define MAX_CODECS 2 | ||
177 | |||
178 | |||
165 | typedef struct snd_stru_ali ali_t; | 179 | typedef struct snd_stru_ali ali_t; |
166 | typedef struct snd_ali_stru_voice snd_ali_voice_t; | 180 | typedef struct snd_ali_stru_voice snd_ali_voice_t; |
167 | 181 | ||
@@ -245,7 +259,7 @@ struct snd_stru_ali { | |||
245 | struct pci_dev *pci_m7101; | 259 | struct pci_dev *pci_m7101; |
246 | 260 | ||
247 | snd_card_t *card; | 261 | snd_card_t *card; |
248 | snd_pcm_t *pcm; | 262 | snd_pcm_t *pcm[MAX_CODECS]; |
249 | alidev_t synth; | 263 | alidev_t synth; |
250 | snd_ali_channel_control_t chregs; | 264 | snd_ali_channel_control_t chregs; |
251 | 265 | ||
@@ -255,8 +269,10 @@ struct snd_stru_ali { | |||
255 | unsigned int spurious_irq_count; | 269 | unsigned int spurious_irq_count; |
256 | unsigned int spurious_irq_max_delta; | 270 | unsigned int spurious_irq_max_delta; |
257 | 271 | ||
272 | unsigned int num_of_codecs; | ||
273 | |||
258 | ac97_bus_t *ac97_bus; | 274 | ac97_bus_t *ac97_bus; |
259 | ac97_t *ac97; | 275 | ac97_t *ac97[MAX_CODECS]; |
260 | unsigned short ac97_ext_id; | 276 | unsigned short ac97_ext_id; |
261 | unsigned short ac97_ext_status; | 277 | unsigned short ac97_ext_status; |
262 | 278 | ||
@@ -383,7 +399,7 @@ static int snd_ali_codec_ready( ali_t *codec, | |||
383 | unsigned long end_time; | 399 | unsigned long end_time; |
384 | unsigned int res; | 400 | unsigned int res; |
385 | 401 | ||
386 | end_time = jiffies + 10 * (HZ >> 2); | 402 | end_time = jiffies + 10 * msecs_to_jiffies(250); |
387 | do { | 403 | do { |
388 | res = snd_ali_5451_peek(codec,port); | 404 | res = snd_ali_5451_peek(codec,port); |
389 | if (! (res & 0x8000)) | 405 | if (! (res & 0x8000)) |
@@ -406,7 +422,7 @@ static int snd_ali_stimer_ready(ali_t *codec, int sched) | |||
406 | dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER); | 422 | dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER); |
407 | dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); | 423 | dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); |
408 | 424 | ||
409 | end_time = jiffies + 10 * (HZ >> 2); | 425 | end_time = jiffies + 10 * msecs_to_jiffies(250); |
410 | do { | 426 | do { |
411 | dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); | 427 | dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); |
412 | if (dwChk2 != dwChk1) | 428 | if (dwChk2 != dwChk1) |
@@ -489,7 +505,12 @@ static void snd_ali_codec_write(ac97_t *ac97, | |||
489 | ali_t *codec = ac97->private_data; | 505 | ali_t *codec = ac97->private_data; |
490 | 506 | ||
491 | snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val); | 507 | snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val); |
492 | snd_ali_codec_poke(codec, 0, reg, val); | 508 | if(reg == AC97_GPIO_STATUS) { |
509 | outl((val << ALI_AC97_GPIO_DATA_SHIFT)|ALI_AC97_GPIO_ENABLE, | ||
510 | ALI_REG(codec, ALI_AC97_GPIO)); | ||
511 | return; | ||
512 | } | ||
513 | snd_ali_codec_poke(codec, ac97->num, reg, val); | ||
493 | return ; | 514 | return ; |
494 | } | 515 | } |
495 | 516 | ||
@@ -499,7 +520,7 @@ static unsigned short snd_ali_codec_read(ac97_t *ac97, unsigned short reg) | |||
499 | ali_t *codec = ac97->private_data; | 520 | ali_t *codec = ac97->private_data; |
500 | 521 | ||
501 | snd_ali_printk("codec_read reg=%xh.\n", reg); | 522 | snd_ali_printk("codec_read reg=%xh.\n", reg); |
502 | return (snd_ali_codec_peek(codec, 0, reg)); | 523 | return (snd_ali_codec_peek(codec, ac97->num, reg)); |
503 | } | 524 | } |
504 | 525 | ||
505 | /* | 526 | /* |
@@ -1051,7 +1072,7 @@ static irqreturn_t snd_ali_card_interrupt(int irq, | |||
1051 | } | 1072 | } |
1052 | 1073 | ||
1053 | 1074 | ||
1054 | static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec) | 1075 | static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, int channel) |
1055 | { | 1076 | { |
1056 | snd_ali_voice_t *pvoice = NULL; | 1077 | snd_ali_voice_t *pvoice = NULL; |
1057 | unsigned long flags; | 1078 | unsigned long flags; |
@@ -1061,7 +1082,8 @@ static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec) | |||
1061 | 1082 | ||
1062 | spin_lock_irqsave(&codec->voice_alloc, flags); | 1083 | spin_lock_irqsave(&codec->voice_alloc, flags); |
1063 | if (type == SNDRV_ALI_VOICE_TYPE_PCM) { | 1084 | if (type == SNDRV_ALI_VOICE_TYPE_PCM) { |
1064 | idx = snd_ali_find_free_channel(codec,rec); | 1085 | idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) : |
1086 | snd_ali_find_free_channel(codec,rec); | ||
1065 | if(idx < 0) { | 1087 | if(idx < 0) { |
1066 | snd_printk("ali_alloc_voice: err.\n"); | 1088 | snd_printk("ali_alloc_voice: err.\n"); |
1067 | spin_unlock_irqrestore(&codec->voice_alloc, flags); | 1089 | spin_unlock_irqrestore(&codec->voice_alloc, flags); |
@@ -1297,7 +1319,7 @@ static int snd_ali_playback_hw_params(snd_pcm_substream_t * substream, | |||
1297 | 1319 | ||
1298 | if (params_buffer_size(hw_params)/2 != params_period_size(hw_params)) { | 1320 | if (params_buffer_size(hw_params)/2 != params_period_size(hw_params)) { |
1299 | if (evoice == NULL) { | 1321 | if (evoice == NULL) { |
1300 | evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0); | 1322 | evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0, -1); |
1301 | if (evoice == NULL) | 1323 | if (evoice == NULL) |
1302 | return -ENOMEM; | 1324 | return -ENOMEM; |
1303 | pvoice->extra = evoice; | 1325 | pvoice->extra = evoice; |
@@ -1328,13 +1350,13 @@ static int snd_ali_playback_hw_free(snd_pcm_substream_t * substream) | |||
1328 | return 0; | 1350 | return 0; |
1329 | } | 1351 | } |
1330 | 1352 | ||
1331 | static int snd_ali_capture_hw_params(snd_pcm_substream_t * substream, | 1353 | static int snd_ali_hw_params(snd_pcm_substream_t * substream, |
1332 | snd_pcm_hw_params_t * hw_params) | 1354 | snd_pcm_hw_params_t * hw_params) |
1333 | { | 1355 | { |
1334 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 1356 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); |
1335 | } | 1357 | } |
1336 | 1358 | ||
1337 | static int snd_ali_capture_hw_free(snd_pcm_substream_t * substream) | 1359 | static int snd_ali_hw_free(snd_pcm_substream_t * substream) |
1338 | { | 1360 | { |
1339 | return snd_pcm_lib_free_pages(substream); | 1361 | return snd_pcm_lib_free_pages(substream); |
1340 | } | 1362 | } |
@@ -1428,7 +1450,7 @@ static int snd_ali_playback_prepare(snd_pcm_substream_t * substream) | |||
1428 | } | 1450 | } |
1429 | 1451 | ||
1430 | 1452 | ||
1431 | static int snd_ali_capture_prepare(snd_pcm_substream_t * substream) | 1453 | static int snd_ali_prepare(snd_pcm_substream_t * substream) |
1432 | { | 1454 | { |
1433 | ali_t *codec = snd_pcm_substream_chip(substream); | 1455 | ali_t *codec = snd_pcm_substream_chip(substream); |
1434 | snd_pcm_runtime_t *runtime = substream->runtime; | 1456 | snd_pcm_runtime_t *runtime = substream->runtime; |
@@ -1446,11 +1468,13 @@ static int snd_ali_capture_prepare(snd_pcm_substream_t * substream) | |||
1446 | 1468 | ||
1447 | spin_lock_irqsave(&codec->reg_lock, flags); | 1469 | spin_lock_irqsave(&codec->reg_lock, flags); |
1448 | 1470 | ||
1449 | snd_ali_printk("capture_prepare...\n"); | 1471 | snd_ali_printk("ali_prepare...\n"); |
1450 | 1472 | ||
1451 | snd_ali_enable_special_channel(codec,pvoice->number); | 1473 | snd_ali_enable_special_channel(codec,pvoice->number); |
1452 | 1474 | ||
1453 | Delta = snd_ali_convert_rate(runtime->rate, 1); | 1475 | Delta = (pvoice->number == ALI_MODEM_IN_CHANNEL || |
1476 | pvoice->number == ALI_MODEM_OUT_CHANNEL) ? | ||
1477 | 0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode); | ||
1454 | 1478 | ||
1455 | // Prepare capture intr channel | 1479 | // Prepare capture intr channel |
1456 | if (pvoice->number == ALI_SPDIF_IN_CHANNEL) { | 1480 | if (pvoice->number == ALI_SPDIF_IN_CHANNEL) { |
@@ -1534,7 +1558,7 @@ static snd_pcm_uframes_t snd_ali_playback_pointer(snd_pcm_substream_t *substream | |||
1534 | } | 1558 | } |
1535 | 1559 | ||
1536 | 1560 | ||
1537 | static snd_pcm_uframes_t snd_ali_capture_pointer(snd_pcm_substream_t *substream) | 1561 | static snd_pcm_uframes_t snd_ali_pointer(snd_pcm_substream_t *substream) |
1538 | { | 1562 | { |
1539 | ali_t *codec = snd_pcm_substream_chip(substream); | 1563 | ali_t *codec = snd_pcm_substream_chip(substream); |
1540 | snd_pcm_runtime_t *runtime = substream->runtime; | 1564 | snd_pcm_runtime_t *runtime = substream->runtime; |
@@ -1616,7 +1640,8 @@ static void snd_ali_pcm_free_substream(snd_pcm_runtime_t *runtime) | |||
1616 | } | 1640 | } |
1617 | } | 1641 | } |
1618 | 1642 | ||
1619 | static int snd_ali_playback_open(snd_pcm_substream_t * substream) | 1643 | static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel, |
1644 | snd_pcm_hardware_t *phw) | ||
1620 | { | 1645 | { |
1621 | ali_t *codec = snd_pcm_substream_chip(substream); | 1646 | ali_t *codec = snd_pcm_substream_chip(substream); |
1622 | snd_pcm_runtime_t *runtime = substream->runtime; | 1647 | snd_pcm_runtime_t *runtime = substream->runtime; |
@@ -1624,7 +1649,7 @@ static int snd_ali_playback_open(snd_pcm_substream_t * substream) | |||
1624 | unsigned long flags = 0; | 1649 | unsigned long flags = 0; |
1625 | 1650 | ||
1626 | spin_lock_irqsave(&codec->reg_lock, flags); | 1651 | spin_lock_irqsave(&codec->reg_lock, flags); |
1627 | pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0); | 1652 | pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel); |
1628 | if (pvoice == NULL) { | 1653 | if (pvoice == NULL) { |
1629 | spin_unlock_irqrestore(&codec->reg_lock, flags); | 1654 | spin_unlock_irqrestore(&codec->reg_lock, flags); |
1630 | return -EAGAIN; | 1655 | return -EAGAIN; |
@@ -1636,49 +1661,31 @@ static int snd_ali_playback_open(snd_pcm_substream_t * substream) | |||
1636 | runtime->private_data = pvoice; | 1661 | runtime->private_data = pvoice; |
1637 | runtime->private_free = snd_ali_pcm_free_substream; | 1662 | runtime->private_free = snd_ali_pcm_free_substream; |
1638 | 1663 | ||
1639 | runtime->hw = snd_ali_playback; | 1664 | runtime->hw = *phw; |
1640 | snd_pcm_set_sync(substream); | 1665 | snd_pcm_set_sync(substream); |
1641 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024); | 1666 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024); |
1642 | return 0; | 1667 | return 0; |
1643 | } | 1668 | } |
1644 | 1669 | ||
1670 | static int snd_ali_playback_open(snd_pcm_substream_t * substream) | ||
1671 | { | ||
1672 | return snd_ali_open(substream, 0, -1, &snd_ali_playback); | ||
1673 | } | ||
1645 | 1674 | ||
1646 | static int snd_ali_capture_open(snd_pcm_substream_t * substream) | 1675 | static int snd_ali_capture_open(snd_pcm_substream_t * substream) |
1647 | { | 1676 | { |
1648 | ali_t *codec = snd_pcm_substream_chip(substream); | 1677 | return snd_ali_open(substream, 1, -1, &snd_ali_capture); |
1649 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
1650 | snd_ali_voice_t *pvoice; | ||
1651 | unsigned long flags; | ||
1652 | |||
1653 | spin_lock_irqsave(&codec->reg_lock, flags); | ||
1654 | pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 1); | ||
1655 | if (pvoice == NULL) { | ||
1656 | spin_unlock_irqrestore(&codec->reg_lock, flags); | ||
1657 | return -EAGAIN; | ||
1658 | } | ||
1659 | pvoice->codec = codec; | ||
1660 | spin_unlock_irqrestore(&codec->reg_lock, flags); | ||
1661 | |||
1662 | pvoice->substream = substream; | ||
1663 | runtime->private_data = pvoice; | ||
1664 | runtime->private_free = snd_ali_pcm_free_substream; | ||
1665 | runtime->hw = snd_ali_capture; | ||
1666 | snd_pcm_set_sync(substream); | ||
1667 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024); | ||
1668 | return 0; | ||
1669 | } | 1678 | } |
1670 | 1679 | ||
1671 | |||
1672 | static int snd_ali_playback_close(snd_pcm_substream_t * substream) | 1680 | static int snd_ali_playback_close(snd_pcm_substream_t * substream) |
1673 | { | 1681 | { |
1674 | return 0; | 1682 | return 0; |
1675 | } | 1683 | } |
1676 | 1684 | ||
1677 | static int snd_ali_capture_close(snd_pcm_substream_t * substream) | 1685 | static int snd_ali_close(snd_pcm_substream_t * substream) |
1678 | { | 1686 | { |
1679 | ali_t *codec = snd_pcm_substream_chip(substream); | 1687 | ali_t *codec = snd_pcm_substream_chip(substream); |
1680 | snd_pcm_runtime_t *runtime = substream->runtime; | 1688 | snd_ali_voice_t *pvoice = (snd_ali_voice_t *) substream->runtime->private_data; |
1681 | snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data; | ||
1682 | 1689 | ||
1683 | snd_ali_disable_special_channel(codec,pvoice->number); | 1690 | snd_ali_disable_special_channel(codec,pvoice->number); |
1684 | 1691 | ||
@@ -1698,29 +1705,121 @@ static snd_pcm_ops_t snd_ali_playback_ops = { | |||
1698 | 1705 | ||
1699 | static snd_pcm_ops_t snd_ali_capture_ops = { | 1706 | static snd_pcm_ops_t snd_ali_capture_ops = { |
1700 | .open = snd_ali_capture_open, | 1707 | .open = snd_ali_capture_open, |
1701 | .close = snd_ali_capture_close, | 1708 | .close = snd_ali_close, |
1702 | .ioctl = snd_ali_ioctl, | 1709 | .ioctl = snd_ali_ioctl, |
1703 | .hw_params = snd_ali_capture_hw_params, | 1710 | .hw_params = snd_ali_hw_params, |
1704 | .hw_free = snd_ali_capture_hw_free, | 1711 | .hw_free = snd_ali_hw_free, |
1705 | .prepare = snd_ali_capture_prepare, | 1712 | .prepare = snd_ali_prepare, |
1713 | .trigger = snd_ali_trigger, | ||
1714 | .pointer = snd_ali_pointer, | ||
1715 | }; | ||
1716 | |||
1717 | /* | ||
1718 | * Modem PCM | ||
1719 | */ | ||
1720 | |||
1721 | static int snd_ali_modem_hw_params(snd_pcm_substream_t * substream, | ||
1722 | snd_pcm_hw_params_t * hw_params) | ||
1723 | { | ||
1724 | ali_t *chip = snd_pcm_substream_chip(substream); | ||
1725 | unsigned int modem_num = chip->num_of_codecs - 1; | ||
1726 | snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, params_rate(hw_params)); | ||
1727 | snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0); | ||
1728 | return snd_ali_hw_params(substream, hw_params); | ||
1729 | } | ||
1730 | |||
1731 | static snd_pcm_hardware_t snd_ali_modem = | ||
1732 | { | ||
1733 | .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | | ||
1734 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
1735 | SNDRV_PCM_INFO_MMAP_VALID | | ||
1736 | SNDRV_PCM_INFO_RESUME | | ||
1737 | SNDRV_PCM_INFO_SYNC_START), | ||
1738 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
1739 | .rates = SNDRV_PCM_RATE_KNOT|SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000, | ||
1740 | .rate_min = 8000, | ||
1741 | .rate_max = 16000, | ||
1742 | .channels_min = 1, | ||
1743 | .channels_max = 1, | ||
1744 | .buffer_bytes_max = (256*1024), | ||
1745 | .period_bytes_min = 64, | ||
1746 | .period_bytes_max = (256*1024), | ||
1747 | .periods_min = 1, | ||
1748 | .periods_max = 1024, | ||
1749 | .fifo_size = 0, | ||
1750 | }; | ||
1751 | |||
1752 | static int snd_ali_modem_open(snd_pcm_substream_t * substream, int rec, int channel) | ||
1753 | { | ||
1754 | static unsigned int rates [] = {8000,9600,12000,16000}; | ||
1755 | static snd_pcm_hw_constraint_list_t hw_constraint_rates = { | ||
1756 | .count = ARRAY_SIZE(rates), | ||
1757 | .list = rates, | ||
1758 | .mask = 0, | ||
1759 | }; | ||
1760 | int err = snd_ali_open(substream, rec, channel, &snd_ali_modem); | ||
1761 | if (err) | ||
1762 | return err; | ||
1763 | return snd_pcm_hw_constraint_list(substream->runtime, 0, | ||
1764 | SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates); | ||
1765 | } | ||
1766 | |||
1767 | static int snd_ali_modem_playback_open(snd_pcm_substream_t * substream) | ||
1768 | { | ||
1769 | return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL); | ||
1770 | } | ||
1771 | |||
1772 | static int snd_ali_modem_capture_open(snd_pcm_substream_t * substream) | ||
1773 | { | ||
1774 | return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL); | ||
1775 | } | ||
1776 | |||
1777 | static snd_pcm_ops_t snd_ali_modem_playback_ops = { | ||
1778 | .open = snd_ali_modem_playback_open, | ||
1779 | .close = snd_ali_close, | ||
1780 | .ioctl = snd_pcm_lib_ioctl, | ||
1781 | .hw_params = snd_ali_modem_hw_params, | ||
1782 | .hw_free = snd_ali_hw_free, | ||
1783 | .prepare = snd_ali_prepare, | ||
1784 | .trigger = snd_ali_trigger, | ||
1785 | .pointer = snd_ali_pointer, | ||
1786 | }; | ||
1787 | |||
1788 | static snd_pcm_ops_t snd_ali_modem_capture_ops = { | ||
1789 | .open = snd_ali_modem_capture_open, | ||
1790 | .close = snd_ali_close, | ||
1791 | .ioctl = snd_pcm_lib_ioctl, | ||
1792 | .hw_params = snd_ali_modem_hw_params, | ||
1793 | .hw_free = snd_ali_hw_free, | ||
1794 | .prepare = snd_ali_prepare, | ||
1706 | .trigger = snd_ali_trigger, | 1795 | .trigger = snd_ali_trigger, |
1707 | .pointer = snd_ali_capture_pointer, | 1796 | .pointer = snd_ali_pointer, |
1797 | }; | ||
1798 | |||
1799 | |||
1800 | struct ali_pcm_description { | ||
1801 | char *name; | ||
1802 | unsigned int playback_num; | ||
1803 | unsigned int capture_num; | ||
1804 | snd_pcm_ops_t *playback_ops; | ||
1805 | snd_pcm_ops_t *capture_ops; | ||
1708 | }; | 1806 | }; |
1709 | 1807 | ||
1710 | 1808 | ||
1711 | static void snd_ali_pcm_free(snd_pcm_t *pcm) | 1809 | static void snd_ali_pcm_free(snd_pcm_t *pcm) |
1712 | { | 1810 | { |
1713 | ali_t *codec = pcm->private_data; | 1811 | ali_t *codec = pcm->private_data; |
1714 | codec->pcm = NULL; | 1812 | codec->pcm[pcm->device] = NULL; |
1715 | } | 1813 | } |
1716 | 1814 | ||
1717 | static int __devinit snd_ali_pcm(ali_t * codec, int device, snd_pcm_t ** rpcm) | 1815 | |
1816 | static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_description *desc) | ||
1718 | { | 1817 | { |
1719 | snd_pcm_t *pcm; | 1818 | snd_pcm_t *pcm; |
1720 | int err; | 1819 | int err; |
1721 | 1820 | ||
1722 | if (rpcm) *rpcm = NULL; | 1821 | err = snd_pcm_new(codec->card, desc->name, device, |
1723 | err = snd_pcm_new(codec->card, "ALI 5451", device, ALI_CHANNELS, 1, &pcm); | 1822 | desc->playback_num, desc->capture_num, &pcm); |
1724 | if (err < 0) { | 1823 | if (err < 0) { |
1725 | snd_printk("snd_ali_pcm: err called snd_pcm_new.\n"); | 1824 | snd_printk("snd_ali_pcm: err called snd_pcm_new.\n"); |
1726 | return err; | 1825 | return err; |
@@ -1728,20 +1827,36 @@ static int __devinit snd_ali_pcm(ali_t * codec, int device, snd_pcm_t ** rpcm) | |||
1728 | pcm->private_data = codec; | 1827 | pcm->private_data = codec; |
1729 | pcm->private_free = snd_ali_pcm_free; | 1828 | pcm->private_free = snd_ali_pcm_free; |
1730 | pcm->info_flags = 0; | 1829 | pcm->info_flags = 0; |
1731 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ali_playback_ops); | 1830 | if (desc->playback_ops) |
1732 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ali_capture_ops); | 1831 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, desc->playback_ops); |
1832 | if (desc->capture_ops) | ||
1833 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, desc->capture_ops); | ||
1733 | 1834 | ||
1734 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1835 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1735 | snd_dma_pci_data(codec->pci), 64*1024, 128*1024); | 1836 | snd_dma_pci_data(codec->pci), 64*1024, 128*1024); |
1736 | 1837 | ||
1737 | pcm->info_flags = 0; | 1838 | pcm->info_flags = 0; |
1738 | pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; | 1839 | pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; |
1739 | strcpy(pcm->name, "ALI 5451"); | 1840 | strcpy(pcm->name, desc->name); |
1740 | codec->pcm = pcm; | 1841 | codec->pcm[0] = pcm; |
1741 | if (rpcm) *rpcm = pcm; | ||
1742 | return 0; | 1842 | return 0; |
1743 | } | 1843 | } |
1744 | 1844 | ||
1845 | struct ali_pcm_description ali_pcms[] = { | ||
1846 | { "ALI 5451", ALI_CHANNELS, 1, &snd_ali_playback_ops, &snd_ali_capture_ops }, | ||
1847 | { "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops } | ||
1848 | }; | ||
1849 | |||
1850 | static int __devinit snd_ali_build_pcms(ali_t *codec) | ||
1851 | { | ||
1852 | int i, err; | ||
1853 | for(i = 0 ; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms) ; i++) | ||
1854 | if((err = snd_ali_pcm(codec, i, &ali_pcms[i])) < 0) | ||
1855 | return err; | ||
1856 | return 0; | ||
1857 | } | ||
1858 | |||
1859 | |||
1745 | #define ALI5451_SPDIF(xname, xindex, value) \ | 1860 | #define ALI5451_SPDIF(xname, xindex, value) \ |
1746 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ | 1861 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\ |
1747 | .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \ | 1862 | .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \ |
@@ -1860,14 +1975,14 @@ static void snd_ali_mixer_free_ac97_bus(ac97_bus_t *bus) | |||
1860 | static void snd_ali_mixer_free_ac97(ac97_t *ac97) | 1975 | static void snd_ali_mixer_free_ac97(ac97_t *ac97) |
1861 | { | 1976 | { |
1862 | ali_t *codec = ac97->private_data; | 1977 | ali_t *codec = ac97->private_data; |
1863 | codec->ac97 = NULL; | 1978 | codec->ac97[ac97->num] = NULL; |
1864 | } | 1979 | } |
1865 | 1980 | ||
1866 | static int __devinit snd_ali_mixer(ali_t * codec) | 1981 | static int __devinit snd_ali_mixer(ali_t * codec) |
1867 | { | 1982 | { |
1868 | ac97_template_t ac97; | 1983 | ac97_template_t ac97; |
1869 | unsigned int idx; | 1984 | unsigned int idx; |
1870 | int err; | 1985 | int i, err; |
1871 | static ac97_bus_ops_t ops = { | 1986 | static ac97_bus_ops_t ops = { |
1872 | .write = snd_ali_codec_write, | 1987 | .write = snd_ali_codec_write, |
1873 | .read = snd_ali_codec_read, | 1988 | .read = snd_ali_codec_read, |
@@ -1880,10 +1995,16 @@ static int __devinit snd_ali_mixer(ali_t * codec) | |||
1880 | memset(&ac97, 0, sizeof(ac97)); | 1995 | memset(&ac97, 0, sizeof(ac97)); |
1881 | ac97.private_data = codec; | 1996 | ac97.private_data = codec; |
1882 | ac97.private_free = snd_ali_mixer_free_ac97; | 1997 | ac97.private_free = snd_ali_mixer_free_ac97; |
1883 | if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97)) < 0) { | 1998 | |
1884 | snd_printk("ali mixer creating error.\n"); | 1999 | for ( i = 0 ; i < codec->num_of_codecs ; i++) { |
2000 | ac97.num = i; | ||
2001 | if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i])) < 0) { | ||
2002 | snd_printk("ali mixer %d creating error.\n", i); | ||
2003 | if(i == 0) | ||
1885 | return err; | 2004 | return err; |
1886 | } | 2005 | } |
2006 | } | ||
2007 | |||
1887 | if (codec->spdif_support) { | 2008 | if (codec->spdif_support) { |
1888 | for(idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) { | 2009 | for(idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) { |
1889 | err=snd_ctl_add(codec->card, snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec)); | 2010 | err=snd_ctl_add(codec->card, snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec)); |
@@ -1904,8 +2025,12 @@ static int ali_suspend(snd_card_t *card, pm_message_t state) | |||
1904 | if (! im) | 2025 | if (! im) |
1905 | return 0; | 2026 | return 0; |
1906 | 2027 | ||
1907 | snd_pcm_suspend_all(chip->pcm); | 2028 | for(i = 0 ; i < chip->num_of_codecs ; i++) { |
1908 | snd_ac97_suspend(chip->ac97); | 2029 | if (chip->pcm[i]) |
2030 | snd_pcm_suspend_all(chip->pcm[i]); | ||
2031 | if(chip->ac97[i]) | ||
2032 | snd_ac97_suspend(chip->ac97[i]); | ||
2033 | } | ||
1909 | 2034 | ||
1910 | spin_lock_irq(&chip->reg_lock); | 2035 | spin_lock_irq(&chip->reg_lock); |
1911 | 2036 | ||
@@ -1969,7 +2094,9 @@ static int ali_resume(snd_card_t *card) | |||
1969 | 2094 | ||
1970 | spin_unlock_irq(&chip->reg_lock); | 2095 | spin_unlock_irq(&chip->reg_lock); |
1971 | 2096 | ||
1972 | snd_ac97_resume(chip->ac97); | 2097 | for(i = 0 ; i < chip->num_of_codecs ; i++) |
2098 | if(chip->ac97[i]) | ||
2099 | snd_ac97_resume(chip->ac97[i]); | ||
1973 | 2100 | ||
1974 | return 0; | 2101 | return 0; |
1975 | } | 2102 | } |
@@ -2036,11 +2163,37 @@ static int snd_ali_chip_init(ali_t *codec) | |||
2036 | codec->spdif_mask = 0x00000002; | 2163 | codec->spdif_mask = 0x00000002; |
2037 | } | 2164 | } |
2038 | 2165 | ||
2166 | codec->num_of_codecs = 1; | ||
2167 | |||
2168 | /* secondary codec - modem */ | ||
2169 | if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) { | ||
2170 | codec->num_of_codecs++; | ||
2171 | outl(inl(ALI_REG(codec, ALI_SCTRL)) | | ||
2172 | (ALI_SCTRL_LINE_IN2|ALI_SCTRL_GPIO_IN2|ALI_SCTRL_LINE_OUT_EN), | ||
2173 | ALI_REG(codec, ALI_SCTRL)); | ||
2174 | } | ||
2175 | |||
2039 | snd_ali_printk("chip initialize succeed.\n"); | 2176 | snd_ali_printk("chip initialize succeed.\n"); |
2040 | return 0; | 2177 | return 0; |
2041 | 2178 | ||
2042 | } | 2179 | } |
2043 | 2180 | ||
2181 | /* proc for register dump */ | ||
2182 | static void snd_ali_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buf) | ||
2183 | { | ||
2184 | ali_t *codec = entry->private_data; | ||
2185 | int i; | ||
2186 | for(i = 0 ; i < 256 ; i+= 4) | ||
2187 | snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i))); | ||
2188 | } | ||
2189 | |||
2190 | static void __devinit snd_ali_proc_init(ali_t *codec) | ||
2191 | { | ||
2192 | snd_info_entry_t *entry; | ||
2193 | if(!snd_card_proc_new(codec->card, "ali5451", &entry)) | ||
2194 | snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read); | ||
2195 | } | ||
2196 | |||
2044 | static int __devinit snd_ali_resources(ali_t *codec) | 2197 | static int __devinit snd_ali_resources(ali_t *codec) |
2045 | { | 2198 | { |
2046 | int err; | 2199 | int err; |
@@ -2233,11 +2386,13 @@ static int __devinit snd_ali_probe(struct pci_dev *pci, | |||
2233 | } | 2386 | } |
2234 | 2387 | ||
2235 | snd_ali_printk("pcm building ...\n"); | 2388 | snd_ali_printk("pcm building ...\n"); |
2236 | if ((err = snd_ali_pcm(codec, 0, NULL)) < 0) { | 2389 | if ((err = snd_ali_build_pcms(codec)) < 0) { |
2237 | snd_card_free(card); | 2390 | snd_card_free(card); |
2238 | return err; | 2391 | return err; |
2239 | } | 2392 | } |
2240 | 2393 | ||
2394 | snd_ali_proc_init(codec); | ||
2395 | |||
2241 | strcpy(card->driver, "ALI5451"); | 2396 | strcpy(card->driver, "ALI5451"); |
2242 | strcpy(card->shortname, "ALI 5451"); | 2397 | strcpy(card->shortname, "ALI 5451"); |
2243 | 2398 | ||
@@ -2270,7 +2425,7 @@ static struct pci_driver driver = { | |||
2270 | 2425 | ||
2271 | static int __init alsa_card_ali_init(void) | 2426 | static int __init alsa_card_ali_init(void) |
2272 | { | 2427 | { |
2273 | return pci_module_init(&driver); | 2428 | return pci_register_driver(&driver); |
2274 | } | 2429 | } |
2275 | 2430 | ||
2276 | static void __exit alsa_card_ali_exit(void) | 2431 | static void __exit alsa_card_ali_exit(void) |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index f1a5f5723ee6..ca28b229c704 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -367,7 +367,7 @@ static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs * | |||
367 | if ((gcr_status & 0x40) && (chip->capture_substream)) /* capturing */ | 367 | if ((gcr_status & 0x40) && (chip->capture_substream)) /* capturing */ |
368 | snd_pcm_period_elapsed(chip->capture_substream); | 368 | snd_pcm_period_elapsed(chip->capture_substream); |
369 | if ((gcr_status & 0x10) && (chip->rmidi)) /* MPU401 interrupt */ | 369 | if ((gcr_status & 0x10) && (chip->rmidi)) /* MPU401 interrupt */ |
370 | snd_mpu401_uart_interrupt(irq, chip->rmidi, regs); | 370 | snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); |
371 | /* release the gcr */ | 371 | /* release the gcr */ |
372 | outb(gcr_status, chip->alt_port + 0xe); | 372 | outb(gcr_status, chip->alt_port + 0xe); |
373 | 373 | ||
@@ -777,7 +777,7 @@ static struct pci_driver driver = { | |||
777 | 777 | ||
778 | static int __init alsa_card_als4000_init(void) | 778 | static int __init alsa_card_als4000_init(void) |
779 | { | 779 | { |
780 | return pci_module_init(&driver); | 780 | return pci_register_driver(&driver); |
781 | } | 781 | } |
782 | 782 | ||
783 | static void __exit alsa_card_als4000_exit(void) | 783 | static void __exit alsa_card_als4000_exit(void) |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 6b04c0acc6f7..cafab4af5c57 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -1334,8 +1334,8 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *r | |||
1334 | 1334 | ||
1335 | static struct ac97_quirk ac97_quirks[] __devinitdata = { | 1335 | static struct ac97_quirk ac97_quirks[] __devinitdata = { |
1336 | { | 1336 | { |
1337 | .vendor = 0x103c, | 1337 | .subvendor = 0x103c, |
1338 | .device = 0x006b, | 1338 | .subdevice = 0x006b, |
1339 | .name = "HP Pavilion ZV5030US", | 1339 | .name = "HP Pavilion ZV5030US", |
1340 | .type = AC97_TUNE_MUTE_LED | 1340 | .type = AC97_TUNE_MUTE_LED |
1341 | }, | 1341 | }, |
@@ -1645,7 +1645,7 @@ static struct pci_driver driver = { | |||
1645 | 1645 | ||
1646 | static int __init alsa_card_atiixp_init(void) | 1646 | static int __init alsa_card_atiixp_init(void) |
1647 | { | 1647 | { |
1648 | return pci_module_init(&driver); | 1648 | return pci_register_driver(&driver); |
1649 | } | 1649 | } |
1650 | 1650 | ||
1651 | static void __exit alsa_card_atiixp_exit(void) | 1651 | static void __exit alsa_card_atiixp_exit(void) |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index fb7cecea846d..8d2002951bd7 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -265,6 +265,7 @@ struct snd_atiixp { | |||
265 | */ | 265 | */ |
266 | static struct pci_device_id snd_atiixp_ids[] = { | 266 | static struct pci_device_id snd_atiixp_ids[] = { |
267 | { 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */ | 267 | { 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */ |
268 | { 0x1002, 0x4378, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */ | ||
268 | { 0, } | 269 | { 0, } |
269 | }; | 270 | }; |
270 | 271 | ||
@@ -463,6 +464,11 @@ static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg) | |||
463 | static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) | 464 | static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) |
464 | { | 465 | { |
465 | atiixp_t *chip = ac97->private_data; | 466 | atiixp_t *chip = ac97->private_data; |
467 | if (reg == AC97_GPIO_STATUS) { | ||
468 | atiixp_write(chip, MODEM_OUT_GPIO, | ||
469 | (val << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN); | ||
470 | return; | ||
471 | } | ||
466 | snd_atiixp_codec_write(chip, ac97->num, reg, val); | 472 | snd_atiixp_codec_write(chip, ac97->num, reg, val); |
467 | } | 473 | } |
468 | 474 | ||
@@ -663,44 +669,33 @@ static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | |||
663 | { | 669 | { |
664 | atiixp_t *chip = snd_pcm_substream_chip(substream); | 670 | atiixp_t *chip = snd_pcm_substream_chip(substream); |
665 | atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data; | 671 | atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data; |
666 | unsigned int reg = 0; | 672 | int err = 0; |
667 | int i; | ||
668 | 673 | ||
669 | snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL); | 674 | snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL); |
670 | 675 | ||
671 | if (cmd != SNDRV_PCM_TRIGGER_START && cmd != SNDRV_PCM_TRIGGER_STOP) | ||
672 | return -EINVAL; | ||
673 | |||
674 | spin_lock(&chip->reg_lock); | 676 | spin_lock(&chip->reg_lock); |
675 | 677 | switch(cmd) { | |
676 | /* hook off/on: via GPIO_OUT */ | 678 | case SNDRV_PCM_TRIGGER_START: |
677 | for (i = 0; i < NUM_ATI_CODECS; i++) { | ||
678 | if (chip->ac97[i]) { | ||
679 | reg = snd_ac97_read(chip->ac97[i], AC97_GPIO_STATUS); | ||
680 | break; | ||
681 | } | ||
682 | } | ||
683 | if(cmd == SNDRV_PCM_TRIGGER_START) | ||
684 | reg |= AC97_GPIO_LINE1_OH; | ||
685 | else | ||
686 | reg &= ~AC97_GPIO_LINE1_OH; | ||
687 | reg = (reg << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN ; | ||
688 | atiixp_write(chip, MODEM_OUT_GPIO, reg); | ||
689 | |||
690 | if (cmd == SNDRV_PCM_TRIGGER_START) { | ||
691 | dma->ops->enable_transfer(chip, 1); | 679 | dma->ops->enable_transfer(chip, 1); |
692 | dma->running = 1; | 680 | dma->running = 1; |
693 | } else { | 681 | break; |
682 | case SNDRV_PCM_TRIGGER_STOP: | ||
694 | dma->ops->enable_transfer(chip, 0); | 683 | dma->ops->enable_transfer(chip, 0); |
695 | dma->running = 0; | 684 | dma->running = 0; |
685 | break; | ||
686 | default: | ||
687 | err = -EINVAL; | ||
688 | break; | ||
696 | } | 689 | } |
690 | if (! err) { | ||
697 | snd_atiixp_check_bus_busy(chip); | 691 | snd_atiixp_check_bus_busy(chip); |
698 | if (cmd == SNDRV_PCM_TRIGGER_STOP) { | 692 | if (cmd == SNDRV_PCM_TRIGGER_STOP) { |
699 | dma->ops->flush_dma(chip); | 693 | dma->ops->flush_dma(chip); |
700 | snd_atiixp_check_bus_busy(chip); | 694 | snd_atiixp_check_bus_busy(chip); |
701 | } | 695 | } |
696 | } | ||
702 | spin_unlock(&chip->reg_lock); | 697 | spin_unlock(&chip->reg_lock); |
703 | return 0; | 698 | return err; |
704 | } | 699 | } |
705 | 700 | ||
706 | 701 | ||
@@ -1332,7 +1327,7 @@ static struct pci_driver driver = { | |||
1332 | 1327 | ||
1333 | static int __init alsa_card_atiixp_init(void) | 1328 | static int __init alsa_card_atiixp_init(void) |
1334 | { | 1329 | { |
1335 | return pci_module_init(&driver); | 1330 | return pci_register_driver(&driver); |
1336 | } | 1331 | } |
1337 | 1332 | ||
1338 | static void __exit alsa_card_atiixp_exit(void) | 1333 | static void __exit alsa_card_atiixp_exit(void) |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 889b4a1a51a1..f6236c63aaaa 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -375,7 +375,7 @@ static struct pci_driver driver = { | |||
375 | // initialization of the module | 375 | // initialization of the module |
376 | static int __init alsa_card_vortex_init(void) | 376 | static int __init alsa_card_vortex_init(void) |
377 | { | 377 | { |
378 | return pci_module_init(&driver); | 378 | return pci_register_driver(&driver); |
379 | } | 379 | } |
380 | 380 | ||
381 | // clean up the module | 381 | // clean up the module |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index b8ae534125c1..72bba7b2d983 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -1520,7 +1520,7 @@ static int __init alsa_card_azf3328_init(void) | |||
1520 | { | 1520 | { |
1521 | int err; | 1521 | int err; |
1522 | snd_azf3328_dbgcallenter(); | 1522 | snd_azf3328_dbgcallenter(); |
1523 | err = pci_module_init(&driver); | 1523 | err = pci_register_driver(&driver); |
1524 | snd_azf3328_dbgcallleave(); | 1524 | snd_azf3328_dbgcallleave(); |
1525 | return err; | 1525 | return err; |
1526 | } | 1526 | } |
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 89a7ffe5e7d7..c5557eaf3e2e 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -798,13 +798,15 @@ static struct { | |||
798 | {0x270f, 0xfc00}, /* Chaintech Digitop DST-1000 DVB-S */ | 798 | {0x270f, 0xfc00}, /* Chaintech Digitop DST-1000 DVB-S */ |
799 | }; | 799 | }; |
800 | 800 | ||
801 | static struct pci_driver driver; | ||
802 | |||
801 | /* return the rate of the card, or a negative value if it's blacklisted */ | 803 | /* return the rate of the card, or a negative value if it's blacklisted */ |
802 | static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) | 804 | static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) |
803 | { | 805 | { |
804 | int i; | 806 | int i; |
805 | const struct pci_device_id *supported; | 807 | const struct pci_device_id *supported; |
806 | 808 | ||
807 | supported = pci_match_device(snd_bt87x_ids, pci); | 809 | supported = pci_match_device(&driver, pci); |
808 | if (supported) | 810 | if (supported) |
809 | return supported->driver_data; | 811 | return supported->driver_data; |
810 | 812 | ||
@@ -918,7 +920,7 @@ static int __init alsa_card_bt87x_init(void) | |||
918 | { | 920 | { |
919 | if (load_all) | 921 | if (load_all) |
920 | driver.id_table = snd_bt87x_default_ids; | 922 | driver.id_table = snd_bt87x_default_ids; |
921 | return pci_module_init(&driver); | 923 | return pci_register_driver(&driver); |
922 | } | 924 | } |
923 | 925 | ||
924 | static void __exit alsa_card_bt87x_exit(void) | 926 | static void __exit alsa_card_bt87x_exit(void) |
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index deb028851056..da09cab405a9 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.20 | 4 | * Version: 0.0.21 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * See ca0106_main.c for features. | 7 | * See ca0106_main.c for features. |
@@ -45,6 +45,8 @@ | |||
45 | * Added I2C and SPI registers. Filled in interrupt enable. | 45 | * Added I2C and SPI registers. Filled in interrupt enable. |
46 | * 0.0.20 | 46 | * 0.0.20 |
47 | * Added GPIO info for SB Live 24bit. | 47 | * Added GPIO info for SB Live 24bit. |
48 | * 0.0.21 | ||
49 | * Implement support for Line-in capture on SB Live 24bit. | ||
48 | * | 50 | * |
49 | * | 51 | * |
50 | * This code was initally based on code from ALSA's emu10k1x.c which is: | 52 | * This code was initally based on code from ALSA's emu10k1x.c which is: |
@@ -152,7 +154,7 @@ | |||
152 | * bit 9 0 = Mute / 1 = Analog out. | 154 | * bit 9 0 = Mute / 1 = Analog out. |
153 | * bit 10 0 = Line-in / 1 = Mic-in. | 155 | * bit 10 0 = Line-in / 1 = Mic-in. |
154 | * bit 11 0 = ? / 1 = ? | 156 | * bit 11 0 = ? / 1 = ? |
155 | * bit 12 0 = ? / 1 = ? | 157 | * bit 12 0 = 48 Khz / 1 = 96 Khz Analog out on SB Live 24bit. |
156 | * bit 13 0 = ? / 1 = ? | 158 | * bit 13 0 = ? / 1 = ? |
157 | * bit 14 0 = Mute / 1 = Analog out | 159 | * bit 14 0 = Mute / 1 = Analog out |
158 | * bit 15 0 = ? / 1 = ? | 160 | * bit 15 0 = ? / 1 = ? |
@@ -475,9 +477,56 @@ | |||
475 | /* Causes interrupts based on timer intervals. */ | 477 | /* Causes interrupts based on timer intervals. */ |
476 | #define SPI 0x7a /* SPI: Serial Interface Register */ | 478 | #define SPI 0x7a /* SPI: Serial Interface Register */ |
477 | #define I2C_A 0x7b /* I2C Address. 32 bit */ | 479 | #define I2C_A 0x7b /* I2C Address. 32 bit */ |
478 | #define I2C_0 0x7c /* I2C Data Port 0. 32 bit */ | 480 | #define I2C_D0 0x7c /* I2C Data Port 0. 32 bit */ |
479 | #define I2C_1 0x7d /* I2C Data Port 1. 32 bit */ | 481 | #define I2C_D1 0x7d /* I2C Data Port 1. 32 bit */ |
482 | //I2C values | ||
483 | #define I2C_A_ADC_ADD_MASK 0x000000fe //The address is a 7 bit address | ||
484 | #define I2C_A_ADC_RW_MASK 0x00000001 //bit mask for R/W | ||
485 | #define I2C_A_ADC_TRANS_MASK 0x00000010 //Bit mask for I2c address DAC value | ||
486 | #define I2C_A_ADC_ABORT_MASK 0x00000020 //Bit mask for I2C transaction abort flag | ||
487 | #define I2C_A_ADC_LAST_MASK 0x00000040 //Bit mask for Last word transaction | ||
488 | #define I2C_A_ADC_BYTE_MASK 0x00000080 //Bit mask for Byte Mode | ||
480 | 489 | ||
490 | #define I2C_A_ADC_ADD 0x00000034 //This is the Device address for ADC | ||
491 | #define I2C_A_ADC_READ 0x00000001 //To perform a read operation | ||
492 | #define I2C_A_ADC_START 0x00000100 //Start I2C transaction | ||
493 | #define I2C_A_ADC_ABORT 0x00000200 //I2C transaction abort | ||
494 | #define I2C_A_ADC_LAST 0x00000400 //I2C last transaction | ||
495 | #define I2C_A_ADC_BYTE 0x00000800 //I2C one byte mode | ||
496 | |||
497 | #define I2C_D_ADC_REG_MASK 0xfe000000 //ADC address register | ||
498 | #define I2C_D_ADC_DAT_MASK 0x01ff0000 //ADC data register | ||
499 | |||
500 | #define ADC_TIMEOUT 0x00000007 //ADC Timeout Clock Disable | ||
501 | #define ADC_IFC_CTRL 0x0000000b //ADC Interface Control | ||
502 | #define ADC_MASTER 0x0000000c //ADC Master Mode Control | ||
503 | #define ADC_POWER 0x0000000d //ADC PowerDown Control | ||
504 | #define ADC_ATTEN_ADCL 0x0000000e //ADC Attenuation ADCL | ||
505 | #define ADC_ATTEN_ADCR 0x0000000f //ADC Attenuation ADCR | ||
506 | #define ADC_ALC_CTRL1 0x00000010 //ADC ALC Control 1 | ||
507 | #define ADC_ALC_CTRL2 0x00000011 //ADC ALC Control 2 | ||
508 | #define ADC_ALC_CTRL3 0x00000012 //ADC ALC Control 3 | ||
509 | #define ADC_NOISE_CTRL 0x00000013 //ADC Noise Gate Control | ||
510 | #define ADC_LIMIT_CTRL 0x00000014 //ADC Limiter Control | ||
511 | #define ADC_MUX 0x00000015 //ADC Mux offset | ||
512 | |||
513 | #if 0 | ||
514 | /* FIXME: Not tested yet. */ | ||
515 | #define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain | ||
516 | #define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB | ||
517 | #define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute | ||
518 | #define ADC_MUTE 0x000000c0 //Value to mute ADC | ||
519 | #define ADC_OSR 0x00000008 //Mask for ADC oversample rate select | ||
520 | #define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock | ||
521 | #define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter | ||
522 | #define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window | ||
523 | #endif | ||
524 | |||
525 | #define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux | ||
526 | #define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux | ||
527 | #define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux | ||
528 | #define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) | ||
529 | #define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux | ||
481 | 530 | ||
482 | #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ | 531 | #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ |
483 | #define PCM_FRONT_CHANNEL 0 | 532 | #define PCM_FRONT_CHANNEL 0 |
@@ -508,9 +557,18 @@ struct snd_ca0106_pcm { | |||
508 | unsigned short running; | 557 | unsigned short running; |
509 | }; | 558 | }; |
510 | 559 | ||
560 | typedef struct { | ||
561 | u32 serial; | ||
562 | char * name; | ||
563 | int ac97; | ||
564 | int gpio_type; | ||
565 | int i2c_adc; | ||
566 | } ca0106_details_t; | ||
567 | |||
511 | // definition of the chip-specific record | 568 | // definition of the chip-specific record |
512 | struct snd_ca0106 { | 569 | struct snd_ca0106 { |
513 | snd_card_t *card; | 570 | snd_card_t *card; |
571 | ca0106_details_t *details; | ||
514 | struct pci_dev *pci; | 572 | struct pci_dev *pci; |
515 | 573 | ||
516 | unsigned long port; | 574 | unsigned long port; |
@@ -531,6 +589,7 @@ struct snd_ca0106 { | |||
531 | u32 spdif_bits[4]; /* s/pdif out setup */ | 589 | u32 spdif_bits[4]; /* s/pdif out setup */ |
532 | int spdif_enable; | 590 | int spdif_enable; |
533 | int capture_source; | 591 | int capture_source; |
592 | int capture_mic_line_in; | ||
534 | 593 | ||
535 | struct snd_dma_buffer buffer; | 594 | struct snd_dma_buffer buffer; |
536 | }; | 595 | }; |
@@ -547,3 +606,6 @@ void snd_ca0106_ptr_write(ca0106_t *emu, | |||
547 | unsigned int chn, | 606 | unsigned int chn, |
548 | unsigned int data); | 607 | unsigned int data); |
549 | 608 | ||
609 | int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value); | ||
610 | |||
611 | |||
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 82533b45bc8c..95c289284267 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.22 | 4 | * Version: 0.0.23 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * Front, Rear and Center/LFE. | 7 | * Front, Rear and Center/LFE. |
@@ -77,6 +77,8 @@ | |||
77 | * Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.) | 77 | * Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.) |
78 | * 0.0.22 | 78 | * 0.0.22 |
79 | * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 | 79 | * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 |
80 | * 0.0.23 | ||
81 | * Implement support for Line-in capture on SB Live 24bit. | ||
80 | * | 82 | * |
81 | * BUGS: | 83 | * BUGS: |
82 | * Some stability problems when unloading the snd-ca0106 kernel module. | 84 | * Some stability problems when unloading the snd-ca0106 kernel module. |
@@ -136,6 +138,7 @@ | |||
136 | #include <linux/pci.h> | 138 | #include <linux/pci.h> |
137 | #include <linux/slab.h> | 139 | #include <linux/slab.h> |
138 | #include <linux/moduleparam.h> | 140 | #include <linux/moduleparam.h> |
141 | #include <linux/dma-mapping.h> | ||
139 | #include <sound/core.h> | 142 | #include <sound/core.h> |
140 | #include <sound/initval.h> | 143 | #include <sound/initval.h> |
141 | #include <sound/pcm.h> | 144 | #include <sound/pcm.h> |
@@ -161,18 +164,32 @@ MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard."); | |||
161 | 164 | ||
162 | #include "ca0106.h" | 165 | #include "ca0106.h" |
163 | 166 | ||
164 | typedef struct { | 167 | static ca0106_details_t ca0106_chip_details[] = { |
165 | u32 serial; | 168 | /* AudigyLS[SB0310] */ |
166 | char * name; | 169 | { .serial = 0x10021102, |
167 | } ca0106_names_t; | 170 | .name = "AudigyLS [SB0310]", |
168 | 171 | .ac97 = 1 } , | |
169 | static ca0106_names_t ca0106_chip_names[] = { | 172 | /* Unknown AudigyLS that also says SB0310 on it */ |
170 | { 0x10021102, "AudigyLS [SB0310]"} , | 173 | { .serial = 0x10051102, |
171 | { 0x10051102, "AudigyLS [SB0310b]"} , /* Unknown AudigyLS that also says SB0310 on it */ | 174 | .name = "AudigyLS [SB0310b]", |
172 | { 0x10061102, "Live! 7.1 24bit [SB0410]"} , /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */ | 175 | .ac97 = 1 } , |
173 | { 0x10071102, "Live! 7.1 24bit [SB0413]"} , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ | 176 | /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */ |
174 | { 0x10091462, "MSI K8N Diamond MB [SB0438]"}, /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ | 177 | { .serial = 0x10061102, |
175 | { 0, "AudigyLS [Unknown]" } | 178 | .name = "Live! 7.1 24bit [SB0410]", |
179 | .gpio_type = 1, | ||
180 | .i2c_adc = 1 } , | ||
181 | /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ | ||
182 | { .serial = 0x10071102, | ||
183 | .name = "Live! 7.1 24bit [SB0413]", | ||
184 | .gpio_type = 1, | ||
185 | .i2c_adc = 1 } , | ||
186 | /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ | ||
187 | { .serial = 0x10091462, | ||
188 | .name = "MSI K8N Diamond MB [SB0438]", | ||
189 | .gpio_type = 1, | ||
190 | .i2c_adc = 1 } , | ||
191 | { .serial = 0, | ||
192 | .name = "AudigyLS [Unknown]" } | ||
176 | }; | 193 | }; |
177 | 194 | ||
178 | /* hardware definition */ | 195 | /* hardware definition */ |
@@ -200,10 +217,10 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = { | |||
200 | SNDRV_PCM_INFO_INTERLEAVED | | 217 | SNDRV_PCM_INFO_INTERLEAVED | |
201 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 218 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
202 | SNDRV_PCM_INFO_MMAP_VALID), | 219 | SNDRV_PCM_INFO_MMAP_VALID), |
203 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 220 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, |
204 | .rates = SNDRV_PCM_RATE_48000, | 221 | .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, |
205 | .rate_min = 48000, | 222 | .rate_min = 44100, |
206 | .rate_max = 48000, | 223 | .rate_max = 192000, |
207 | .channels_min = 2, | 224 | .channels_min = 2, |
208 | .channels_max = 2, | 225 | .channels_max = 2, |
209 | .buffer_bytes_max = ((65536 - 64) * 8), | 226 | .buffer_bytes_max = ((65536 - 64) * 8), |
@@ -246,6 +263,62 @@ void snd_ca0106_ptr_write(ca0106_t *emu, | |||
246 | spin_unlock_irqrestore(&emu->emu_lock, flags); | 263 | spin_unlock_irqrestore(&emu->emu_lock, flags); |
247 | } | 264 | } |
248 | 265 | ||
266 | int snd_ca0106_i2c_write(ca0106_t *emu, | ||
267 | u32 reg, | ||
268 | u32 value) | ||
269 | { | ||
270 | u32 tmp; | ||
271 | int timeout=0; | ||
272 | int status; | ||
273 | int retry; | ||
274 | if ((reg > 0x7f) || (value > 0x1ff)) | ||
275 | { | ||
276 | snd_printk("i2c_write: invalid values.\n"); | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | tmp = reg << 25 | value << 16; | ||
281 | /* Not sure what this I2C channel controls. */ | ||
282 | /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ | ||
283 | |||
284 | /* This controls the I2C connected to the WM8775 ADC Codec */ | ||
285 | snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp); | ||
286 | |||
287 | for(retry=0;retry<10;retry++) | ||
288 | { | ||
289 | /* Send the data to i2c */ | ||
290 | tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); | ||
291 | tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); | ||
292 | tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); | ||
293 | snd_ca0106_ptr_write(emu, I2C_A, 0, tmp); | ||
294 | |||
295 | /* Wait till the transaction ends */ | ||
296 | while(1) | ||
297 | { | ||
298 | status = snd_ca0106_ptr_read(emu, I2C_A, 0); | ||
299 | //snd_printk("I2C:status=0x%x\n", status); | ||
300 | timeout++; | ||
301 | if((status & I2C_A_ADC_START)==0) | ||
302 | break; | ||
303 | |||
304 | if(timeout>1000) | ||
305 | break; | ||
306 | } | ||
307 | //Read back and see if the transaction is successful | ||
308 | if((status & I2C_A_ADC_ABORT)==0) | ||
309 | break; | ||
310 | } | ||
311 | |||
312 | if(retry==10) | ||
313 | { | ||
314 | snd_printk("Writing to ADC failed!\n"); | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | |||
249 | static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb) | 322 | static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb) |
250 | { | 323 | { |
251 | unsigned long flags; | 324 | unsigned long flags; |
@@ -259,11 +332,7 @@ static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb) | |||
259 | 332 | ||
260 | static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime) | 333 | static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime) |
261 | { | 334 | { |
262 | ca0106_pcm_t *epcm = runtime->private_data; | 335 | kfree(runtime->private_data); |
263 | |||
264 | if (epcm) { | ||
265 | kfree(epcm); | ||
266 | } | ||
267 | } | 336 | } |
268 | 337 | ||
269 | /* open_playback callback */ | 338 | /* open_playback callback */ |
@@ -538,6 +607,61 @@ static int snd_ca0106_pcm_prepare_capture(snd_pcm_substream_t *substream) | |||
538 | snd_pcm_runtime_t *runtime = substream->runtime; | 607 | snd_pcm_runtime_t *runtime = substream->runtime; |
539 | ca0106_pcm_t *epcm = runtime->private_data; | 608 | ca0106_pcm_t *epcm = runtime->private_data; |
540 | int channel = epcm->channel_id; | 609 | int channel = epcm->channel_id; |
610 | u32 hcfg_mask = HCFG_CAPTURE_S32_LE; | ||
611 | u32 hcfg_set = 0x00000000; | ||
612 | u32 hcfg; | ||
613 | u32 over_sampling=0x2; | ||
614 | u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */ | ||
615 | u32 reg71_set = 0; | ||
616 | u32 reg71; | ||
617 | |||
618 | //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); | ||
619 | //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); | ||
620 | //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); | ||
621 | /* reg71 controls ADC rate. */ | ||
622 | switch (runtime->rate) { | ||
623 | case 44100: | ||
624 | reg71_set = 0x00004000; | ||
625 | break; | ||
626 | case 48000: | ||
627 | reg71_set = 0; | ||
628 | break; | ||
629 | case 96000: | ||
630 | reg71_set = 0x00008000; | ||
631 | over_sampling=0xa; | ||
632 | break; | ||
633 | case 192000: | ||
634 | reg71_set = 0x0000c000; | ||
635 | over_sampling=0xa; | ||
636 | break; | ||
637 | default: | ||
638 | reg71_set = 0; | ||
639 | break; | ||
640 | } | ||
641 | /* Format is a global setting */ | ||
642 | /* FIXME: Only let the first channel accessed set this. */ | ||
643 | switch (runtime->format) { | ||
644 | case SNDRV_PCM_FORMAT_S16_LE: | ||
645 | hcfg_set = 0; | ||
646 | break; | ||
647 | case SNDRV_PCM_FORMAT_S32_LE: | ||
648 | hcfg_set = HCFG_CAPTURE_S32_LE; | ||
649 | break; | ||
650 | default: | ||
651 | hcfg_set = 0; | ||
652 | break; | ||
653 | } | ||
654 | hcfg = inl(emu->port + HCFG) ; | ||
655 | hcfg = (hcfg & ~hcfg_mask) | hcfg_set; | ||
656 | outl(hcfg, emu->port + HCFG); | ||
657 | reg71 = snd_ca0106_ptr_read(emu, 0x71, 0); | ||
658 | reg71 = (reg71 & ~reg71_mask) | reg71_set; | ||
659 | snd_ca0106_ptr_write(emu, 0x71, 0, reg71); | ||
660 | if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ | ||
661 | snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */ | ||
662 | } | ||
663 | |||
664 | |||
541 | //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); | 665 | //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); |
542 | snd_ca0106_ptr_write(emu, 0x13, channel, 0); | 666 | snd_ca0106_ptr_write(emu, 0x13, channel, 0); |
543 | snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); | 667 | snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); |
@@ -810,6 +934,7 @@ static int snd_ca0106_ac97(ca0106_t *chip) | |||
810 | 934 | ||
811 | memset(&ac97, 0, sizeof(ac97)); | 935 | memset(&ac97, 0, sizeof(ac97)); |
812 | ac97.private_data = chip; | 936 | ac97.private_data = chip; |
937 | ac97.scaps = AC97_SCAP_NO_SPDIF; | ||
813 | return snd_ac97_mixer(pbus, &ac97, &chip->ac97); | 938 | return snd_ac97_mixer(pbus, &ac97, &chip->ac97); |
814 | } | 939 | } |
815 | 940 | ||
@@ -993,6 +1118,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card, | |||
993 | ca0106_t **rchip) | 1118 | ca0106_t **rchip) |
994 | { | 1119 | { |
995 | ca0106_t *chip; | 1120 | ca0106_t *chip; |
1121 | ca0106_details_t *c; | ||
996 | int err; | 1122 | int err; |
997 | int ch; | 1123 | int ch; |
998 | static snd_device_ops_t ops = { | 1124 | static snd_device_ops_t ops = { |
@@ -1003,8 +1129,8 @@ static int __devinit snd_ca0106_create(snd_card_t *card, | |||
1003 | 1129 | ||
1004 | if ((err = pci_enable_device(pci)) < 0) | 1130 | if ((err = pci_enable_device(pci)) < 0) |
1005 | return err; | 1131 | return err; |
1006 | if (pci_set_dma_mask(pci, 0xffffffffUL) < 0 || | 1132 | if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 || |
1007 | pci_set_consistent_dma_mask(pci, 0xffffffffUL) < 0) { | 1133 | pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) { |
1008 | printk(KERN_ERR "error to set 32bit mask DMA\n"); | 1134 | printk(KERN_ERR "error to set 32bit mask DMA\n"); |
1009 | pci_disable_device(pci); | 1135 | pci_disable_device(pci); |
1010 | return -ENXIO; | 1136 | return -ENXIO; |
@@ -1054,6 +1180,15 @@ static int __devinit snd_ca0106_create(snd_card_t *card, | |||
1054 | printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model, | 1180 | printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model, |
1055 | chip->revision, chip->serial); | 1181 | chip->revision, chip->serial); |
1056 | #endif | 1182 | #endif |
1183 | strcpy(card->driver, "CA0106"); | ||
1184 | strcpy(card->shortname, "CA0106"); | ||
1185 | |||
1186 | for (c=ca0106_chip_details; c->serial; c++) { | ||
1187 | if (c->serial == chip->serial) break; | ||
1188 | } | ||
1189 | chip->details = c; | ||
1190 | sprintf(card->longname, "%s at 0x%lx irq %i", | ||
1191 | c->name, chip->port, chip->irq); | ||
1057 | 1192 | ||
1058 | outl(0, chip->port + INTE); | 1193 | outl(0, chip->port + INTE); |
1059 | 1194 | ||
@@ -1113,7 +1248,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card, | |||
1113 | //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */ | 1248 | //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */ |
1114 | /* Analog or Digital output */ | 1249 | /* Analog or Digital output */ |
1115 | snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf); | 1250 | snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf); |
1116 | snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000b0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers */ | 1251 | snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */ |
1117 | chip->spdif_enable = 0; /* Set digital SPDIF output off */ | 1252 | chip->spdif_enable = 0; /* Set digital SPDIF output off */ |
1118 | chip->capture_source = 3; /* Set CAPTURE_SOURCE */ | 1253 | chip->capture_source = 3; /* Set CAPTURE_SOURCE */ |
1119 | //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */ | 1254 | //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */ |
@@ -1138,13 +1273,11 @@ static int __devinit snd_ca0106_create(snd_card_t *card, | |||
1138 | snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ | 1273 | snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ |
1139 | chip->capture_source = 3; /* Set CAPTURE_SOURCE */ | 1274 | chip->capture_source = 3; /* Set CAPTURE_SOURCE */ |
1140 | 1275 | ||
1141 | if ((chip->serial == 0x10061102) || | 1276 | if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ |
1142 | (chip->serial == 0x10071102) || | ||
1143 | (chip->serial == 0x10091462)) { /* The SB0410 and SB0413 use GPIO differently. */ | ||
1144 | /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ | 1277 | /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ |
1145 | outl(0x0, chip->port+GPIO); | 1278 | outl(0x0, chip->port+GPIO); |
1146 | //outl(0x00f0e000, chip->port+GPIO); /* Analog */ | 1279 | //outl(0x00f0e000, chip->port+GPIO); /* Analog */ |
1147 | outl(0x005f4300, chip->port+GPIO); /* Analog */ | 1280 | outl(0x005f5301, chip->port+GPIO); /* Analog */ |
1148 | } else { | 1281 | } else { |
1149 | outl(0x0, chip->port+GPIO); | 1282 | outl(0x0, chip->port+GPIO); |
1150 | outl(0x005f03a3, chip->port+GPIO); /* Analog */ | 1283 | outl(0x005f03a3, chip->port+GPIO); /* Analog */ |
@@ -1157,6 +1290,10 @@ static int __devinit snd_ca0106_create(snd_card_t *card, | |||
1157 | //outl(0x00000009, chip->port+HCFG); | 1290 | //outl(0x00000009, chip->port+HCFG); |
1158 | outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ | 1291 | outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ |
1159 | 1292 | ||
1293 | if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ | ||
1294 | snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ | ||
1295 | } | ||
1296 | |||
1160 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, | 1297 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, |
1161 | chip, &ops)) < 0) { | 1298 | chip, &ops)) < 0) { |
1162 | snd_ca0106_free(chip); | 1299 | snd_ca0106_free(chip); |
@@ -1172,7 +1309,6 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1172 | static int dev; | 1309 | static int dev; |
1173 | snd_card_t *card; | 1310 | snd_card_t *card; |
1174 | ca0106_t *chip; | 1311 | ca0106_t *chip; |
1175 | ca0106_names_t *c; | ||
1176 | int err; | 1312 | int err; |
1177 | 1313 | ||
1178 | if (dev >= SNDRV_CARDS) | 1314 | if (dev >= SNDRV_CARDS) |
@@ -1207,9 +1343,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1207 | snd_card_free(card); | 1343 | snd_card_free(card); |
1208 | return err; | 1344 | return err; |
1209 | } | 1345 | } |
1210 | if ((chip->serial != 0x10061102) && | 1346 | if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */ |
1211 | (chip->serial != 0x10071102) && | ||
1212 | (chip->serial != 0x10091462) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */ | ||
1213 | if ((err = snd_ca0106_ac97(chip)) < 0) { | 1347 | if ((err = snd_ca0106_ac97(chip)) < 0) { |
1214 | snd_card_free(card); | 1348 | snd_card_free(card); |
1215 | return err; | 1349 | return err; |
@@ -1222,15 +1356,6 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1222 | 1356 | ||
1223 | snd_ca0106_proc_init(chip); | 1357 | snd_ca0106_proc_init(chip); |
1224 | 1358 | ||
1225 | strcpy(card->driver, "CA0106"); | ||
1226 | strcpy(card->shortname, "CA0106"); | ||
1227 | |||
1228 | for (c=ca0106_chip_names; c->serial; c++) { | ||
1229 | if (c->serial == chip->serial) break; | ||
1230 | } | ||
1231 | sprintf(card->longname, "%s at 0x%lx irq %i", | ||
1232 | c->name, chip->port, chip->irq); | ||
1233 | |||
1234 | if ((err = snd_card_register(card)) < 0) { | 1359 | if ((err = snd_card_register(card)) < 0) { |
1235 | snd_card_free(card); | 1360 | snd_card_free(card); |
1236 | return err; | 1361 | return err; |
@@ -1267,7 +1392,7 @@ static int __init alsa_card_ca0106_init(void) | |||
1267 | { | 1392 | { |
1268 | int err; | 1393 | int err; |
1269 | 1394 | ||
1270 | if ((err = pci_module_init(&driver)) > 0) | 1395 | if ((err = pci_register_driver(&driver)) > 0) |
1271 | return err; | 1396 | return err; |
1272 | 1397 | ||
1273 | return 0; | 1398 | return 0; |
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 97bed1b0899d..0e5e9ce0ff28 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.16 | 4 | * Version: 0.0.17 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * See ca0106_main.c for features. | 7 | * See ca0106_main.c for features. |
@@ -37,6 +37,8 @@ | |||
37 | * Separated ca0106.c into separate functional .c files. | 37 | * Separated ca0106.c into separate functional .c files. |
38 | * 0.0.16 | 38 | * 0.0.16 |
39 | * Modified Copyright message. | 39 | * Modified Copyright message. |
40 | * 0.0.17 | ||
41 | * Implement Mic and Line in Capture. | ||
40 | * | 42 | * |
41 | * This code was initally based on code from ALSA's emu10k1x.c which is: | 43 | * This code was initally based on code from ALSA's emu10k1x.c which is: |
42 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> | 44 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> |
@@ -113,7 +115,7 @@ static int snd_ca0106_shared_spdif_put(snd_kcontrol_t * kcontrol, | |||
113 | } else { | 115 | } else { |
114 | /* Analog */ | 116 | /* Analog */ |
115 | snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); | 117 | snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); |
116 | snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000b0000); | 118 | snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000); |
117 | snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, | 119 | snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, |
118 | snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000); | 120 | snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000); |
119 | mask = inl(emu->port + GPIO) | 0x101; | 121 | mask = inl(emu->port + GPIO) | 0x101; |
@@ -183,6 +185,65 @@ static snd_kcontrol_new_t snd_ca0106_capture_source __devinitdata = | |||
183 | .put = snd_ca0106_capture_source_put | 185 | .put = snd_ca0106_capture_source_put |
184 | }; | 186 | }; |
185 | 187 | ||
188 | static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) | ||
189 | { | ||
190 | static char *texts[2] = { "Line in", "Mic in" }; | ||
191 | |||
192 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
193 | uinfo->count = 1; | ||
194 | uinfo->value.enumerated.items = 2; | ||
195 | if (uinfo->value.enumerated.item > 1) | ||
196 | uinfo->value.enumerated.item = 1; | ||
197 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static int snd_ca0106_capture_mic_line_in_get(snd_kcontrol_t * kcontrol, | ||
202 | snd_ctl_elem_value_t * ucontrol) | ||
203 | { | ||
204 | ca0106_t *emu = snd_kcontrol_chip(kcontrol); | ||
205 | |||
206 | ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in; | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int snd_ca0106_capture_mic_line_in_put(snd_kcontrol_t * kcontrol, | ||
211 | snd_ctl_elem_value_t * ucontrol) | ||
212 | { | ||
213 | ca0106_t *emu = snd_kcontrol_chip(kcontrol); | ||
214 | unsigned int val; | ||
215 | int change = 0; | ||
216 | u32 tmp; | ||
217 | |||
218 | val = ucontrol->value.enumerated.item[0] ; | ||
219 | change = (emu->capture_mic_line_in != val); | ||
220 | if (change) { | ||
221 | emu->capture_mic_line_in = val; | ||
222 | if (val) { | ||
223 | snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ | ||
224 | tmp = inl(emu->port+GPIO) & ~0x400; | ||
225 | tmp = tmp | 0x400; | ||
226 | outl(tmp, emu->port+GPIO); | ||
227 | snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); | ||
228 | } else { | ||
229 | snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ | ||
230 | tmp = inl(emu->port+GPIO) & ~0x400; | ||
231 | outl(tmp, emu->port+GPIO); | ||
232 | snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); | ||
233 | } | ||
234 | } | ||
235 | return change; | ||
236 | } | ||
237 | |||
238 | static snd_kcontrol_new_t snd_ca0106_capture_mic_line_in __devinitdata = | ||
239 | { | ||
240 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
241 | .name = "Mic/Line in Capture", | ||
242 | .info = snd_ca0106_capture_mic_line_in_info, | ||
243 | .get = snd_ca0106_capture_mic_line_in_get, | ||
244 | .put = snd_ca0106_capture_mic_line_in_put | ||
245 | }; | ||
246 | |||
186 | static int snd_ca0106_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) | 247 | static int snd_ca0106_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) |
187 | { | 248 | { |
188 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | 249 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; |
@@ -437,7 +498,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe = | |||
437 | static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown = | 498 | static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown = |
438 | { | 499 | { |
439 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 500 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
440 | .name = "Analog Unknown Volume", | 501 | .name = "Analog Side Volume", |
441 | .info = snd_ca0106_volume_info, | 502 | .info = snd_ca0106_volume_info, |
442 | .get = snd_ca0106_volume_get_analog_unknown, | 503 | .get = snd_ca0106_volume_get_analog_unknown, |
443 | .put = snd_ca0106_volume_put_analog_unknown | 504 | .put = snd_ca0106_volume_put_analog_unknown |
@@ -620,10 +681,11 @@ int __devinit snd_ca0106_mixer(ca0106_t *emu) | |||
620 | return -ENOMEM; | 681 | return -ENOMEM; |
621 | if ((err = snd_ctl_add(card, kctl))) | 682 | if ((err = snd_ctl_add(card, kctl))) |
622 | return err; | 683 | return err; |
623 | if ((kctl = ctl_find(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT))) != NULL) { | 684 | if (emu->details->i2c_adc == 1) { |
624 | /* already defined by ac97, remove it */ | 685 | if ((kctl = snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)) == NULL) |
625 | /* FIXME: or do we need both controls? */ | 686 | return -ENOMEM; |
626 | remove_ctl(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT)); | 687 | if ((err = snd_ctl_add(card, kctl))) |
688 | return err; | ||
627 | } | 689 | } |
628 | if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL) | 690 | if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL) |
629 | return -ENOMEM; | 691 | return -ENOMEM; |
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index afb711421e47..1c9cc821d1b9 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit | 3 | * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit |
4 | * Version: 0.0.17 | 4 | * Version: 0.0.18 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * See ca0106_main.c for features. | 7 | * See ca0106_main.c for features. |
@@ -39,7 +39,9 @@ | |||
39 | * Modified Copyright message. | 39 | * Modified Copyright message. |
40 | * 0.0.17 | 40 | * 0.0.17 |
41 | * Add iec958 file in proc file system to show status of SPDIF in. | 41 | * Add iec958 file in proc file system to show status of SPDIF in. |
42 | * | 42 | * 0.0.18 |
43 | * Implement support for Line-in capture on SB Live 24bit. | ||
44 | * | ||
43 | * This code was initally based on code from ALSA's emu10k1x.c which is: | 45 | * This code was initally based on code from ALSA's emu10k1x.c which is: |
44 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> | 46 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> |
45 | * | 47 | * |
@@ -95,7 +97,7 @@ static struct snd_ca0106_category_str snd_ca0106_con_category[] = { | |||
95 | }; | 97 | }; |
96 | 98 | ||
97 | 99 | ||
98 | void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value) | 100 | static void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value) |
99 | { | 101 | { |
100 | int i; | 102 | int i; |
101 | u32 status[4]; | 103 | u32 status[4]; |
@@ -407,6 +409,20 @@ static void snd_ca0106_proc_reg_write(snd_info_entry_t *entry, | |||
407 | } | 409 | } |
408 | } | 410 | } |
409 | 411 | ||
412 | static void snd_ca0106_proc_i2c_write(snd_info_entry_t *entry, | ||
413 | snd_info_buffer_t * buffer) | ||
414 | { | ||
415 | ca0106_t *emu = entry->private_data; | ||
416 | char line[64]; | ||
417 | unsigned int reg, val; | ||
418 | while (!snd_info_get_line(buffer, line, sizeof(line))) { | ||
419 | if (sscanf(line, "%x %x", ®, &val) != 2) | ||
420 | continue; | ||
421 | if ((reg <= 0x7f) || (val <= 0x1ff)) { | ||
422 | snd_ca0106_i2c_write(emu, reg, val); | ||
423 | } | ||
424 | } | ||
425 | } | ||
410 | 426 | ||
411 | int __devinit snd_ca0106_proc_init(ca0106_t * emu) | 427 | int __devinit snd_ca0106_proc_init(ca0106_t * emu) |
412 | { | 428 | { |
@@ -418,6 +434,7 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu) | |||
418 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32); | 434 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32); |
419 | entry->c.text.write_size = 64; | 435 | entry->c.text.write_size = 64; |
420 | entry->c.text.write = snd_ca0106_proc_reg_write32; | 436 | entry->c.text.write = snd_ca0106_proc_reg_write32; |
437 | entry->mode |= S_IWUSR; | ||
421 | } | 438 | } |
422 | if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) | 439 | if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) |
423 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16); | 440 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16); |
@@ -427,6 +444,14 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu) | |||
427 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1); | 444 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1); |
428 | entry->c.text.write_size = 64; | 445 | entry->c.text.write_size = 64; |
429 | entry->c.text.write = snd_ca0106_proc_reg_write; | 446 | entry->c.text.write = snd_ca0106_proc_reg_write; |
447 | entry->mode |= S_IWUSR; | ||
448 | // entry->private_data = emu; | ||
449 | } | ||
450 | if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { | ||
451 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write); | ||
452 | entry->c.text.write_size = 64; | ||
453 | entry->c.text.write = snd_ca0106_proc_i2c_write; | ||
454 | entry->mode |= S_IWUSR; | ||
430 | // entry->private_data = emu; | 455 | // entry->private_data = emu; |
431 | } | 456 | } |
432 | if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) | 457 | if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 113208fbde1b..f5a4ac1ceef9 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -306,7 +306,7 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
306 | #define CM_REG_FM_PCI 0x50 | 306 | #define CM_REG_FM_PCI 0x50 |
307 | 307 | ||
308 | /* | 308 | /* |
309 | * for CMI-8338 .. this is not valid for CMI-8738. | 309 | * access from SB-mixer port |
310 | */ | 310 | */ |
311 | #define CM_REG_EXTENT_IND 0xf0 | 311 | #define CM_REG_EXTENT_IND 0xf0 |
312 | #define CM_VPHONE_MASK 0xe0 /* Phone volume control (0-3) << 5 */ | 312 | #define CM_VPHONE_MASK 0xe0 /* Phone volume control (0-3) << 5 */ |
@@ -315,6 +315,7 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
315 | #define CM_VSPKM 0x08 /* Speaker mute control, default high */ | 315 | #define CM_VSPKM 0x08 /* Speaker mute control, default high */ |
316 | #define CM_RLOOPREN 0x04 /* Rec. R-channel enable */ | 316 | #define CM_RLOOPREN 0x04 /* Rec. R-channel enable */ |
317 | #define CM_RLOOPLEN 0x02 /* Rec. L-channel enable */ | 317 | #define CM_RLOOPLEN 0x02 /* Rec. L-channel enable */ |
318 | #define CM_VADMIC3 0x01 /* Mic record boost */ | ||
318 | 319 | ||
319 | /* | 320 | /* |
320 | * CMI-8338 spec ver 0.5 (this is not valid for CMI-8738): | 321 | * CMI-8338 spec ver 0.5 (this is not valid for CMI-8738): |
@@ -488,71 +489,83 @@ struct snd_stru_cmipci { | |||
488 | 489 | ||
489 | 490 | ||
490 | /* read/write operations for dword register */ | 491 | /* read/write operations for dword register */ |
491 | inline static void snd_cmipci_write(cmipci_t *cm, unsigned int cmd, unsigned int data) | 492 | static inline void snd_cmipci_write(cmipci_t *cm, unsigned int cmd, unsigned int data) |
492 | { | 493 | { |
493 | outl(data, cm->iobase + cmd); | 494 | outl(data, cm->iobase + cmd); |
494 | } | 495 | } |
495 | inline static unsigned int snd_cmipci_read(cmipci_t *cm, unsigned int cmd) | 496 | |
497 | static inline unsigned int snd_cmipci_read(cmipci_t *cm, unsigned int cmd) | ||
496 | { | 498 | { |
497 | return inl(cm->iobase + cmd); | 499 | return inl(cm->iobase + cmd); |
498 | } | 500 | } |
499 | 501 | ||
500 | /* read/write operations for word register */ | 502 | /* read/write operations for word register */ |
501 | inline static void snd_cmipci_write_w(cmipci_t *cm, unsigned int cmd, unsigned short data) | 503 | static inline void snd_cmipci_write_w(cmipci_t *cm, unsigned int cmd, unsigned short data) |
502 | { | 504 | { |
503 | outw(data, cm->iobase + cmd); | 505 | outw(data, cm->iobase + cmd); |
504 | } | 506 | } |
505 | inline static unsigned short snd_cmipci_read_w(cmipci_t *cm, unsigned int cmd) | 507 | |
508 | static inline unsigned short snd_cmipci_read_w(cmipci_t *cm, unsigned int cmd) | ||
506 | { | 509 | { |
507 | return inw(cm->iobase + cmd); | 510 | return inw(cm->iobase + cmd); |
508 | } | 511 | } |
509 | 512 | ||
510 | /* read/write operations for byte register */ | 513 | /* read/write operations for byte register */ |
511 | inline static void snd_cmipci_write_b(cmipci_t *cm, unsigned int cmd, unsigned char data) | 514 | static inline void snd_cmipci_write_b(cmipci_t *cm, unsigned int cmd, unsigned char data) |
512 | { | 515 | { |
513 | outb(data, cm->iobase + cmd); | 516 | outb(data, cm->iobase + cmd); |
514 | } | 517 | } |
515 | 518 | ||
516 | inline static unsigned char snd_cmipci_read_b(cmipci_t *cm, unsigned int cmd) | 519 | static inline unsigned char snd_cmipci_read_b(cmipci_t *cm, unsigned int cmd) |
517 | { | 520 | { |
518 | return inb(cm->iobase + cmd); | 521 | return inb(cm->iobase + cmd); |
519 | } | 522 | } |
520 | 523 | ||
521 | /* bit operations for dword register */ | 524 | /* bit operations for dword register */ |
522 | static void snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) | 525 | static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) |
523 | { | 526 | { |
524 | unsigned int val; | 527 | unsigned int val, oval; |
525 | val = inl(cm->iobase + cmd); | 528 | val = oval = inl(cm->iobase + cmd); |
526 | val |= flag; | 529 | val |= flag; |
530 | if (val == oval) | ||
531 | return 0; | ||
527 | outl(val, cm->iobase + cmd); | 532 | outl(val, cm->iobase + cmd); |
533 | return 1; | ||
528 | } | 534 | } |
529 | 535 | ||
530 | static void snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) | 536 | static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) |
531 | { | 537 | { |
532 | unsigned int val; | 538 | unsigned int val, oval; |
533 | val = inl(cm->iobase + cmd); | 539 | val = oval = inl(cm->iobase + cmd); |
534 | val &= ~flag; | 540 | val &= ~flag; |
541 | if (val == oval) | ||
542 | return 0; | ||
535 | outl(val, cm->iobase + cmd); | 543 | outl(val, cm->iobase + cmd); |
544 | return 1; | ||
536 | } | 545 | } |
537 | 546 | ||
538 | #if 0 // not used | ||
539 | /* bit operations for byte register */ | 547 | /* bit operations for byte register */ |
540 | static void snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) | 548 | static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) |
541 | { | 549 | { |
542 | unsigned char val; | 550 | unsigned char val, oval; |
543 | val = inb(cm->iobase + cmd); | 551 | val = oval = inb(cm->iobase + cmd); |
544 | val |= flag; | 552 | val |= flag; |
553 | if (val == oval) | ||
554 | return 0; | ||
545 | outb(val, cm->iobase + cmd); | 555 | outb(val, cm->iobase + cmd); |
556 | return 1; | ||
546 | } | 557 | } |
547 | 558 | ||
548 | static void snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) | 559 | static int snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) |
549 | { | 560 | { |
550 | unsigned char val; | 561 | unsigned char val, oval; |
551 | val = inb(cm->iobase + cmd); | 562 | val = oval = inb(cm->iobase + cmd); |
552 | val &= ~flag; | 563 | val &= ~flag; |
564 | if (val == oval) | ||
565 | return 0; | ||
553 | outb(val, cm->iobase + cmd); | 566 | outb(val, cm->iobase + cmd); |
567 | return 1; | ||
554 | } | 568 | } |
555 | #endif | ||
556 | 569 | ||
557 | 570 | ||
558 | /* | 571 | /* |
@@ -2123,8 +2136,12 @@ static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = { | |||
2123 | CMIPCI_MIXER_VOL_STEREO("Aux Playback Volume", CM_REG_AUX_VOL, 4, 0, 15), | 2136 | CMIPCI_MIXER_VOL_STEREO("Aux Playback Volume", CM_REG_AUX_VOL, 4, 0, 15), |
2124 | CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 0), | 2137 | CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 0), |
2125 | CMIPCI_MIXER_SW_STEREO("Aux Capture Switch", CM_REG_MIXER2, CM_RAUXLEN_SHIFT, CM_RAUXREN_SHIFT, 0), | 2138 | CMIPCI_MIXER_SW_STEREO("Aux Capture Switch", CM_REG_MIXER2, CM_RAUXLEN_SHIFT, CM_RAUXREN_SHIFT, 0), |
2126 | CMIPCI_MIXER_SW_MONO("Mic Boost", CM_REG_MIXER2, CM_MICGAINZ_SHIFT, 1), | 2139 | CMIPCI_MIXER_SW_MONO("Mic Boost Playback Switch", CM_REG_MIXER2, CM_MICGAINZ_SHIFT, 1), |
2127 | CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), | 2140 | CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), |
2141 | CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7), | ||
2142 | CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0), | ||
2143 | CMIPCI_DOUBLE("PC Speaker Playnack Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), | ||
2144 | CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0), | ||
2128 | }; | 2145 | }; |
2129 | 2146 | ||
2130 | /* | 2147 | /* |
@@ -2250,8 +2267,8 @@ DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* rever | |||
2250 | DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); | 2267 | DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); |
2251 | #endif | 2268 | #endif |
2252 | DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); | 2269 | DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); |
2253 | DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0); | 2270 | // DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0); |
2254 | DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0); | 2271 | // DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0); |
2255 | // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ | 2272 | // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ |
2256 | DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); | 2273 | DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); |
2257 | 2274 | ||
@@ -2300,10 +2317,114 @@ static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v | |||
2300 | } | 2317 | } |
2301 | 2318 | ||
2302 | 2319 | ||
2320 | static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol, | ||
2321 | snd_ctl_elem_info_t *uinfo) | ||
2322 | { | ||
2323 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2324 | static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" }; | ||
2325 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2326 | uinfo->count = 1; | ||
2327 | uinfo->value.enumerated.items = cm->chip_version >= 39 ? 3 : 2; | ||
2328 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2329 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
2330 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
2331 | return 0; | ||
2332 | } | ||
2333 | |||
2334 | static inline unsigned int get_line_in_mode(cmipci_t *cm) | ||
2335 | { | ||
2336 | unsigned int val; | ||
2337 | if (cm->chip_version >= 39) { | ||
2338 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL); | ||
2339 | if (val & CM_LINE_AS_BASS) | ||
2340 | return 2; | ||
2341 | } | ||
2342 | val = snd_cmipci_read_b(cm, CM_REG_MIXER1); | ||
2343 | if (val & CM_SPK4) | ||
2344 | return 1; | ||
2345 | return 0; | ||
2346 | } | ||
2347 | |||
2348 | static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol, | ||
2349 | snd_ctl_elem_value_t *ucontrol) | ||
2350 | { | ||
2351 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2352 | |||
2353 | spin_lock_irq(&cm->reg_lock); | ||
2354 | ucontrol->value.enumerated.item[0] = get_line_in_mode(cm); | ||
2355 | spin_unlock_irq(&cm->reg_lock); | ||
2356 | return 0; | ||
2357 | } | ||
2358 | |||
2359 | static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol, | ||
2360 | snd_ctl_elem_value_t *ucontrol) | ||
2361 | { | ||
2362 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2363 | int change; | ||
2364 | |||
2365 | spin_lock_irq(&cm->reg_lock); | ||
2366 | if (ucontrol->value.enumerated.item[0] == 2) | ||
2367 | change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); | ||
2368 | else | ||
2369 | change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); | ||
2370 | if (ucontrol->value.enumerated.item[0] == 1) | ||
2371 | change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4); | ||
2372 | else | ||
2373 | change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4); | ||
2374 | spin_unlock_irq(&cm->reg_lock); | ||
2375 | return change; | ||
2376 | } | ||
2377 | |||
2378 | static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol, | ||
2379 | snd_ctl_elem_info_t *uinfo) | ||
2380 | { | ||
2381 | static char *texts[2] = { "Mic-In", "Center/LFE Output" }; | ||
2382 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2383 | uinfo->count = 1; | ||
2384 | uinfo->value.enumerated.items = 2; | ||
2385 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2386 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
2387 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
2388 | return 0; | ||
2389 | } | ||
2390 | |||
2391 | static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol, | ||
2392 | snd_ctl_elem_value_t *ucontrol) | ||
2393 | { | ||
2394 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2395 | /* same bit as spdi_phase */ | ||
2396 | spin_lock_irq(&cm->reg_lock); | ||
2397 | ucontrol->value.enumerated.item[0] = | ||
2398 | (snd_cmipci_read_b(cm, CM_REG_MISC) & CM_SPDIF_INVERSE) ? 1 : 0; | ||
2399 | spin_unlock_irq(&cm->reg_lock); | ||
2400 | return 0; | ||
2401 | } | ||
2402 | |||
2403 | static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol, | ||
2404 | snd_ctl_elem_value_t *ucontrol) | ||
2405 | { | ||
2406 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2407 | int change; | ||
2408 | |||
2409 | spin_lock_irq(&cm->reg_lock); | ||
2410 | if (ucontrol->value.enumerated.item[0]) | ||
2411 | change = snd_cmipci_set_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); | ||
2412 | else | ||
2413 | change = snd_cmipci_clear_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); | ||
2414 | spin_unlock_irq(&cm->reg_lock); | ||
2415 | return change; | ||
2416 | } | ||
2417 | |||
2303 | /* both for CM8338/8738 */ | 2418 | /* both for CM8338/8738 */ |
2304 | static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = { | 2419 | static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = { |
2305 | DEFINE_MIXER_SWITCH("Four Channel Mode", fourch), | 2420 | DEFINE_MIXER_SWITCH("Four Channel Mode", fourch), |
2306 | DEFINE_MIXER_SWITCH("Line-In As Rear", line_rear), | 2421 | { |
2422 | .name = "Line-In Mode", | ||
2423 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2424 | .info = snd_cmipci_line_in_mode_info, | ||
2425 | .get = snd_cmipci_line_in_mode_get, | ||
2426 | .put = snd_cmipci_line_in_mode_put, | ||
2427 | }, | ||
2307 | }; | 2428 | }; |
2308 | 2429 | ||
2309 | /* for non-multichannel chips */ | 2430 | /* for non-multichannel chips */ |
@@ -2341,10 +2462,15 @@ static snd_kcontrol_new_t snd_cmipci_old_mixer_switches[] __devinitdata = { | |||
2341 | 2462 | ||
2342 | /* only for model 039 or later */ | 2463 | /* only for model 039 or later */ |
2343 | static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = { | 2464 | static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = { |
2344 | DEFINE_MIXER_SWITCH("Line-In As Bass", line_bass), | ||
2345 | DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2), | 2465 | DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2), |
2346 | DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2), | 2466 | DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2), |
2347 | DEFINE_MIXER_SWITCH("Mic As Center/LFE", spdi_phase), /* same bit as spdi_phase */ | 2467 | { |
2468 | .name = "Mic-In Mode", | ||
2469 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2470 | .info = snd_cmipci_mic_in_mode_info, | ||
2471 | .get = snd_cmipci_mic_in_mode_get, | ||
2472 | .put = snd_cmipci_mic_in_mode_put, | ||
2473 | } | ||
2348 | }; | 2474 | }; |
2349 | 2475 | ||
2350 | /* card control switches */ | 2476 | /* card control switches */ |
@@ -2944,7 +3070,7 @@ static struct pci_driver driver = { | |||
2944 | 3070 | ||
2945 | static int __init alsa_card_cmipci_init(void) | 3071 | static int __init alsa_card_cmipci_init(void) |
2946 | { | 3072 | { |
2947 | return pci_module_init(&driver); | 3073 | return pci_register_driver(&driver); |
2948 | } | 3074 | } |
2949 | 3075 | ||
2950 | static void __exit alsa_card_cmipci_exit(void) | 3076 | static void __exit alsa_card_cmipci_exit(void) |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index d7e06b3caf97..c7a370d4f923 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -206,7 +206,10 @@ MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled)."); | |||
206 | 206 | ||
207 | #define BA0_PMCS 0x0344 /* Power Management Control/Status */ | 207 | #define BA0_PMCS 0x0344 /* Power Management Control/Status */ |
208 | #define BA0_CWPR 0x03e0 /* Configuration Write Protect */ | 208 | #define BA0_CWPR 0x03e0 /* Configuration Write Protect */ |
209 | |||
209 | #define BA0_EPPMC 0x03e4 /* Extended PCI Power Management Control */ | 210 | #define BA0_EPPMC 0x03e4 /* Extended PCI Power Management Control */ |
211 | #define BA0_EPPMC_FPDN (1<<14) /* Full Power DowN */ | ||
212 | |||
210 | #define BA0_GPIOR 0x03e8 /* GPIO Pin Interface Register */ | 213 | #define BA0_GPIOR 0x03e8 /* GPIO Pin Interface Register */ |
211 | 214 | ||
212 | #define BA0_SPMC 0x03ec /* Serial Port Power Management Control (& ASDIN2 enable) */ | 215 | #define BA0_SPMC 0x03ec /* Serial Port Power Management Control (& ASDIN2 enable) */ |
@@ -539,7 +542,7 @@ static void snd_cs4281_delay(unsigned int delay) | |||
539 | } | 542 | } |
540 | } | 543 | } |
541 | 544 | ||
542 | inline static void snd_cs4281_delay_long(void) | 545 | static inline void snd_cs4281_delay_long(void) |
543 | { | 546 | { |
544 | set_current_state(TASK_UNINTERRUPTIBLE); | 547 | set_current_state(TASK_UNINTERRUPTIBLE); |
545 | schedule_timeout(1); | 548 | schedule_timeout(1); |
@@ -1335,11 +1338,6 @@ static inline int snd_cs4281_create_gameport(cs4281_t *chip) { return -ENOSYS; } | |||
1335 | static inline void snd_cs4281_free_gameport(cs4281_t *chip) { } | 1338 | static inline void snd_cs4281_free_gameport(cs4281_t *chip) { } |
1336 | #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ | 1339 | #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ |
1337 | 1340 | ||
1338 | |||
1339 | /* | ||
1340 | |||
1341 | */ | ||
1342 | |||
1343 | static int snd_cs4281_free(cs4281_t *chip) | 1341 | static int snd_cs4281_free(cs4281_t *chip) |
1344 | { | 1342 | { |
1345 | snd_cs4281_free_gameport(chip); | 1343 | snd_cs4281_free_gameport(chip); |
@@ -1461,6 +1459,11 @@ static int snd_cs4281_chip_init(cs4281_t *chip) | |||
1461 | int timeout; | 1459 | int timeout; |
1462 | int retry_count = 2; | 1460 | int retry_count = 2; |
1463 | 1461 | ||
1462 | /* Having EPPMC.FPDN=1 prevent proper chip initialisation */ | ||
1463 | tmp = snd_cs4281_peekBA0(chip, BA0_EPPMC); | ||
1464 | if (tmp & BA0_EPPMC_FPDN) | ||
1465 | snd_cs4281_pokeBA0(chip, BA0_EPPMC, tmp & ~BA0_EPPMC_FPDN); | ||
1466 | |||
1464 | __retry: | 1467 | __retry: |
1465 | tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); | 1468 | tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); |
1466 | if (tmp != BA0_CFLR_DEFAULT) { | 1469 | if (tmp != BA0_CFLR_DEFAULT) { |
@@ -2124,7 +2127,7 @@ static struct pci_driver driver = { | |||
2124 | 2127 | ||
2125 | static int __init alsa_card_cs4281_init(void) | 2128 | static int __init alsa_card_cs4281_init(void) |
2126 | { | 2129 | { |
2127 | return pci_module_init(&driver); | 2130 | return pci_register_driver(&driver); |
2128 | } | 2131 | } |
2129 | 2132 | ||
2130 | static void __exit alsa_card_cs4281_exit(void) | 2133 | static void __exit alsa_card_cs4281_exit(void) |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 25d6466a867c..db212ecd792a 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
@@ -171,7 +171,7 @@ static struct pci_driver driver = { | |||
171 | 171 | ||
172 | static int __init alsa_card_cs46xx_init(void) | 172 | static int __init alsa_card_cs46xx_init(void) |
173 | { | 173 | { |
174 | return pci_module_init(&driver); | 174 | return pci_register_driver(&driver); |
175 | } | 175 | } |
176 | 176 | ||
177 | static void __exit alsa_card_cs46xx_exit(void) | 177 | static void __exit alsa_card_cs46xx_exit(void) |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 5f2ffb7efa06..ff28af1f658e 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -1295,8 +1295,7 @@ static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = { | |||
1295 | 1295 | ||
1296 | static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime) | 1296 | static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime) |
1297 | { | 1297 | { |
1298 | cs46xx_pcm_t * cpcm = runtime->private_data; | 1298 | kfree(runtime->private_data); |
1299 | kfree(cpcm); | ||
1300 | } | 1299 | } |
1301 | 1300 | ||
1302 | static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id) | 1301 | static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id) |
@@ -2401,8 +2400,7 @@ static void snd_cs46xx_codec_reset (ac97_t * ac97) | |||
2401 | if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05) | 2400 | if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05) |
2402 | return; | 2401 | return; |
2403 | 2402 | ||
2404 | set_current_state(TASK_UNINTERRUPTIBLE); | 2403 | msleep(10); |
2405 | schedule_timeout(HZ/100); | ||
2406 | } while (time_after_eq(end_time, jiffies)); | 2404 | } while (time_after_eq(end_time, jiffies)); |
2407 | 2405 | ||
2408 | snd_printk("CS46xx secondary codec dont respond!\n"); | 2406 | snd_printk("CS46xx secondary codec dont respond!\n"); |
@@ -2436,8 +2434,7 @@ static int __devinit cs46xx_detect_codec(cs46xx_t *chip, int codec) | |||
2436 | err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]); | 2434 | err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]); |
2437 | return err; | 2435 | return err; |
2438 | } | 2436 | } |
2439 | set_current_state(TASK_INTERRUPTIBLE); | 2437 | msleep(10); |
2440 | schedule_timeout(HZ/100); | ||
2441 | } | 2438 | } |
2442 | snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec); | 2439 | snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec); |
2443 | return -ENXIO; | 2440 | return -ENXIO; |
@@ -3019,8 +3016,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip) | |||
3019 | /* | 3016 | /* |
3020 | * Wait until the PLL has stabilized. | 3017 | * Wait until the PLL has stabilized. |
3021 | */ | 3018 | */ |
3022 | set_current_state(TASK_UNINTERRUPTIBLE); | 3019 | msleep(100); |
3023 | schedule_timeout(HZ/10); /* 100ms */ | ||
3024 | 3020 | ||
3025 | /* | 3021 | /* |
3026 | * Turn on clocking of the core so that we can setup the serial ports. | 3022 | * Turn on clocking of the core so that we can setup the serial ports. |
@@ -3073,8 +3069,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip) | |||
3073 | */ | 3069 | */ |
3074 | if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY) | 3070 | if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY) |
3075 | goto ok1; | 3071 | goto ok1; |
3076 | set_current_state(TASK_UNINTERRUPTIBLE); | 3072 | msleep(10); |
3077 | schedule_timeout((HZ+99)/100); | ||
3078 | } | 3073 | } |
3079 | 3074 | ||
3080 | 3075 | ||
@@ -3123,8 +3118,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip) | |||
3123 | */ | 3118 | */ |
3124 | if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) | 3119 | if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) |
3125 | goto ok2; | 3120 | goto ok2; |
3126 | set_current_state(TASK_UNINTERRUPTIBLE); | 3121 | msleep(10); |
3127 | schedule_timeout((HZ+99)/100); | ||
3128 | } | 3122 | } |
3129 | 3123 | ||
3130 | #ifndef CONFIG_SND_CS46XX_NEW_DSP | 3124 | #ifndef CONFIG_SND_CS46XX_NEW_DSP |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 6446afe19d80..b17142cabead 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -52,6 +52,7 @@ static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; | |||
52 | static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; | 52 | static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; |
53 | static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; | 53 | static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; |
54 | static int enable_ir[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 54 | static int enable_ir[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; |
55 | static uint subsystem[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* Force card subsystem model */ | ||
55 | 56 | ||
56 | module_param_array(index, int, NULL, 0444); | 57 | module_param_array(index, int, NULL, 0444); |
57 | MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); | 58 | MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); |
@@ -71,7 +72,8 @@ module_param_array(max_buffer_size, int, NULL, 0444); | |||
71 | MODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB."); | 72 | MODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB."); |
72 | module_param_array(enable_ir, bool, NULL, 0444); | 73 | module_param_array(enable_ir, bool, NULL, 0444); |
73 | MODULE_PARM_DESC(enable_ir, "Enable IR."); | 74 | MODULE_PARM_DESC(enable_ir, "Enable IR."); |
74 | 75 | module_param_array(subsystem, uint, NULL, 0444); | |
76 | MODULE_PARM_DESC(subsystem, "Force card subsystem model."); | ||
75 | /* | 77 | /* |
76 | * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 | 78 | * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 |
77 | */ | 79 | */ |
@@ -122,7 +124,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, | |||
122 | max_buffer_size[dev] = 1024; | 124 | max_buffer_size[dev] = 1024; |
123 | if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], | 125 | if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], |
124 | (long)max_buffer_size[dev] * 1024 * 1024, | 126 | (long)max_buffer_size[dev] * 1024 * 1024, |
125 | enable_ir[dev], | 127 | enable_ir[dev], subsystem[dev], |
126 | &emu)) < 0) { | 128 | &emu)) < 0) { |
127 | snd_card_free(card); | 129 | snd_card_free(card); |
128 | return err; | 130 | return err; |
@@ -140,7 +142,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, | |||
140 | return err; | 142 | return err; |
141 | } | 143 | } |
142 | /* This stores the periods table. */ | 144 | /* This stores the periods table. */ |
143 | if (emu->audigy && emu->revision == 4) { /* P16V */ | 145 | if (emu->card_capabilities->ca0151_chip) { /* P16V */ |
144 | if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &emu->p16v_buffer) < 0) { | 146 | if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &emu->p16v_buffer) < 0) { |
145 | snd_p16v_free(emu); | 147 | snd_p16v_free(emu); |
146 | return -ENOMEM; | 148 | return -ENOMEM; |
@@ -161,7 +163,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, | |||
161 | snd_card_free(card); | 163 | snd_card_free(card); |
162 | return err; | 164 | return err; |
163 | } | 165 | } |
164 | if (emu->audigy && emu->revision == 4) { /* P16V */ | 166 | if (emu->card_capabilities->ca0151_chip) { /* P16V */ |
165 | if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) { | 167 | if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) { |
166 | snd_card_free(card); | 168 | snd_card_free(card); |
167 | return err; | 169 | return err; |
@@ -228,7 +230,7 @@ static struct pci_driver driver = { | |||
228 | 230 | ||
229 | static int __init alsa_card_emu10k1_init(void) | 231 | static int __init alsa_card_emu10k1_init(void) |
230 | { | 232 | { |
231 | return pci_module_init(&driver); | 233 | return pci_register_driver(&driver); |
232 | } | 234 | } |
233 | 235 | ||
234 | static void __exit alsa_card_emu10k1_exit(void) | 236 | static void __exit alsa_card_emu10k1_exit(void) |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index c3c96f9f2c7f..746b51ef3966 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -170,7 +170,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) | |||
170 | SPCS_GENERATIONSTATUS | 0x00001200 | | 170 | SPCS_GENERATIONSTATUS | 0x00001200 | |
171 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); | 171 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); |
172 | 172 | ||
173 | if (emu->audigy && emu->revision == 4) { /* audigy2 */ | 173 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ |
174 | /* Hacks for Alice3 to work independent of haP16V driver */ | 174 | /* Hacks for Alice3 to work independent of haP16V driver */ |
175 | u32 tmp; | 175 | u32 tmp; |
176 | 176 | ||
@@ -189,9 +189,9 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) | |||
189 | /* Enabled Phased (8-channel) P16V playback */ | 189 | /* Enabled Phased (8-channel) P16V playback */ |
190 | outl(0x0201, emu->port + HCFG2); | 190 | outl(0x0201, emu->port + HCFG2); |
191 | /* Set playback routing. */ | 191 | /* Set playback routing. */ |
192 | snd_emu10k1_ptr_write(emu, CAPTURE_P16V_SOURCE, 0, 78e4); | 192 | snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4); |
193 | } | 193 | } |
194 | if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */ | 194 | if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ |
195 | /* Hacks for Alice3 to work independent of haP16V driver */ | 195 | /* Hacks for Alice3 to work independent of haP16V driver */ |
196 | u32 tmp; | 196 | u32 tmp; |
197 | 197 | ||
@@ -253,6 +253,8 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) | |||
253 | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); | 253 | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); |
254 | else | 254 | else |
255 | outl(HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); | 255 | outl(HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); |
256 | /* FIXME: Remove all these emu->model and replace it with a card recognition parameter, | ||
257 | * e.g. card_capabilities->joystick */ | ||
256 | } else if (emu->model == 0x20 || | 258 | } else if (emu->model == 0x20 || |
257 | emu->model == 0xc400 || | 259 | emu->model == 0xc400 || |
258 | (emu->model == 0x21 && emu->revision < 6)) | 260 | (emu->model == 0x21 && emu->revision < 6)) |
@@ -299,12 +301,12 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) | |||
299 | if (emu->audigy) { | 301 | if (emu->audigy) { |
300 | outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); | 302 | outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); |
301 | 303 | ||
302 | if (emu->revision == 4) { /* audigy2 */ | 304 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ |
303 | /* Unmute Analog now. Set GPO6 to 1 for Apollo. | 305 | /* Unmute Analog now. Set GPO6 to 1 for Apollo. |
304 | * This has to be done after init ALice3 I2SOut beyond 48KHz. | 306 | * This has to be done after init ALice3 I2SOut beyond 48KHz. |
305 | * So, sequence is important. */ | 307 | * So, sequence is important. */ |
306 | outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); | 308 | outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); |
307 | } else if (emu->serial == 0x10011102) { /* audigy2 value */ | 309 | } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 value */ |
308 | /* Unmute Analog now. */ | 310 | /* Unmute Analog now. */ |
309 | outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); | 311 | outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); |
310 | } else { | 312 | } else { |
@@ -600,7 +602,7 @@ static int snd_emu10k1_free(emu10k1_t *emu) | |||
600 | if (emu->port) | 602 | if (emu->port) |
601 | pci_release_regions(emu->pci); | 603 | pci_release_regions(emu->pci); |
602 | pci_disable_device(emu->pci); | 604 | pci_disable_device(emu->pci); |
603 | if (emu->audigy && emu->revision == 4) /* P16V */ | 605 | if (emu->card_capabilities->ca0151_chip) /* P16V */ |
604 | snd_p16v_free(emu); | 606 | snd_p16v_free(emu); |
605 | kfree(emu); | 607 | kfree(emu); |
606 | return 0; | 608 | return 0; |
@@ -612,21 +614,33 @@ static int snd_emu10k1_dev_free(snd_device_t *device) | |||
612 | return snd_emu10k1_free(emu); | 614 | return snd_emu10k1_free(emu); |
613 | } | 615 | } |
614 | 616 | ||
615 | /* vendor, device, subsystem, emu10k1_chip, emu10k2_chip, ca0102_chip, ca0108_chip, ca0151_chip, spk71, spdif_bug, ac97_chip, ecard, driver, name */ | ||
616 | |||
617 | static emu_chip_details_t emu_chip_details[] = { | 617 | static emu_chip_details_t emu_chip_details[] = { |
618 | /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ | 618 | /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ |
619 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | ||
619 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, | 620 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, |
620 | .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", | 621 | .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", |
622 | .id = "Audigy2", | ||
621 | .emu10k2_chip = 1, | 623 | .emu10k2_chip = 1, |
622 | .ca0108_chip = 1, | 624 | .ca0108_chip = 1, |
623 | .spk71 = 1} , | 625 | .spk71 = 1, |
626 | .ac97_chip = 1} , | ||
624 | {.vendor = 0x1102, .device = 0x0008, | 627 | {.vendor = 0x1102, .device = 0x0008, |
625 | .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", | 628 | .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", |
629 | .id = "Audigy2", | ||
626 | .emu10k2_chip = 1, | 630 | .emu10k2_chip = 1, |
627 | .ca0108_chip = 1} , | 631 | .ca0108_chip = 1, |
632 | .ac97_chip = 1} , | ||
633 | /* Tested by James@superbug.co.uk 8th July 2005. No sound available yet. */ | ||
634 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, | ||
635 | .driver = "Audigy2", .name = "E-mu 1212m [4001]", | ||
636 | .id = "EMU1212m", | ||
637 | .emu10k2_chip = 1, | ||
638 | .ca0102_chip = 1, | ||
639 | .ecard = 1} , | ||
640 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | ||
628 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, | 641 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, |
629 | .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", | 642 | .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", |
643 | .id = "Audigy2", | ||
630 | .emu10k2_chip = 1, | 644 | .emu10k2_chip = 1, |
631 | .ca0102_chip = 1, | 645 | .ca0102_chip = 1, |
632 | .ca0151_chip = 1, | 646 | .ca0151_chip = 1, |
@@ -635,6 +649,7 @@ static emu_chip_details_t emu_chip_details[] = { | |||
635 | .ac97_chip = 1} , | 649 | .ac97_chip = 1} , |
636 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, | 650 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, |
637 | .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", | 651 | .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", |
652 | .id = "Audigy2", | ||
638 | .emu10k2_chip = 1, | 653 | .emu10k2_chip = 1, |
639 | .ca0102_chip = 1, | 654 | .ca0102_chip = 1, |
640 | .ca0151_chip = 1, | 655 | .ca0151_chip = 1, |
@@ -643,6 +658,7 @@ static emu_chip_details_t emu_chip_details[] = { | |||
643 | .ac97_chip = 1} , | 658 | .ac97_chip = 1} , |
644 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, | 659 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, |
645 | .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", | 660 | .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", |
661 | .id = "Audigy2", | ||
646 | .emu10k2_chip = 1, | 662 | .emu10k2_chip = 1, |
647 | .ca0102_chip = 1, | 663 | .ca0102_chip = 1, |
648 | .ca0151_chip = 1, | 664 | .ca0151_chip = 1, |
@@ -651,6 +667,7 @@ static emu_chip_details_t emu_chip_details[] = { | |||
651 | .ac97_chip = 1} , | 667 | .ac97_chip = 1} , |
652 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, | 668 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, |
653 | .driver = "Audigy2", .name = "Audigy 2 [SB0240]", | 669 | .driver = "Audigy2", .name = "Audigy 2 [SB0240]", |
670 | .id = "Audigy2", | ||
654 | .emu10k2_chip = 1, | 671 | .emu10k2_chip = 1, |
655 | .ca0102_chip = 1, | 672 | .ca0102_chip = 1, |
656 | .ca0151_chip = 1, | 673 | .ca0151_chip = 1, |
@@ -659,35 +676,160 @@ static emu_chip_details_t emu_chip_details[] = { | |||
659 | .ac97_chip = 1} , | 676 | .ac97_chip = 1} , |
660 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, | 677 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, |
661 | .driver = "Audigy2", .name = "Audigy 2 EX [1005]", | 678 | .driver = "Audigy2", .name = "Audigy 2 EX [1005]", |
679 | .id = "Audigy2", | ||
662 | .emu10k2_chip = 1, | 680 | .emu10k2_chip = 1, |
663 | .ca0102_chip = 1, | 681 | .ca0102_chip = 1, |
664 | .ca0151_chip = 1, | 682 | .ca0151_chip = 1, |
665 | .spdif_bug = 1} , | 683 | .spdif_bug = 1} , |
666 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, | 684 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, |
667 | .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", | 685 | .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", |
686 | .id = "Audigy2", | ||
668 | .emu10k2_chip = 1, | 687 | .emu10k2_chip = 1, |
669 | .ca0102_chip = 1, | 688 | .ca0102_chip = 1, |
670 | .ca0151_chip = 1, | 689 | .ca0151_chip = 1, |
671 | .spk71 = 1, | 690 | .spk71 = 1, |
672 | .spdif_bug = 1, | 691 | .spdif_bug = 1, |
673 | .ac97_chip = 1} , | 692 | .ac97_chip = 1} , |
693 | {.vendor = 0x1102, .device = 0x0004, .revision = 0x04, | ||
694 | .driver = "Audigy2", .name = "Audigy 2 [Unknown]", | ||
695 | .id = "Audigy2", | ||
696 | .emu10k2_chip = 1, | ||
697 | .ca0102_chip = 1, | ||
698 | .ca0151_chip = 1, | ||
699 | .spdif_bug = 1, | ||
700 | .ac97_chip = 1} , | ||
701 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102, | ||
702 | .driver = "Audigy", .name = "Audigy 1 [SB0090]", | ||
703 | .id = "Audigy", | ||
704 | .emu10k2_chip = 1, | ||
705 | .ca0102_chip = 1, | ||
706 | .ac97_chip = 1} , | ||
707 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102, | ||
708 | .driver = "Audigy", .name = "Audigy 1 ES [SB0160]", | ||
709 | .id = "Audigy", | ||
710 | .emu10k2_chip = 1, | ||
711 | .ca0102_chip = 1, | ||
712 | .spdif_bug = 1, | ||
713 | .ac97_chip = 1} , | ||
714 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102, | ||
715 | .driver = "Audigy", .name = "Audigy 1 [SB0090]", | ||
716 | .id = "Audigy", | ||
717 | .emu10k2_chip = 1, | ||
718 | .ca0102_chip = 1, | ||
719 | .ac97_chip = 1} , | ||
674 | {.vendor = 0x1102, .device = 0x0004, | 720 | {.vendor = 0x1102, .device = 0x0004, |
675 | .driver = "Audigy", .name = "Audigy 1 or 2 [Unknown]", | 721 | .driver = "Audigy", .name = "Audigy 1 [Unknown]", |
722 | .id = "Audigy", | ||
676 | .emu10k2_chip = 1, | 723 | .emu10k2_chip = 1, |
677 | .ca0102_chip = 1, | 724 | .ca0102_chip = 1, |
678 | .spdif_bug = 1} , | 725 | .ac97_chip = 1} , |
679 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, | 726 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102, |
680 | .driver = "EMU10K1", .name = "E-mu APS [4001]", | 727 | .driver = "EMU10K1", .name = "SBLive! [SB0105]", |
728 | .id = "Live", | ||
681 | .emu10k1_chip = 1, | 729 | .emu10k1_chip = 1, |
682 | .ecard = 1} , | 730 | .ac97_chip = 1, |
731 | .sblive51 = 1} , | ||
732 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102, | ||
733 | .driver = "EMU10K1", .name = "SBLive! Value [SB0103]", | ||
734 | .id = "Live", | ||
735 | .emu10k1_chip = 1, | ||
736 | .ac97_chip = 1, | ||
737 | .sblive51 = 1} , | ||
738 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102, | ||
739 | .driver = "EMU10K1", .name = "SBLive! Value [SB0101]", | ||
740 | .id = "Live", | ||
741 | .emu10k1_chip = 1, | ||
742 | .ac97_chip = 1, | ||
743 | .sblive51 = 1} , | ||
683 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, | 744 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, |
684 | .driver = "EMU10K1", .name = "SB Live 5.1", | 745 | .driver = "EMU10K1", .name = "SB Live 5.1", |
746 | .id = "Live", | ||
747 | .emu10k1_chip = 1, | ||
748 | .ac97_chip = 1, | ||
749 | .sblive51 = 1} , | ||
750 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, | ||
751 | .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]", | ||
752 | .id = "Live", | ||
753 | .emu10k1_chip = 1, | ||
754 | .ac97_chip = 1, | ||
755 | .sblive51 = 1} , | ||
756 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102, | ||
757 | .driver = "EMU10K1", .name = "SBLive! Value [CT4850]", | ||
758 | .id = "Live", | ||
759 | .emu10k1_chip = 1, | ||
760 | .ac97_chip = 1, | ||
761 | .sblive51 = 1} , | ||
762 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, | ||
763 | .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]", | ||
764 | .id = "Live", | ||
685 | .emu10k1_chip = 1, | 765 | .emu10k1_chip = 1, |
686 | .ac97_chip = 1} , | 766 | .ac97_chip = 1} , |
767 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102, | ||
768 | .driver = "EMU10K1", .name = "SBLive! Value [CT4871]", | ||
769 | .id = "Live", | ||
770 | .emu10k1_chip = 1, | ||
771 | .ac97_chip = 1, | ||
772 | .sblive51 = 1} , | ||
773 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102, | ||
774 | .driver = "EMU10K1", .name = "SBLive! Value [CT4831]", | ||
775 | .id = "Live", | ||
776 | .emu10k1_chip = 1, | ||
777 | .ac97_chip = 1, | ||
778 | .sblive51 = 1} , | ||
779 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102, | ||
780 | .driver = "EMU10K1", .name = "SBLive! Value [CT4870]", | ||
781 | .id = "Live", | ||
782 | .emu10k1_chip = 1, | ||
783 | .ac97_chip = 1, | ||
784 | .sblive51 = 1} , | ||
785 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | ||
786 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102, | ||
787 | .driver = "EMU10K1", .name = "SBLive! Value [CT4832]", | ||
788 | .id = "Live", | ||
789 | .emu10k1_chip = 1, | ||
790 | .ac97_chip = 1, | ||
791 | .sblive51 = 1} , | ||
792 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102, | ||
793 | .driver = "EMU10K1", .name = "SBLive! Value [CT4830]", | ||
794 | .id = "Live", | ||
795 | .emu10k1_chip = 1, | ||
796 | .ac97_chip = 1, | ||
797 | .sblive51 = 1} , | ||
798 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102, | ||
799 | .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", | ||
800 | .id = "Live", | ||
801 | .emu10k1_chip = 1, | ||
802 | .ac97_chip = 1, | ||
803 | .sblive51 = 1} , | ||
804 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102, | ||
805 | .driver = "EMU10K1", .name = "SBLive! Value [CT4780]", | ||
806 | .id = "Live", | ||
807 | .emu10k1_chip = 1, | ||
808 | .ac97_chip = 1, | ||
809 | .sblive51 = 1} , | ||
810 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, | ||
811 | .driver = "EMU10K1", .name = "E-mu APS [4001]", | ||
812 | .id = "APS", | ||
813 | .emu10k1_chip = 1, | ||
814 | .ecard = 1} , | ||
815 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102, | ||
816 | .driver = "EMU10K1", .name = "SBLive! [CT4620]", | ||
817 | .id = "Live", | ||
818 | .emu10k1_chip = 1, | ||
819 | .ac97_chip = 1, | ||
820 | .sblive51 = 1} , | ||
821 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102, | ||
822 | .driver = "EMU10K1", .name = "SBLive! Value [CT4670]", | ||
823 | .id = "Live", | ||
824 | .emu10k1_chip = 1, | ||
825 | .ac97_chip = 1, | ||
826 | .sblive51 = 1} , | ||
687 | {.vendor = 0x1102, .device = 0x0002, | 827 | {.vendor = 0x1102, .device = 0x0002, |
688 | .driver = "EMU10K1", .name = "SB Live [Unknown]", | 828 | .driver = "EMU10K1", .name = "SB Live [Unknown]", |
829 | .id = "Live", | ||
689 | .emu10k1_chip = 1, | 830 | .emu10k1_chip = 1, |
690 | .ac97_chip = 1} , | 831 | .ac97_chip = 1, |
832 | .sblive51 = 1} , | ||
691 | { } /* terminator */ | 833 | { } /* terminator */ |
692 | }; | 834 | }; |
693 | 835 | ||
@@ -697,6 +839,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
697 | unsigned short extout_mask, | 839 | unsigned short extout_mask, |
698 | long max_cache_bytes, | 840 | long max_cache_bytes, |
699 | int enable_ir, | 841 | int enable_ir, |
842 | uint subsystem, | ||
700 | emu10k1_t ** remu) | 843 | emu10k1_t ** remu) |
701 | { | 844 | { |
702 | emu10k1_t *emu; | 845 | emu10k1_t *emu; |
@@ -738,13 +881,21 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
738 | emu->revision = revision; | 881 | emu->revision = revision; |
739 | pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); | 882 | pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); |
740 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model); | 883 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model); |
741 | emu->card_type = EMU10K1_CARD_CREATIVE; | ||
742 | snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model); | 884 | snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model); |
743 | 885 | ||
744 | for (c = emu_chip_details; c->vendor; c++) { | 886 | for (c = emu_chip_details; c->vendor; c++) { |
745 | if (c->vendor == pci->vendor && c->device == pci->device) { | 887 | if (c->vendor == pci->vendor && c->device == pci->device) { |
746 | if (c->subsystem == emu->serial) break; | 888 | if (subsystem) { |
747 | if (c->subsystem == 0) break; | 889 | if (c->subsystem && (c->subsystem == subsystem) ) { |
890 | break; | ||
891 | } else continue; | ||
892 | } else { | ||
893 | if (c->subsystem && (c->subsystem != emu->serial) ) | ||
894 | continue; | ||
895 | if (c->revision && c->revision != emu->revision) | ||
896 | continue; | ||
897 | } | ||
898 | break; | ||
748 | } | 899 | } |
749 | } | 900 | } |
750 | if (c->vendor == 0) { | 901 | if (c->vendor == 0) { |
@@ -754,11 +905,32 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
754 | return -ENOENT; | 905 | return -ENOENT; |
755 | } | 906 | } |
756 | emu->card_capabilities = c; | 907 | emu->card_capabilities = c; |
757 | if (c->subsystem != 0) | 908 | if (c->subsystem && !subsystem) |
758 | snd_printdd("Sound card name=%s\n", c->name); | 909 | snd_printdd("Sound card name=%s\n", c->name); |
759 | else | 910 | else if (subsystem) |
760 | snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial); | 911 | snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x. Forced to subsytem=0x%x\n", |
912 | c->name, pci->vendor, pci->device, emu->serial, c->subsystem); | ||
913 | else | ||
914 | snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x.\n", | ||
915 | c->name, pci->vendor, pci->device, emu->serial); | ||
761 | 916 | ||
917 | if (!*card->id && c->id) { | ||
918 | int i, n = 0; | ||
919 | strlcpy(card->id, c->id, sizeof(card->id)); | ||
920 | for (;;) { | ||
921 | for (i = 0; i < snd_ecards_limit; i++) { | ||
922 | if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id)) | ||
923 | break; | ||
924 | } | ||
925 | if (i >= snd_ecards_limit) | ||
926 | break; | ||
927 | n++; | ||
928 | if (n >= SNDRV_CARDS) | ||
929 | break; | ||
930 | snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n); | ||
931 | } | ||
932 | } | ||
933 | |||
762 | is_audigy = emu->audigy = c->emu10k2_chip; | 934 | is_audigy = emu->audigy = c->emu10k2_chip; |
763 | 935 | ||
764 | /* set the DMA transfer mask */ | 936 | /* set the DMA transfer mask */ |
@@ -816,15 +988,6 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
816 | 988 | ||
817 | pci_set_master(pci); | 989 | pci_set_master(pci); |
818 | 990 | ||
819 | if (c->ecard) { | ||
820 | emu->card_type = EMU10K1_CARD_EMUAPS; | ||
821 | emu->APS = 1; | ||
822 | } | ||
823 | if (! c->ac97_chip) | ||
824 | emu->no_ac97 = 1; | ||
825 | |||
826 | emu->spk71 = c->spk71; | ||
827 | |||
828 | emu->fx8010.fxbus_mask = 0x303f; | 991 | emu->fx8010.fxbus_mask = 0x303f; |
829 | if (extin_mask == 0) | 992 | if (extin_mask == 0) |
830 | extin_mask = 0x3fcf; | 993 | extin_mask = 0x3fcf; |
@@ -833,7 +996,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
833 | emu->fx8010.extin_mask = extin_mask; | 996 | emu->fx8010.extin_mask = extin_mask; |
834 | emu->fx8010.extout_mask = extout_mask; | 997 | emu->fx8010.extout_mask = extout_mask; |
835 | 998 | ||
836 | if (emu->APS) { | 999 | if (emu->card_capabilities->ecard) { |
837 | if ((err = snd_emu10k1_ecard_init(emu)) < 0) { | 1000 | if ((err = snd_emu10k1_ecard_init(emu)) < 0) { |
838 | snd_emu10k1_free(emu); | 1001 | snd_emu10k1_free(emu); |
839 | return err; | 1002 | return err; |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 27dfd8ddddf4..e90c5ddd1d17 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -361,10 +361,7 @@ static void snd_emu10k1x_gpio_write(emu10k1x_t *emu, unsigned int value) | |||
361 | 361 | ||
362 | static void snd_emu10k1x_pcm_free_substream(snd_pcm_runtime_t *runtime) | 362 | static void snd_emu10k1x_pcm_free_substream(snd_pcm_runtime_t *runtime) |
363 | { | 363 | { |
364 | emu10k1x_pcm_t *epcm = runtime->private_data; | 364 | kfree(runtime->private_data); |
365 | |||
366 | if (epcm) | ||
367 | kfree(epcm); | ||
368 | } | 365 | } |
369 | 366 | ||
370 | static void snd_emu10k1x_pcm_interrupt(emu10k1x_t *emu, emu10k1x_voice_t *voice) | 367 | static void snd_emu10k1x_pcm_interrupt(emu10k1x_t *emu, emu10k1x_voice_t *voice) |
@@ -1075,6 +1072,7 @@ static int __devinit snd_emu10k1x_proc_init(emu10k1x_t * emu) | |||
1075 | snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read); | 1072 | snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read); |
1076 | entry->c.text.write_size = 64; | 1073 | entry->c.text.write_size = 64; |
1077 | entry->c.text.write = snd_emu10k1x_proc_reg_write; | 1074 | entry->c.text.write = snd_emu10k1x_proc_reg_write; |
1075 | entry->mode |= S_IWUSR; | ||
1078 | entry->private_data = emu; | 1076 | entry->private_data = emu; |
1079 | } | 1077 | } |
1080 | 1078 | ||
@@ -1627,7 +1625,7 @@ static int __init alsa_card_emu10k1x_init(void) | |||
1627 | { | 1625 | { |
1628 | int err; | 1626 | int err; |
1629 | 1627 | ||
1630 | if ((err = pci_module_init(&driver)) > 0) | 1628 | if ((err = pci_register_driver(&driver)) > 0) |
1631 | return err; | 1629 | return err; |
1632 | 1630 | ||
1633 | return 0; | 1631 | return 0; |
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index b9fa2e887fee..0529fb281125 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -1077,7 +1077,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu) | |||
1077 | gpr += 2; | 1077 | gpr += 2; |
1078 | 1078 | ||
1079 | /* PCM Side Playback (independent from stereo mix) */ | 1079 | /* PCM Side Playback (independent from stereo mix) */ |
1080 | if (emu->spk71) { | 1080 | if (emu->card_capabilities->spk71) { |
1081 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE)); | 1081 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE)); |
1082 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE)); | 1082 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE)); |
1083 | snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100); | 1083 | snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100); |
@@ -1145,14 +1145,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1145 | A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L); | 1145 | A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L); |
1146 | A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R); | 1146 | A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R); |
1147 | snd_emu10k1_init_stereo_control(&controls[nctl++], | 1147 | snd_emu10k1_init_stereo_control(&controls[nctl++], |
1148 | emu->no_ac97 ? "CD Playback Volume" : "Audigy CD Playback Volume", | 1148 | emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume", |
1149 | gpr, 0); | 1149 | gpr, 0); |
1150 | gpr += 2; | 1150 | gpr += 2; |
1151 | /* Audigy CD Capture Volume */ | 1151 | /* Audigy CD Capture Volume */ |
1152 | A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L); | 1152 | A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L); |
1153 | A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R); | 1153 | A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R); |
1154 | snd_emu10k1_init_stereo_control(&controls[nctl++], | 1154 | snd_emu10k1_init_stereo_control(&controls[nctl++], |
1155 | emu->no_ac97 ? "CD Capture Volume" : "Audigy CD Capture Volume", | 1155 | emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume", |
1156 | gpr, 0); | 1156 | gpr, 0); |
1157 | gpr += 2; | 1157 | gpr += 2; |
1158 | 1158 | ||
@@ -1171,14 +1171,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1171 | A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L); | 1171 | A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L); |
1172 | A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R); | 1172 | A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R); |
1173 | snd_emu10k1_init_stereo_control(&controls[nctl++], | 1173 | snd_emu10k1_init_stereo_control(&controls[nctl++], |
1174 | emu->no_ac97 ? "Line Playback Volume" : "Line2 Playback Volume", | 1174 | emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume", |
1175 | gpr, 0); | 1175 | gpr, 0); |
1176 | gpr += 2; | 1176 | gpr += 2; |
1177 | /* Line2 Capture Volume */ | 1177 | /* Line2 Capture Volume */ |
1178 | A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L); | 1178 | A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L); |
1179 | A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R); | 1179 | A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R); |
1180 | snd_emu10k1_init_stereo_control(&controls[nctl++], | 1180 | snd_emu10k1_init_stereo_control(&controls[nctl++], |
1181 | emu->no_ac97 ? "Line Capture Volume" : "Line2 Capture Volume", | 1181 | emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume", |
1182 | gpr, 0); | 1182 | gpr, 0); |
1183 | gpr += 2; | 1183 | gpr += 2; |
1184 | 1184 | ||
@@ -1197,14 +1197,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1197 | A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L); | 1197 | A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L); |
1198 | A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R); | 1198 | A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R); |
1199 | snd_emu10k1_init_stereo_control(&controls[nctl++], | 1199 | snd_emu10k1_init_stereo_control(&controls[nctl++], |
1200 | emu->no_ac97 ? "Aux Playback Volume" : "Aux2 Playback Volume", | 1200 | emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume", |
1201 | gpr, 0); | 1201 | gpr, 0); |
1202 | gpr += 2; | 1202 | gpr += 2; |
1203 | /* Aux2 Capture Volume */ | 1203 | /* Aux2 Capture Volume */ |
1204 | A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L); | 1204 | A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L); |
1205 | A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R); | 1205 | A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R); |
1206 | snd_emu10k1_init_stereo_control(&controls[nctl++], | 1206 | snd_emu10k1_init_stereo_control(&controls[nctl++], |
1207 | emu->no_ac97 ? "Aux Capture Volume" : "Aux2 Capture Volume", | 1207 | emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume", |
1208 | gpr, 0); | 1208 | gpr, 0); |
1209 | gpr += 2; | 1209 | gpr += 2; |
1210 | 1210 | ||
@@ -1232,7 +1232,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1232 | snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0); | 1232 | snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0); |
1233 | gpr++; | 1233 | gpr++; |
1234 | 1234 | ||
1235 | if (emu->spk71) { | 1235 | if (emu->card_capabilities->spk71) { |
1236 | /* Stereo Mix Side Playback */ | 1236 | /* Stereo Mix Side Playback */ |
1237 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix)); | 1237 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix)); |
1238 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1)); | 1238 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1)); |
@@ -1266,7 +1266,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1266 | A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */ | 1266 | A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */ |
1267 | A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */ | 1267 | A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */ |
1268 | A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */ | 1268 | A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */ |
1269 | if (emu->spk71) { | 1269 | if (emu->card_capabilities->spk71) { |
1270 | A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */ | 1270 | A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */ |
1271 | A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */ | 1271 | A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */ |
1272 | } | 1272 | } |
@@ -1359,7 +1359,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1359 | A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS); | 1359 | A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS); |
1360 | A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS); | 1360 | A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS); |
1361 | A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS); | 1361 | A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS); |
1362 | if (emu->spk71) | 1362 | if (emu->card_capabilities->spk71) |
1363 | A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS); | 1363 | A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS); |
1364 | 1364 | ||
1365 | /* headphone */ | 1365 | /* headphone */ |
@@ -1982,22 +1982,27 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu) | |||
1982 | OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000); | 1982 | OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000); |
1983 | 1983 | ||
1984 | /* EFX capture - capture the 16 EXTINS */ | 1984 | /* EFX capture - capture the 16 EXTINS */ |
1985 | OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0)); | 1985 | if (emu->card_capabilities->sblive51) { |
1986 | OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1)); | 1986 | /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER |
1987 | OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2)); | 1987 | * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording. |
1988 | OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3)); | 1988 | * |
1989 | /* Dont connect anything to FXBUS2 1 and 2. These are shared with | 1989 | * Since only 14 of the 16 EXTINs are used, this is not a big problem. |
1990 | * Center/LFE on the SBLive 5.1. The kX driver only changes the | 1990 | * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture |
1991 | * routing when it detects an SBLive 5.1. | 1991 | * 0 and 3, then the rest of the EXTINs to the corresponding FX capture |
1992 | * | 1992 | * channel. Multitrack recorders will still see the center/lfe output signal |
1993 | * Since only 14 of the 16 EXTINs are used, this is not a big problem. | 1993 | * on the second and third channels. |
1994 | * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture | 1994 | */ |
1995 | * 0 and 3, then the rest of the EXTINs to the corresponding FX capture | 1995 | OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0)); |
1996 | * channel. | 1996 | OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1)); |
1997 | */ | 1997 | OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2)); |
1998 | for (z = 4; z < 14; z++) { | 1998 | OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3)); |
1999 | OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z)); | 1999 | for (z = 4; z < 14; z++) |
2000 | OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z)); | ||
2001 | } else { | ||
2002 | for (z = 0; z < 16; z++) | ||
2003 | OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z)); | ||
2000 | } | 2004 | } |
2005 | |||
2001 | 2006 | ||
2002 | if (gpr > tmp) { | 2007 | if (gpr > tmp) { |
2003 | snd_BUG(); | 2008 | snd_BUG(); |
@@ -2128,7 +2133,6 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info) | |||
2128 | int res; | 2133 | int res; |
2129 | 2134 | ||
2130 | memset(info, 0, sizeof(info)); | 2135 | memset(info, 0, sizeof(info)); |
2131 | info->card = emu->card_type; | ||
2132 | info->internal_tram_size = emu->fx8010.itram_size; | 2136 | info->internal_tram_size = emu->fx8010.itram_size; |
2133 | info->external_tram_size = emu->fx8010.etram_pages.bytes / 2; | 2137 | info->external_tram_size = emu->fx8010.etram_pages.bytes / 2; |
2134 | fxbus = fxbuses; | 2138 | fxbus = fxbuses; |
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 044663d31aa7..6be82c5fe138 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c | |||
@@ -68,6 +68,7 @@ static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol, | |||
68 | return 0; | 68 | return 0; |
69 | } | 69 | } |
70 | 70 | ||
71 | #if 0 | ||
71 | static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) | 72 | static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) |
72 | { | 73 | { |
73 | static char *texts[] = {"44100", "48000", "96000"}; | 74 | static char *texts[] = {"44100", "48000", "96000"}; |
@@ -152,6 +153,7 @@ static snd_kcontrol_new_t snd_audigy_spdif_output_rate = | |||
152 | .get = snd_audigy_spdif_output_rate_get, | 153 | .get = snd_audigy_spdif_output_rate_get, |
153 | .put = snd_audigy_spdif_output_rate_put | 154 | .put = snd_audigy_spdif_output_rate_put |
154 | }; | 155 | }; |
156 | #endif | ||
155 | 157 | ||
156 | static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol, | 158 | static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol, |
157 | snd_ctl_elem_value_t * ucontrol) | 159 | snd_ctl_elem_value_t * ucontrol) |
@@ -791,7 +793,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) | |||
791 | NULL | 793 | NULL |
792 | }; | 794 | }; |
793 | 795 | ||
794 | if (!emu->no_ac97) { | 796 | if (emu->card_capabilities->ac97_chip) { |
795 | ac97_bus_t *pbus; | 797 | ac97_bus_t *pbus; |
796 | ac97_template_t ac97; | 798 | ac97_template_t ac97; |
797 | static ac97_bus_ops_t ops = { | 799 | static ac97_bus_ops_t ops = { |
@@ -833,7 +835,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) | |||
833 | for (; *c; c++) | 835 | for (; *c; c++) |
834 | remove_ctl(card, *c); | 836 | remove_ctl(card, *c); |
835 | } else { | 837 | } else { |
836 | if (emu->APS) | 838 | if (emu->card_capabilities->ecard) |
837 | strcpy(emu->card->mixername, "EMU APS"); | 839 | strcpy(emu->card->mixername, "EMU APS"); |
838 | else if (emu->audigy) | 840 | else if (emu->audigy) |
839 | strcpy(emu->card->mixername, "SB Audigy"); | 841 | strcpy(emu->card->mixername, "SB Audigy"); |
@@ -918,7 +920,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) | |||
918 | mix->attn[0] = 0xffff; | 920 | mix->attn[0] = 0xffff; |
919 | } | 921 | } |
920 | 922 | ||
921 | if (! emu->APS) { /* FIXME: APS has these controls? */ | 923 | if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */ |
922 | /* sb live! and audigy */ | 924 | /* sb live! and audigy */ |
923 | if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL) | 925 | if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL) |
924 | return -ENOMEM; | 926 | return -ENOMEM; |
@@ -935,18 +937,20 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu) | |||
935 | return -ENOMEM; | 937 | return -ENOMEM; |
936 | if ((err = snd_ctl_add(card, kctl))) | 938 | if ((err = snd_ctl_add(card, kctl))) |
937 | return err; | 939 | return err; |
940 | #if 0 | ||
938 | if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL) | 941 | if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL) |
939 | return -ENOMEM; | 942 | return -ENOMEM; |
940 | if ((err = snd_ctl_add(card, kctl))) | 943 | if ((err = snd_ctl_add(card, kctl))) |
941 | return err; | 944 | return err; |
942 | } else if (! emu->APS) { | 945 | #endif |
946 | } else if (! emu->card_capabilities->ecard) { | ||
943 | /* sb live! */ | 947 | /* sb live! */ |
944 | if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL) | 948 | if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL) |
945 | return -ENOMEM; | 949 | return -ENOMEM; |
946 | if ((err = snd_ctl_add(card, kctl))) | 950 | if ((err = snd_ctl_add(card, kctl))) |
947 | return err; | 951 | return err; |
948 | } | 952 | } |
949 | if (emu->audigy && emu->revision == 4) { /* P16V */ | 953 | if (emu->card_capabilities->ca0151_chip) { /* P16V */ |
950 | if ((err = snd_p16v_mixer(emu))) | 954 | if ((err = snd_p16v_mixer(emu))) |
951 | return err; | 955 | return err; |
952 | } | 956 | } |
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index d1c2a02c486b..520b99af5f55 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
@@ -262,7 +262,7 @@ static unsigned int emu10k1_select_interprom(unsigned int pitch_target) | |||
262 | * | 262 | * |
263 | * returns: cache invalidate size in samples | 263 | * returns: cache invalidate size in samples |
264 | */ | 264 | */ |
265 | static int inline emu10k1_ccis(int stereo, int w_16) | 265 | static inline int emu10k1_ccis(int stereo, int w_16) |
266 | { | 266 | { |
267 | if (w_16) { | 267 | if (w_16) { |
268 | return stereo ? 24 : 26; | 268 | return stereo ? 24 : 26; |
@@ -991,9 +991,7 @@ static void snd_emu10k1_pcm_efx_mixer_notify(emu10k1_t *emu, int idx, int activa | |||
991 | 991 | ||
992 | static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime) | 992 | static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime) |
993 | { | 993 | { |
994 | emu10k1_pcm_t *epcm = runtime->private_data; | 994 | kfree(runtime->private_data); |
995 | |||
996 | kfree(epcm); | ||
997 | } | 995 | } |
998 | 996 | ||
999 | static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream) | 997 | static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream) |
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index d990d5eb45a8..cc22707c91fa 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/emu10k1.h> | 32 | #include <sound/emu10k1.h> |
33 | #include "p16v.h" | ||
33 | 34 | ||
34 | static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu, | 35 | static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu, |
35 | snd_info_buffer_t * buffer, | 36 | snd_info_buffer_t * buffer, |
@@ -44,28 +45,34 @@ static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu, | |||
44 | unsigned int status, rate = 0; | 45 | unsigned int status, rate = 0; |
45 | 46 | ||
46 | status = snd_emu10k1_ptr_read(emu, status_reg, 0); | 47 | status = snd_emu10k1_ptr_read(emu, status_reg, 0); |
47 | if (rate_reg > 0) | ||
48 | rate = snd_emu10k1_ptr_read(emu, rate_reg, 0); | ||
49 | 48 | ||
50 | snd_iprintf(buffer, "\n%s\n", title); | 49 | snd_iprintf(buffer, "\n%s\n", title); |
51 | 50 | ||
52 | snd_iprintf(buffer, "Professional Mode : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no"); | 51 | if (status != 0xffffffff) { |
53 | snd_iprintf(buffer, "Not Audio Data : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no"); | 52 | snd_iprintf(buffer, "Professional Mode : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no"); |
54 | snd_iprintf(buffer, "Copyright : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no"); | 53 | snd_iprintf(buffer, "Not Audio Data : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no"); |
55 | snd_iprintf(buffer, "Emphasis : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]); | 54 | snd_iprintf(buffer, "Copyright : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no"); |
56 | snd_iprintf(buffer, "Mode : %i\n", (status & SPCS_MODEMASK) >> 6); | 55 | snd_iprintf(buffer, "Emphasis : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]); |
57 | snd_iprintf(buffer, "Category Code : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8); | 56 | snd_iprintf(buffer, "Mode : %i\n", (status & SPCS_MODEMASK) >> 6); |
58 | snd_iprintf(buffer, "Generation Status : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy"); | 57 | snd_iprintf(buffer, "Category Code : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8); |
59 | snd_iprintf(buffer, "Source Mask : %i\n", (status & SPCS_SOURCENUMMASK) >> 16); | 58 | snd_iprintf(buffer, "Generation Status : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy"); |
60 | snd_iprintf(buffer, "Channel Number : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]); | 59 | snd_iprintf(buffer, "Source Mask : %i\n", (status & SPCS_SOURCENUMMASK) >> 16); |
61 | snd_iprintf(buffer, "Sample Rate : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]); | 60 | snd_iprintf(buffer, "Channel Number : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]); |
62 | snd_iprintf(buffer, "Clock Accuracy : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]); | 61 | snd_iprintf(buffer, "Sample Rate : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]); |
63 | 62 | snd_iprintf(buffer, "Clock Accuracy : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]); | |
64 | if (rate_reg > 0) { | 63 | |
65 | snd_iprintf(buffer, "S/PDIF Locked : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off"); | 64 | if (rate_reg > 0) { |
66 | snd_iprintf(buffer, "Rate Locked : %s\n", rate & SRCS_RATELOCKED ? "on" : "off"); | 65 | rate = snd_emu10k1_ptr_read(emu, rate_reg, 0); |
67 | snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", rate & SRCS_ESTSAMPLERATE); | 66 | snd_iprintf(buffer, "S/PDIF Valid : %s\n", rate & SRCS_SPDIFVALID ? "on" : "off"); |
67 | snd_iprintf(buffer, "S/PDIF Locked : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off"); | ||
68 | snd_iprintf(buffer, "Rate Locked : %s\n", rate & SRCS_RATELOCKED ? "on" : "off"); | ||
69 | /* From ((Rate * 48000 ) / 262144); */ | ||
70 | snd_iprintf(buffer, "Estimated Sample Rate : %d\n", ((rate & 0xFFFFF ) * 375) >> 11); | ||
71 | } | ||
72 | } else { | ||
73 | snd_iprintf(buffer, "No signal detected.\n"); | ||
68 | } | 74 | } |
75 | |||
69 | } | 76 | } |
70 | 77 | ||
71 | static void snd_emu10k1_proc_read(snd_info_entry_t *entry, | 78 | static void snd_emu10k1_proc_read(snd_info_entry_t *entry, |
@@ -182,7 +189,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry, | |||
182 | 189 | ||
183 | snd_iprintf(buffer, "EMU10K1\n\n"); | 190 | snd_iprintf(buffer, "EMU10K1\n\n"); |
184 | snd_iprintf(buffer, "Card : %s\n", | 191 | snd_iprintf(buffer, "Card : %s\n", |
185 | emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative")); | 192 | emu->audigy ? "Audigy" : (emu->card_capabilities->ecard ? "EMU APS" : "Creative")); |
186 | snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size); | 193 | snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size); |
187 | snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2); | 194 | snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2); |
188 | snd_iprintf(buffer, "\n"); | 195 | snd_iprintf(buffer, "\n"); |
@@ -223,15 +230,35 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry, | |||
223 | snd_iprintf(buffer, "\nAll FX Outputs :\n"); | 230 | snd_iprintf(buffer, "\nAll FX Outputs :\n"); |
224 | for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++) | 231 | for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++) |
225 | snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]); | 232 | snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]); |
226 | snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 0", SPCS0, -1); | 233 | } |
227 | snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 1", SPCS1, -1); | 234 | |
228 | snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 2/3", SPCS2, -1); | 235 | static void snd_emu10k1_proc_spdif_read(snd_info_entry_t *entry, |
229 | snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF", CDCS, CDSRCS); | 236 | snd_info_buffer_t * buffer) |
230 | snd_emu10k1_proc_spdif_status(emu, buffer, "General purpose S/PDIF", GPSCS, GPSRCS); | 237 | { |
238 | emu10k1_t *emu = entry->private_data; | ||
239 | snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS); | ||
240 | snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS); | ||
241 | #if 0 | ||
231 | val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0); | 242 | val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0); |
232 | snd_iprintf(buffer, "\nZoomed Video\n"); | 243 | snd_iprintf(buffer, "\nZoomed Video\n"); |
233 | snd_iprintf(buffer, "Rate Locked : %s\n", val & SRCS_RATELOCKED ? "on" : "off"); | 244 | snd_iprintf(buffer, "Rate Locked : %s\n", val & SRCS_RATELOCKED ? "on" : "off"); |
234 | snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", val & SRCS_ESTSAMPLERATE); | 245 | snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", val & SRCS_ESTSAMPLERATE); |
246 | #endif | ||
247 | } | ||
248 | |||
249 | static void snd_emu10k1_proc_rates_read(snd_info_entry_t *entry, | ||
250 | snd_info_buffer_t * buffer) | ||
251 | { | ||
252 | static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 }; | ||
253 | emu10k1_t *emu = entry->private_data; | ||
254 | unsigned int val, tmp, n; | ||
255 | val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0); | ||
256 | tmp = (val >> 16) & 0x8; | ||
257 | for (n=0;n<4;n++) { | ||
258 | tmp = val >> (16 + (n*4)); | ||
259 | if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]); | ||
260 | else snd_iprintf(buffer, "Channel %d: No input\n", n); | ||
261 | } | ||
235 | } | 262 | } |
236 | 263 | ||
237 | static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry, | 264 | static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry, |
@@ -500,32 +527,46 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu) | |||
500 | snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read); | 527 | snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read); |
501 | entry->c.text.write_size = 64; | 528 | entry->c.text.write_size = 64; |
502 | entry->c.text.write = snd_emu_proc_io_reg_write; | 529 | entry->c.text.write = snd_emu_proc_io_reg_write; |
530 | entry->mode |= S_IWUSR; | ||
503 | } | 531 | } |
504 | if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { | 532 | if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { |
505 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a); | 533 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a); |
506 | entry->c.text.write_size = 64; | 534 | entry->c.text.write_size = 64; |
507 | entry->c.text.write = snd_emu_proc_ptr_reg_write00; | 535 | entry->c.text.write = snd_emu_proc_ptr_reg_write00; |
536 | entry->mode |= S_IWUSR; | ||
508 | } | 537 | } |
509 | if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { | 538 | if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { |
510 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b); | 539 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b); |
511 | entry->c.text.write_size = 64; | 540 | entry->c.text.write_size = 64; |
512 | entry->c.text.write = snd_emu_proc_ptr_reg_write00; | 541 | entry->c.text.write = snd_emu_proc_ptr_reg_write00; |
542 | entry->mode |= S_IWUSR; | ||
513 | } | 543 | } |
514 | if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { | 544 | if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { |
515 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a); | 545 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a); |
516 | entry->c.text.write_size = 64; | 546 | entry->c.text.write_size = 64; |
517 | entry->c.text.write = snd_emu_proc_ptr_reg_write20; | 547 | entry->c.text.write = snd_emu_proc_ptr_reg_write20; |
548 | entry->mode |= S_IWUSR; | ||
518 | } | 549 | } |
519 | if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { | 550 | if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { |
520 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b); | 551 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b); |
521 | entry->c.text.write_size = 64; | 552 | entry->c.text.write_size = 64; |
522 | entry->c.text.write = snd_emu_proc_ptr_reg_write20; | 553 | entry->c.text.write = snd_emu_proc_ptr_reg_write20; |
554 | entry->mode |= S_IWUSR; | ||
523 | } | 555 | } |
524 | #endif | 556 | #endif |
525 | 557 | ||
526 | if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) | 558 | if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) |
527 | snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read); | 559 | snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read); |
528 | 560 | ||
561 | if (emu->card_capabilities->emu10k2_chip) { | ||
562 | if (! snd_card_proc_new(emu->card, "spdif-in", &entry)) | ||
563 | snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_spdif_read); | ||
564 | } | ||
565 | if (emu->card_capabilities->ca0151_chip) { | ||
566 | if (! snd_card_proc_new(emu->card, "capture-rates", &entry)) | ||
567 | snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_rates_read); | ||
568 | } | ||
569 | |||
529 | if (! snd_card_proc_new(emu->card, "voices", &entry)) | 570 | if (! snd_card_proc_new(emu->card, "voices", &entry)) |
530 | snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read); | 571 | snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read); |
531 | 572 | ||
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c index b81a7cafff39..cd8460d56752 100644 --- a/sound/pci/emu10k1/irq.c +++ b/sound/pci/emu10k1/irq.c | |||
@@ -37,7 +37,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
37 | int handled = 0; | 37 | int handled = 0; |
38 | 38 | ||
39 | while ((status = inl(emu->port + IPR)) != 0) { | 39 | while ((status = inl(emu->port + IPR)) != 0) { |
40 | // printk("irq - status = 0x%x\n", status); | 40 | //printk("emu10k1 irq - status = 0x%x\n", status); |
41 | orig_status = status; | 41 | orig_status = status; |
42 | handled = 1; | 42 | handled = 1; |
43 | if (status & IPR_PCIERROR) { | 43 | if (status & IPR_PCIERROR) { |
@@ -147,9 +147,36 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
147 | snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE); | 147 | snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE); |
148 | status &= ~IPR_FXDSP; | 148 | status &= ~IPR_FXDSP; |
149 | } | 149 | } |
150 | if (status & IPR_P16V) { | ||
151 | while ((status2 = inl(emu->port + IPR2)) != 0) { | ||
152 | u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ | ||
153 | emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]); | ||
154 | emu10k1_voice_t *cvoice = &(emu->p16v_capture_voice); | ||
155 | |||
156 | //printk(KERN_INFO "status2=0x%x\n", status2); | ||
157 | orig_status2 = status2; | ||
158 | if(status2 & mask) { | ||
159 | if(pvoice->use) { | ||
160 | snd_pcm_period_elapsed(pvoice->epcm->substream); | ||
161 | } else { | ||
162 | snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use); | ||
163 | } | ||
164 | } | ||
165 | if(status2 & 0x110000) { | ||
166 | //printk(KERN_INFO "capture int found\n"); | ||
167 | if(cvoice->use) { | ||
168 | //printk(KERN_INFO "capture period_elapsed\n"); | ||
169 | snd_pcm_period_elapsed(cvoice->epcm->substream); | ||
170 | } | ||
171 | } | ||
172 | outl(orig_status2, emu->port + IPR2); /* ack all */ | ||
173 | } | ||
174 | status &= ~IPR_P16V; | ||
175 | } | ||
176 | |||
150 | if (status) { | 177 | if (status) { |
151 | unsigned int bits; | 178 | unsigned int bits; |
152 | //snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status); | 179 | snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status); |
153 | //make sure any interrupts we don't handle are disabled: | 180 | //make sure any interrupts we don't handle are disabled: |
154 | bits = INTE_FXDSPENABLE | | 181 | bits = INTE_FXDSPENABLE | |
155 | INTE_PCIERRORENABLE | | 182 | INTE_PCIERRORENABLE | |
@@ -170,20 +197,5 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
170 | } | 197 | } |
171 | outl(orig_status, emu->port + IPR); /* ack all */ | 198 | outl(orig_status, emu->port + IPR); /* ack all */ |
172 | } | 199 | } |
173 | if (emu->audigy && emu->revision == 4) { /* P16V */ | ||
174 | while ((status2 = inl(emu->port + IPR2)) != 0) { | ||
175 | u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */ | ||
176 | emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]); | ||
177 | orig_status2 = status2; | ||
178 | if(status2 & mask) { | ||
179 | if(pvoice->use) { | ||
180 | snd_pcm_period_elapsed(pvoice->epcm->substream); | ||
181 | } else { | ||
182 | snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use); | ||
183 | } | ||
184 | } | ||
185 | outl(orig_status2, emu->port + IPR2); /* ack all */ | ||
186 | } | ||
187 | } | ||
188 | return IRQ_RETVAL(handled); | 200 | return IRQ_RETVAL(handled); |
189 | } | 201 | } |
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 7a595f0dd7a1..6afeaeab3e13 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c | |||
@@ -495,7 +495,7 @@ static int synth_free_pages(emu10k1_t *emu, emu10k1_memblk_t *blk) | |||
495 | } | 495 | } |
496 | 496 | ||
497 | /* calculate buffer pointer from offset address */ | 497 | /* calculate buffer pointer from offset address */ |
498 | inline static void *offset_ptr(emu10k1_t *emu, int page, int offset) | 498 | static inline void *offset_ptr(emu10k1_t *emu, int page, int offset) |
499 | { | 499 | { |
500 | char *ptr; | 500 | char *ptr; |
501 | snd_assert(page >= 0 && page < emu->max_cache_pages, return NULL); | 501 | snd_assert(page >= 0 && page < emu->max_cache_pages, return NULL); |
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index d03cb2fefc9e..a1691330d3b6 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver p16v chips | 3 | * Driver p16v chips |
4 | * Version: 0.22 | 4 | * Version: 0.25 |
5 | * | 5 | * |
6 | * FEATURES currently supported: | 6 | * FEATURES currently supported: |
7 | * Output fixed at S32_LE, 2 channel to hw:0,0 | 7 | * Output fixed at S32_LE, 2 channel to hw:0,0 |
@@ -41,7 +41,15 @@ | |||
41 | * Integrated with snd-emu10k1 driver. | 41 | * Integrated with snd-emu10k1 driver. |
42 | * 0.22 | 42 | * 0.22 |
43 | * Removed #if 0 ... #endif | 43 | * Removed #if 0 ... #endif |
44 | * | 44 | * 0.23 |
45 | * Implement different capture rates. | ||
46 | * 0.24 | ||
47 | * Implement different capture source channels. | ||
48 | * e.g. When HD Capture source is set to SPDIF, | ||
49 | * setting HD Capture channel to 0 captures from CDROM digital input. | ||
50 | * setting HD Capture channel to 1 captures from SPDIF in. | ||
51 | * 0.25 | ||
52 | * Include capture buffer sizes. | ||
45 | * | 53 | * |
46 | * BUGS: | 54 | * BUGS: |
47 | * Some stability problems when unloading the snd-p16v kernel module. | 55 | * Some stability problems when unloading the snd-p16v kernel module. |
@@ -119,22 +127,41 @@ static snd_pcm_hardware_t snd_p16v_playback_hw = { | |||
119 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 127 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
120 | SNDRV_PCM_INFO_MMAP_VALID), | 128 | SNDRV_PCM_INFO_MMAP_VALID), |
121 | .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */ | 129 | .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */ |
122 | .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 , | 130 | .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, |
123 | .rate_min = 48000, | 131 | .rate_min = 44100, |
124 | .rate_max = 192000, | 132 | .rate_max = 192000, |
125 | .channels_min = 8, | 133 | .channels_min = 8, |
126 | .channels_max = 8, | 134 | .channels_max = 8, |
127 | .buffer_bytes_max = (32*1024), | 135 | .buffer_bytes_max = ((65536 - 64) * 8), |
128 | .period_bytes_min = 64, | 136 | .period_bytes_min = 64, |
129 | .period_bytes_max = (16*1024), | 137 | .period_bytes_max = (65536 - 64), |
130 | .periods_min = 2, | 138 | .periods_min = 2, |
131 | .periods_max = 8, | 139 | .periods_max = 8, |
132 | .fifo_size = 0, | 140 | .fifo_size = 0, |
133 | }; | 141 | }; |
134 | 142 | ||
143 | static snd_pcm_hardware_t snd_p16v_capture_hw = { | ||
144 | .info = (SNDRV_PCM_INFO_MMAP | | ||
145 | SNDRV_PCM_INFO_INTERLEAVED | | ||
146 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
147 | SNDRV_PCM_INFO_MMAP_VALID), | ||
148 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
149 | .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, | ||
150 | .rate_min = 44100, | ||
151 | .rate_max = 192000, | ||
152 | .channels_min = 2, | ||
153 | .channels_max = 2, | ||
154 | .buffer_bytes_max = (65536 - 64), | ||
155 | .period_bytes_min = 64, | ||
156 | .period_bytes_max = (65536 - 128) >> 1, /* size has to be N*64 bytes */ | ||
157 | .periods_min = 2, | ||
158 | .periods_max = 2, | ||
159 | .fifo_size = 0, | ||
160 | }; | ||
161 | |||
135 | static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime) | 162 | static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime) |
136 | { | 163 | { |
137 | snd_pcm_t *epcm = runtime->private_data; | 164 | emu10k1_pcm_t *epcm = runtime->private_data; |
138 | 165 | ||
139 | if (epcm) { | 166 | if (epcm) { |
140 | //snd_printk("epcm free: %p\n", epcm); | 167 | //snd_printk("epcm free: %p\n", epcm); |
@@ -178,15 +205,63 @@ static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, in | |||
178 | 205 | ||
179 | return 0; | 206 | return 0; |
180 | } | 207 | } |
208 | /* open_capture callback */ | ||
209 | static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int channel_id) | ||
210 | { | ||
211 | emu10k1_t *emu = snd_pcm_substream_chip(substream); | ||
212 | emu10k1_voice_t *channel = &(emu->p16v_capture_voice); | ||
213 | emu10k1_pcm_t *epcm; | ||
214 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
215 | int err; | ||
216 | |||
217 | epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL); | ||
218 | //snd_printk("epcm kcalloc: %p\n", epcm); | ||
219 | |||
220 | if (epcm == NULL) | ||
221 | return -ENOMEM; | ||
222 | epcm->emu = emu; | ||
223 | epcm->substream = substream; | ||
224 | //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id); | ||
225 | |||
226 | runtime->private_data = epcm; | ||
227 | runtime->private_free = snd_p16v_pcm_free_substream; | ||
228 | |||
229 | runtime->hw = snd_p16v_capture_hw; | ||
230 | |||
231 | channel->emu = emu; | ||
232 | channel->number = channel_id; | ||
233 | |||
234 | channel->use=1; | ||
235 | //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use); | ||
236 | //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel); | ||
237 | //channel->interrupt = snd_p16v_pcm_channel_interrupt; | ||
238 | channel->epcm=epcm; | ||
239 | if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) | ||
240 | return err; | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
181 | 245 | ||
182 | /* close callback */ | 246 | /* close callback */ |
183 | static int snd_p16v_pcm_close_playback(snd_pcm_substream_t *substream) | 247 | static int snd_p16v_pcm_close_playback(snd_pcm_substream_t *substream) |
184 | { | 248 | { |
185 | emu10k1_t *emu = snd_pcm_substream_chip(substream); | 249 | emu10k1_t *emu = snd_pcm_substream_chip(substream); |
186 | //snd_pcm_runtime_t *runtime = substream->runtime; | 250 | //snd_pcm_runtime_t *runtime = substream->runtime; |
187 | //emu10k1_pcm_t *epcm = runtime->private_data; | 251 | //emu10k1_pcm_t *epcm = runtime->private_data; |
188 | emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0; | 252 | emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0; |
189 | /* FIXME: maybe zero others */ | 253 | /* FIXME: maybe zero others */ |
254 | return 0; | ||
255 | } | ||
256 | |||
257 | /* close callback */ | ||
258 | static int snd_p16v_pcm_close_capture(snd_pcm_substream_t *substream) | ||
259 | { | ||
260 | emu10k1_t *emu = snd_pcm_substream_chip(substream); | ||
261 | //snd_pcm_runtime_t *runtime = substream->runtime; | ||
262 | //emu10k1_pcm_t *epcm = runtime->private_data; | ||
263 | emu->p16v_capture_voice.use=0; | ||
264 | /* FIXME: maybe zero others */ | ||
190 | return 0; | 265 | return 0; |
191 | } | 266 | } |
192 | 267 | ||
@@ -195,36 +270,55 @@ static int snd_p16v_pcm_open_playback_front(snd_pcm_substream_t *substream) | |||
195 | return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL); | 270 | return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL); |
196 | } | 271 | } |
197 | 272 | ||
273 | static int snd_p16v_pcm_open_capture(snd_pcm_substream_t *substream) | ||
274 | { | ||
275 | // Only using channel 0 for now, but the card has 2 channels. | ||
276 | return snd_p16v_pcm_open_capture_channel(substream, 0); | ||
277 | } | ||
278 | |||
198 | /* hw_params callback */ | 279 | /* hw_params callback */ |
199 | static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream, | 280 | static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream, |
200 | snd_pcm_hw_params_t * hw_params) | 281 | snd_pcm_hw_params_t * hw_params) |
201 | { | 282 | { |
202 | int result; | 283 | int result; |
203 | //snd_printk("hw_params alloc: substream=%p\n", substream); | ||
204 | result = snd_pcm_lib_malloc_pages(substream, | 284 | result = snd_pcm_lib_malloc_pages(substream, |
205 | params_buffer_bytes(hw_params)); | 285 | params_buffer_bytes(hw_params)); |
206 | //snd_printk("hw_params alloc: result=%d\n", result); | ||
207 | //dump_stack(); | ||
208 | return result; | 286 | return result; |
209 | } | 287 | } |
210 | 288 | ||
289 | /* hw_params callback */ | ||
290 | static int snd_p16v_pcm_hw_params_capture(snd_pcm_substream_t *substream, | ||
291 | snd_pcm_hw_params_t * hw_params) | ||
292 | { | ||
293 | int result; | ||
294 | result = snd_pcm_lib_malloc_pages(substream, | ||
295 | params_buffer_bytes(hw_params)); | ||
296 | return result; | ||
297 | } | ||
298 | |||
299 | |||
211 | /* hw_free callback */ | 300 | /* hw_free callback */ |
212 | static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream) | 301 | static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream) |
213 | { | 302 | { |
214 | int result; | 303 | int result; |
215 | //snd_printk("hw_params free: substream=%p\n", substream); | ||
216 | result = snd_pcm_lib_free_pages(substream); | 304 | result = snd_pcm_lib_free_pages(substream); |
217 | //snd_printk("hw_params free: result=%d\n", result); | ||
218 | //dump_stack(); | ||
219 | return result; | 305 | return result; |
220 | } | 306 | } |
221 | 307 | ||
308 | /* hw_free callback */ | ||
309 | static int snd_p16v_pcm_hw_free_capture(snd_pcm_substream_t *substream) | ||
310 | { | ||
311 | int result; | ||
312 | result = snd_pcm_lib_free_pages(substream); | ||
313 | return result; | ||
314 | } | ||
315 | |||
316 | |||
222 | /* prepare playback callback */ | 317 | /* prepare playback callback */ |
223 | static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream) | 318 | static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream) |
224 | { | 319 | { |
225 | emu10k1_t *emu = snd_pcm_substream_chip(substream); | 320 | emu10k1_t *emu = snd_pcm_substream_chip(substream); |
226 | snd_pcm_runtime_t *runtime = substream->runtime; | 321 | snd_pcm_runtime_t *runtime = substream->runtime; |
227 | //emu10k1_pcm_t *epcm = runtime->private_data; | ||
228 | int channel = substream->pcm->device - emu->p16v_device_offset; | 322 | int channel = substream->pcm->device - emu->p16v_device_offset; |
229 | u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel)); | 323 | u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel)); |
230 | u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); | 324 | u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); |
@@ -237,23 +331,21 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream) | |||
237 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); | 331 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); |
238 | switch (runtime->rate) { | 332 | switch (runtime->rate) { |
239 | case 44100: | 333 | case 44100: |
240 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x8000); /* FIXME: This will change the capture rate as well! */ | 334 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080); |
241 | break; | ||
242 | case 48000: | ||
243 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x0000); /* FIXME: This will change the capture rate as well! */ | ||
244 | break; | 335 | break; |
245 | case 96000: | 336 | case 96000: |
246 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x4000); /* FIXME: This will change the capture rate as well! */ | 337 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040); |
247 | break; | 338 | break; |
248 | case 192000: | 339 | case 192000: |
249 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x2000); /* FIXME: This will change the capture rate as well! */ | 340 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020); |
250 | break; | 341 | break; |
342 | case 48000: | ||
251 | default: | 343 | default: |
252 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, 0x0000); /* FIXME: This will change the capture rate as well! */ | 344 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000); |
253 | break; | 345 | break; |
254 | } | 346 | } |
255 | /* FIXME: Check emu->buffer.size before actually writing to it. */ | 347 | /* FIXME: Check emu->buffer.size before actually writing to it. */ |
256 | for(i=0; i < runtime->periods; i++) { | 348 | for(i=0; i < runtime->periods; i++) { |
257 | table_base[i*2]=runtime->dma_addr+(i*period_size_bytes); | 349 | table_base[i*2]=runtime->dma_addr+(i*period_size_bytes); |
258 | table_base[(i*2)+1]=period_size_bytes<<16; | 350 | table_base[(i*2)+1]=period_size_bytes<<16; |
259 | } | 351 | } |
@@ -262,7 +354,8 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream) | |||
262 | snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19); | 354 | snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19); |
263 | snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0); | 355 | snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0); |
264 | snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr); | 356 | snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr); |
265 | snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes | 357 | //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes |
358 | snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes | ||
266 | snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0); | 359 | snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0); |
267 | snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0); | 360 | snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0); |
268 | snd_emu10k1_ptr20_write(emu, 0x08, channel, 0); | 361 | snd_emu10k1_ptr20_write(emu, 0x08, channel, 0); |
@@ -270,6 +363,41 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream) | |||
270 | return 0; | 363 | return 0; |
271 | } | 364 | } |
272 | 365 | ||
366 | /* prepare capture callback */ | ||
367 | static int snd_p16v_pcm_prepare_capture(snd_pcm_substream_t *substream) | ||
368 | { | ||
369 | emu10k1_t *emu = snd_pcm_substream_chip(substream); | ||
370 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
371 | int channel = substream->pcm->device - emu->p16v_device_offset; | ||
372 | u32 tmp; | ||
373 | //printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); | ||
374 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel); | ||
375 | switch (runtime->rate) { | ||
376 | case 44100: | ||
377 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800); | ||
378 | break; | ||
379 | case 96000: | ||
380 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400); | ||
381 | break; | ||
382 | case 192000: | ||
383 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200); | ||
384 | break; | ||
385 | case 48000: | ||
386 | default: | ||
387 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000); | ||
388 | break; | ||
389 | } | ||
390 | /* FIXME: Check emu->buffer.size before actually writing to it. */ | ||
391 | snd_emu10k1_ptr20_write(emu, 0x13, channel, 0); | ||
392 | snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); | ||
393 | snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes | ||
394 | snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0); | ||
395 | //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */ | ||
396 | //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel)); | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
273 | static void snd_p16v_intr_enable(emu10k1_t *emu, unsigned int intrenb) | 401 | static void snd_p16v_intr_enable(emu10k1_t *emu, unsigned int intrenb) |
274 | { | 402 | { |
275 | unsigned long flags; | 403 | unsigned long flags; |
@@ -345,6 +473,36 @@ static int snd_p16v_pcm_trigger_playback(snd_pcm_substream_t *substream, | |||
345 | return result; | 473 | return result; |
346 | } | 474 | } |
347 | 475 | ||
476 | /* trigger_capture callback */ | ||
477 | static int snd_p16v_pcm_trigger_capture(snd_pcm_substream_t *substream, | ||
478 | int cmd) | ||
479 | { | ||
480 | emu10k1_t *emu = snd_pcm_substream_chip(substream); | ||
481 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
482 | emu10k1_pcm_t *epcm = runtime->private_data; | ||
483 | int channel = 0; | ||
484 | int result = 0; | ||
485 | u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP; | ||
486 | |||
487 | switch (cmd) { | ||
488 | case SNDRV_PCM_TRIGGER_START: | ||
489 | snd_p16v_intr_enable(emu, inte); | ||
490 | snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel)); | ||
491 | epcm->running = 1; | ||
492 | break; | ||
493 | case SNDRV_PCM_TRIGGER_STOP: | ||
494 | snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel)); | ||
495 | snd_p16v_intr_disable(emu, inte); | ||
496 | //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel)); | ||
497 | epcm->running = 0; | ||
498 | break; | ||
499 | default: | ||
500 | result = -EINVAL; | ||
501 | break; | ||
502 | } | ||
503 | return result; | ||
504 | } | ||
505 | |||
348 | /* pointer_playback callback */ | 506 | /* pointer_playback callback */ |
349 | static snd_pcm_uframes_t | 507 | static snd_pcm_uframes_t |
350 | snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream) | 508 | snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream) |
@@ -370,6 +528,31 @@ snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream) | |||
370 | return ptr; | 528 | return ptr; |
371 | } | 529 | } |
372 | 530 | ||
531 | /* pointer_capture callback */ | ||
532 | static snd_pcm_uframes_t | ||
533 | snd_p16v_pcm_pointer_capture(snd_pcm_substream_t *substream) | ||
534 | { | ||
535 | emu10k1_t *emu = snd_pcm_substream_chip(substream); | ||
536 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
537 | emu10k1_pcm_t *epcm = runtime->private_data; | ||
538 | snd_pcm_uframes_t ptr, ptr1, ptr2 = 0; | ||
539 | int channel = 0; | ||
540 | |||
541 | if (!epcm->running) | ||
542 | return 0; | ||
543 | |||
544 | ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel); | ||
545 | ptr2 = bytes_to_frames(runtime, ptr1); | ||
546 | ptr=ptr2; | ||
547 | if (ptr >= runtime->buffer_size) { | ||
548 | ptr -= runtime->buffer_size; | ||
549 | printk("buffer capture limited!\n"); | ||
550 | } | ||
551 | //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate); | ||
552 | |||
553 | return ptr; | ||
554 | } | ||
555 | |||
373 | /* operators */ | 556 | /* operators */ |
374 | static snd_pcm_ops_t snd_p16v_playback_front_ops = { | 557 | static snd_pcm_ops_t snd_p16v_playback_front_ops = { |
375 | .open = snd_p16v_pcm_open_playback_front, | 558 | .open = snd_p16v_pcm_open_playback_front, |
@@ -382,6 +565,18 @@ static snd_pcm_ops_t snd_p16v_playback_front_ops = { | |||
382 | .pointer = snd_p16v_pcm_pointer_playback, | 565 | .pointer = snd_p16v_pcm_pointer_playback, |
383 | }; | 566 | }; |
384 | 567 | ||
568 | static snd_pcm_ops_t snd_p16v_capture_ops = { | ||
569 | .open = snd_p16v_pcm_open_capture, | ||
570 | .close = snd_p16v_pcm_close_capture, | ||
571 | .ioctl = snd_pcm_lib_ioctl, | ||
572 | .hw_params = snd_p16v_pcm_hw_params_capture, | ||
573 | .hw_free = snd_p16v_pcm_hw_free_capture, | ||
574 | .prepare = snd_p16v_pcm_prepare_capture, | ||
575 | .trigger = snd_p16v_pcm_trigger_capture, | ||
576 | .pointer = snd_p16v_pcm_pointer_capture, | ||
577 | }; | ||
578 | |||
579 | |||
385 | int snd_p16v_free(emu10k1_t *chip) | 580 | int snd_p16v_free(emu10k1_t *chip) |
386 | { | 581 | { |
387 | // release the data | 582 | // release the data |
@@ -405,20 +600,22 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm) | |||
405 | snd_pcm_t *pcm; | 600 | snd_pcm_t *pcm; |
406 | snd_pcm_substream_t *substream; | 601 | snd_pcm_substream_t *substream; |
407 | int err; | 602 | int err; |
408 | int capture=0; | 603 | int capture=1; |
409 | 604 | ||
410 | //snd_printk("snd_p16v_pcm called. device=%d\n", device); | 605 | //snd_printk("snd_p16v_pcm called. device=%d\n", device); |
411 | emu->p16v_device_offset = device; | 606 | emu->p16v_device_offset = device; |
412 | if (rpcm) | 607 | if (rpcm) |
413 | *rpcm = NULL; | 608 | *rpcm = NULL; |
414 | //if (device == 0) capture=1; | 609 | |
415 | if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0) | 610 | if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0) |
416 | return err; | 611 | return err; |
417 | 612 | ||
418 | pcm->private_data = emu; | 613 | pcm->private_data = emu; |
419 | pcm->private_free = snd_p16v_pcm_free; | 614 | pcm->private_free = snd_p16v_pcm_free; |
420 | 615 | // Single playback 8 channel device. | |
616 | // Single capture 2 channel device. | ||
421 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops); | 617 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops); |
618 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops); | ||
422 | 619 | ||
423 | pcm->info_flags = 0; | 620 | pcm->info_flags = 0; |
424 | pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; | 621 | pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; |
@@ -431,7 +628,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm) | |||
431 | if ((err = snd_pcm_lib_preallocate_pages(substream, | 628 | if ((err = snd_pcm_lib_preallocate_pages(substream, |
432 | SNDRV_DMA_TYPE_DEV, | 629 | SNDRV_DMA_TYPE_DEV, |
433 | snd_dma_pci_data(emu->pci), | 630 | snd_dma_pci_data(emu->pci), |
434 | 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */ | 631 | ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) |
435 | return err; | 632 | return err; |
436 | //snd_printk("preallocate playback substream: err=%d\n", err); | 633 | //snd_printk("preallocate playback substream: err=%d\n", err); |
437 | } | 634 | } |
@@ -442,7 +639,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm) | |||
442 | if ((err = snd_pcm_lib_preallocate_pages(substream, | 639 | if ((err = snd_pcm_lib_preallocate_pages(substream, |
443 | SNDRV_DMA_TYPE_DEV, | 640 | SNDRV_DMA_TYPE_DEV, |
444 | snd_dma_pci_data(emu->pci), | 641 | snd_dma_pci_data(emu->pci), |
445 | 64*1024, 64*1024)) < 0) | 642 | 65536 - 64, 65536 - 64)) < 0) |
446 | return err; | 643 | return err; |
447 | //snd_printk("preallocate capture substream: err=%d\n", err); | 644 | //snd_printk("preallocate capture substream: err=%d\n", err); |
448 | } | 645 | } |
@@ -625,7 +822,7 @@ static int snd_p16v_volume_put_analog_unknown(snd_kcontrol_t * kcontrol, | |||
625 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_front = | 822 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_front = |
626 | { | 823 | { |
627 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 824 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
628 | .name = "HD Analog Front Volume", | 825 | .name = "HD Analog Front Playback Volume", |
629 | .info = snd_p16v_volume_info, | 826 | .info = snd_p16v_volume_info, |
630 | .get = snd_p16v_volume_get_analog_front, | 827 | .get = snd_p16v_volume_get_analog_front, |
631 | .put = snd_p16v_volume_put_analog_front | 828 | .put = snd_p16v_volume_put_analog_front |
@@ -634,7 +831,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_front = | |||
634 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe = | 831 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe = |
635 | { | 832 | { |
636 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 833 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
637 | .name = "HD Analog Center/LFE Volume", | 834 | .name = "HD Analog Center/LFE Playback Volume", |
638 | .info = snd_p16v_volume_info, | 835 | .info = snd_p16v_volume_info, |
639 | .get = snd_p16v_volume_get_analog_center_lfe, | 836 | .get = snd_p16v_volume_get_analog_center_lfe, |
640 | .put = snd_p16v_volume_put_analog_center_lfe | 837 | .put = snd_p16v_volume_put_analog_center_lfe |
@@ -643,7 +840,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe = | |||
643 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown = | 840 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown = |
644 | { | 841 | { |
645 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 842 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
646 | .name = "HD Analog Unknown Volume", | 843 | .name = "HD Analog Unknown Playback Volume", |
647 | .info = snd_p16v_volume_info, | 844 | .info = snd_p16v_volume_info, |
648 | .get = snd_p16v_volume_get_analog_unknown, | 845 | .get = snd_p16v_volume_get_analog_unknown, |
649 | .put = snd_p16v_volume_put_analog_unknown | 846 | .put = snd_p16v_volume_put_analog_unknown |
@@ -652,7 +849,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown = | |||
652 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear = | 849 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear = |
653 | { | 850 | { |
654 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 851 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
655 | .name = "HD Analog Rear Volume", | 852 | .name = "HD Analog Rear Playback Volume", |
656 | .info = snd_p16v_volume_info, | 853 | .info = snd_p16v_volume_info, |
657 | .get = snd_p16v_volume_get_analog_rear, | 854 | .get = snd_p16v_volume_get_analog_rear, |
658 | .put = snd_p16v_volume_put_analog_rear | 855 | .put = snd_p16v_volume_put_analog_rear |
@@ -661,7 +858,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear = | |||
661 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front = | 858 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front = |
662 | { | 859 | { |
663 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 860 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
664 | .name = "HD SPDIF Front Volume", | 861 | .name = "HD SPDIF Front Playback Volume", |
665 | .info = snd_p16v_volume_info, | 862 | .info = snd_p16v_volume_info, |
666 | .get = snd_p16v_volume_get_spdif_front, | 863 | .get = snd_p16v_volume_get_spdif_front, |
667 | .put = snd_p16v_volume_put_spdif_front | 864 | .put = snd_p16v_volume_put_spdif_front |
@@ -670,7 +867,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front = | |||
670 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe = | 867 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe = |
671 | { | 868 | { |
672 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 869 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
673 | .name = "HD SPDIF Center/LFE Volume", | 870 | .name = "HD SPDIF Center/LFE Playback Volume", |
674 | .info = snd_p16v_volume_info, | 871 | .info = snd_p16v_volume_info, |
675 | .get = snd_p16v_volume_get_spdif_center_lfe, | 872 | .get = snd_p16v_volume_get_spdif_center_lfe, |
676 | .put = snd_p16v_volume_put_spdif_center_lfe | 873 | .put = snd_p16v_volume_put_spdif_center_lfe |
@@ -679,7 +876,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe = | |||
679 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown = | 876 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown = |
680 | { | 877 | { |
681 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 878 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
682 | .name = "HD SPDIF Unknown Volume", | 879 | .name = "HD SPDIF Unknown Playback Volume", |
683 | .info = snd_p16v_volume_info, | 880 | .info = snd_p16v_volume_info, |
684 | .get = snd_p16v_volume_get_spdif_unknown, | 881 | .get = snd_p16v_volume_get_spdif_unknown, |
685 | .put = snd_p16v_volume_put_spdif_unknown | 882 | .put = snd_p16v_volume_put_spdif_unknown |
@@ -688,12 +885,112 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown = | |||
688 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear = | 885 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear = |
689 | { | 886 | { |
690 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 887 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
691 | .name = "HD SPDIF Rear Volume", | 888 | .name = "HD SPDIF Rear Playback Volume", |
692 | .info = snd_p16v_volume_info, | 889 | .info = snd_p16v_volume_info, |
693 | .get = snd_p16v_volume_get_spdif_rear, | 890 | .get = snd_p16v_volume_get_spdif_rear, |
694 | .put = snd_p16v_volume_put_spdif_rear | 891 | .put = snd_p16v_volume_put_spdif_rear |
695 | }; | 892 | }; |
696 | 893 | ||
894 | static int snd_p16v_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) | ||
895 | { | ||
896 | static char *texts[8] = { "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S", "CDIF", "FX", "AC97" }; | ||
897 | |||
898 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
899 | uinfo->count = 1; | ||
900 | uinfo->value.enumerated.items = 8; | ||
901 | if (uinfo->value.enumerated.item > 7) | ||
902 | uinfo->value.enumerated.item = 7; | ||
903 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
904 | return 0; | ||
905 | } | ||
906 | |||
907 | static int snd_p16v_capture_source_get(snd_kcontrol_t * kcontrol, | ||
908 | snd_ctl_elem_value_t * ucontrol) | ||
909 | { | ||
910 | emu10k1_t *emu = snd_kcontrol_chip(kcontrol); | ||
911 | |||
912 | ucontrol->value.enumerated.item[0] = emu->p16v_capture_source; | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol, | ||
917 | snd_ctl_elem_value_t * ucontrol) | ||
918 | { | ||
919 | emu10k1_t *emu = snd_kcontrol_chip(kcontrol); | ||
920 | unsigned int val; | ||
921 | int change = 0; | ||
922 | u32 mask; | ||
923 | u32 source; | ||
924 | |||
925 | val = ucontrol->value.enumerated.item[0] ; | ||
926 | change = (emu->p16v_capture_source != val); | ||
927 | if (change) { | ||
928 | emu->p16v_capture_source = val; | ||
929 | source = (val << 28) | (val << 24) | (val << 20) | (val << 16); | ||
930 | mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff; | ||
931 | snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask); | ||
932 | } | ||
933 | return change; | ||
934 | } | ||
935 | |||
936 | static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata = | ||
937 | { | ||
938 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
939 | .name = "HD source Capture", | ||
940 | .info = snd_p16v_capture_source_info, | ||
941 | .get = snd_p16v_capture_source_get, | ||
942 | .put = snd_p16v_capture_source_put | ||
943 | }; | ||
944 | |||
945 | static int snd_p16v_capture_channel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) | ||
946 | { | ||
947 | static char *texts[4] = { "0", "1", "2", "3", }; | ||
948 | |||
949 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
950 | uinfo->count = 1; | ||
951 | uinfo->value.enumerated.items = 4; | ||
952 | if (uinfo->value.enumerated.item > 3) | ||
953 | uinfo->value.enumerated.item = 3; | ||
954 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static int snd_p16v_capture_channel_get(snd_kcontrol_t * kcontrol, | ||
959 | snd_ctl_elem_value_t * ucontrol) | ||
960 | { | ||
961 | emu10k1_t *emu = snd_kcontrol_chip(kcontrol); | ||
962 | |||
963 | ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel; | ||
964 | return 0; | ||
965 | } | ||
966 | |||
967 | static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol, | ||
968 | snd_ctl_elem_value_t * ucontrol) | ||
969 | { | ||
970 | emu10k1_t *emu = snd_kcontrol_chip(kcontrol); | ||
971 | unsigned int val; | ||
972 | int change = 0; | ||
973 | u32 tmp; | ||
974 | |||
975 | val = ucontrol->value.enumerated.item[0] ; | ||
976 | change = (emu->p16v_capture_channel != val); | ||
977 | if (change) { | ||
978 | emu->p16v_capture_channel = val; | ||
979 | tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc; | ||
980 | snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val); | ||
981 | } | ||
982 | return change; | ||
983 | } | ||
984 | |||
985 | static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata = | ||
986 | { | ||
987 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
988 | .name = "HD channel Capture", | ||
989 | .info = snd_p16v_capture_channel_info, | ||
990 | .get = snd_p16v_capture_channel_get, | ||
991 | .put = snd_p16v_capture_channel_put | ||
992 | }; | ||
993 | |||
697 | int snd_p16v_mixer(emu10k1_t *emu) | 994 | int snd_p16v_mixer(emu10k1_t *emu) |
698 | { | 995 | { |
699 | int err; | 996 | int err; |
@@ -731,6 +1028,14 @@ int snd_p16v_mixer(emu10k1_t *emu) | |||
731 | return -ENOMEM; | 1028 | return -ENOMEM; |
732 | if ((err = snd_ctl_add(card, kctl))) | 1029 | if ((err = snd_ctl_add(card, kctl))) |
733 | return err; | 1030 | return err; |
1031 | if ((kctl = snd_ctl_new1(&snd_p16v_capture_source, emu)) == NULL) | ||
1032 | return -ENOMEM; | ||
1033 | if ((err = snd_ctl_add(card, kctl))) | ||
1034 | return err; | ||
1035 | if ((kctl = snd_ctl_new1(&snd_p16v_capture_channel, emu)) == NULL) | ||
1036 | return -ENOMEM; | ||
1037 | if ((err = snd_ctl_add(card, kctl))) | ||
1038 | return err; | ||
734 | return 0; | 1039 | return 0; |
735 | } | 1040 | } |
736 | 1041 | ||
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index f910399db5c3..78a81f3912a1 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -685,6 +685,15 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97, | |||
685 | return 0; | 685 | return 0; |
686 | } | 686 | } |
687 | 687 | ||
688 | static void snd_es1371_codec_wait(ac97_t *ac97) | ||
689 | { | ||
690 | msleep(750); | ||
691 | snd_es1371_codec_read(ac97, AC97_RESET); | ||
692 | snd_es1371_codec_read(ac97, AC97_VENDOR_ID1); | ||
693 | snd_es1371_codec_read(ac97, AC97_VENDOR_ID2); | ||
694 | msleep(50); | ||
695 | } | ||
696 | |||
688 | static void snd_es1371_adc_rate(ensoniq_t * ensoniq, unsigned int rate) | 697 | static void snd_es1371_adc_rate(ensoniq_t * ensoniq, unsigned int rate) |
689 | { | 698 | { |
690 | unsigned int n, truncm, freq, result; | 699 | unsigned int n, truncm, freq, result; |
@@ -1585,6 +1594,7 @@ static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq) | |||
1585 | static ac97_bus_ops_t ops = { | 1594 | static ac97_bus_ops_t ops = { |
1586 | .write = snd_es1371_codec_write, | 1595 | .write = snd_es1371_codec_write, |
1587 | .read = snd_es1371_codec_read, | 1596 | .read = snd_es1371_codec_read, |
1597 | .wait = snd_es1371_codec_wait, | ||
1588 | }; | 1598 | }; |
1589 | 1599 | ||
1590 | if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0) | 1600 | if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0) |
@@ -2008,21 +2018,11 @@ static int __devinit snd_ensoniq_create(snd_card_t * card, | |||
2008 | if (pci->vendor == es1371_ac97_reset_hack[idx].vid && | 2018 | if (pci->vendor == es1371_ac97_reset_hack[idx].vid && |
2009 | pci->device == es1371_ac97_reset_hack[idx].did && | 2019 | pci->device == es1371_ac97_reset_hack[idx].did && |
2010 | ensoniq->rev == es1371_ac97_reset_hack[idx].rev) { | 2020 | ensoniq->rev == es1371_ac97_reset_hack[idx].rev) { |
2011 | unsigned long tmo; | ||
2012 | signed long tmo2; | ||
2013 | |||
2014 | ensoniq->cssr |= ES_1371_ST_AC97_RST; | 2021 | ensoniq->cssr |= ES_1371_ST_AC97_RST; |
2015 | outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); | 2022 | outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); |
2016 | /* need to delay around 20ms(bleech) to give | 2023 | /* need to delay around 20ms(bleech) to give |
2017 | some CODECs enough time to wakeup */ | 2024 | some CODECs enough time to wakeup */ |
2018 | tmo = jiffies + (HZ / 50) + 1; | 2025 | msleep(20); |
2019 | while (1) { | ||
2020 | tmo2 = tmo - jiffies; | ||
2021 | if (tmo2 <= 0) | ||
2022 | break; | ||
2023 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2024 | schedule_timeout(tmo2); | ||
2025 | } | ||
2026 | break; | 2026 | break; |
2027 | } | 2027 | } |
2028 | /* AC'97 warm reset to start the bitclk */ | 2028 | /* AC'97 warm reset to start the bitclk */ |
@@ -2401,7 +2401,7 @@ static struct pci_driver driver = { | |||
2401 | 2401 | ||
2402 | static int __init alsa_card_ens137x_init(void) | 2402 | static int __init alsa_card_ens137x_init(void) |
2403 | { | 2403 | { |
2404 | return pci_module_init(&driver); | 2404 | return pci_register_driver(&driver); |
2405 | } | 2405 | } |
2406 | 2406 | ||
2407 | static void __exit alsa_card_ens137x_exit(void) | 2407 | static void __exit alsa_card_ens137x_exit(void) |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index b4ca8adf393c..b492777bc30f 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -1761,7 +1761,7 @@ static struct pci_driver driver = { | |||
1761 | 1761 | ||
1762 | static int __init alsa_card_es1938_init(void) | 1762 | static int __init alsa_card_es1938_init(void) |
1763 | { | 1763 | { |
1764 | return pci_module_init(&driver); | 1764 | return pci_register_driver(&driver); |
1765 | } | 1765 | } |
1766 | 1766 | ||
1767 | static void __exit alsa_card_es1938_exit(void) | 1767 | static void __exit alsa_card_es1938_exit(void) |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index faf63ff19c42..9d7a28783930 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -636,7 +636,7 @@ static void __maestro_write(es1968_t *chip, u16 reg, u16 data) | |||
636 | chip->maestro_map[reg] = data; | 636 | chip->maestro_map[reg] = data; |
637 | } | 637 | } |
638 | 638 | ||
639 | inline static void maestro_write(es1968_t *chip, u16 reg, u16 data) | 639 | static inline void maestro_write(es1968_t *chip, u16 reg, u16 data) |
640 | { | 640 | { |
641 | unsigned long flags; | 641 | unsigned long flags; |
642 | spin_lock_irqsave(&chip->reg_lock, flags); | 642 | spin_lock_irqsave(&chip->reg_lock, flags); |
@@ -654,7 +654,7 @@ static u16 __maestro_read(es1968_t *chip, u16 reg) | |||
654 | return chip->maestro_map[reg]; | 654 | return chip->maestro_map[reg]; |
655 | } | 655 | } |
656 | 656 | ||
657 | inline static u16 maestro_read(es1968_t *chip, u16 reg) | 657 | static inline u16 maestro_read(es1968_t *chip, u16 reg) |
658 | { | 658 | { |
659 | unsigned long flags; | 659 | unsigned long flags; |
660 | u16 result; | 660 | u16 result; |
@@ -664,11 +664,6 @@ inline static u16 maestro_read(es1968_t *chip, u16 reg) | |||
664 | return result; | 664 | return result; |
665 | } | 665 | } |
666 | 666 | ||
667 | #define big_mdelay(msec) do {\ | ||
668 | set_current_state(TASK_UNINTERRUPTIBLE);\ | ||
669 | schedule_timeout(((msec) * HZ + 999) / 1000);\ | ||
670 | } while (0) | ||
671 | |||
672 | /* Wait for the codec bus to be free */ | 667 | /* Wait for the codec bus to be free */ |
673 | static int snd_es1968_ac97_wait(es1968_t *chip) | 668 | static int snd_es1968_ac97_wait(es1968_t *chip) |
674 | { | 669 | { |
@@ -755,7 +750,7 @@ static void __apu_set_register(es1968_t *chip, u16 channel, u8 reg, u16 data) | |||
755 | apu_data_set(chip, data); | 750 | apu_data_set(chip, data); |
756 | } | 751 | } |
757 | 752 | ||
758 | inline static void apu_set_register(es1968_t *chip, u16 channel, u8 reg, u16 data) | 753 | static inline void apu_set_register(es1968_t *chip, u16 channel, u8 reg, u16 data) |
759 | { | 754 | { |
760 | unsigned long flags; | 755 | unsigned long flags; |
761 | spin_lock_irqsave(&chip->reg_lock, flags); | 756 | spin_lock_irqsave(&chip->reg_lock, flags); |
@@ -771,7 +766,7 @@ static u16 __apu_get_register(es1968_t *chip, u16 channel, u8 reg) | |||
771 | return __maestro_read(chip, IDR0_DATA_PORT); | 766 | return __maestro_read(chip, IDR0_DATA_PORT); |
772 | } | 767 | } |
773 | 768 | ||
774 | inline static u16 apu_get_register(es1968_t *chip, u16 channel, u8 reg) | 769 | static inline u16 apu_get_register(es1968_t *chip, u16 channel, u8 reg) |
775 | { | 770 | { |
776 | unsigned long flags; | 771 | unsigned long flags; |
777 | u16 v; | 772 | u16 v; |
@@ -957,7 +952,7 @@ static u32 snd_es1968_compute_rate(es1968_t *chip, u32 freq) | |||
957 | } | 952 | } |
958 | 953 | ||
959 | /* get current pointer */ | 954 | /* get current pointer */ |
960 | inline static unsigned int | 955 | static inline unsigned int |
961 | snd_es1968_get_dma_ptr(es1968_t *chip, esschan_t *es) | 956 | snd_es1968_get_dma_ptr(es1968_t *chip, esschan_t *es) |
962 | { | 957 | { |
963 | unsigned int offset; | 958 | unsigned int offset; |
@@ -978,7 +973,7 @@ static void snd_es1968_apu_set_freq(es1968_t *chip, int apu, int freq) | |||
978 | } | 973 | } |
979 | 974 | ||
980 | /* spin lock held */ | 975 | /* spin lock held */ |
981 | inline static void snd_es1968_trigger_apu(es1968_t *esm, int apu, int mode) | 976 | static inline void snd_es1968_trigger_apu(es1968_t *esm, int apu, int mode) |
982 | { | 977 | { |
983 | /* set the APU mode */ | 978 | /* set the APU mode */ |
984 | __apu_set_register(esm, apu, 0, | 979 | __apu_set_register(esm, apu, 0, |
@@ -1809,8 +1804,7 @@ static void __devinit es1968_measure_clock(es1968_t *chip) | |||
1809 | snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR); | 1804 | snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR); |
1810 | do_gettimeofday(&start_time); | 1805 | do_gettimeofday(&start_time); |
1811 | spin_unlock_irq(&chip->reg_lock); | 1806 | spin_unlock_irq(&chip->reg_lock); |
1812 | set_current_state(TASK_UNINTERRUPTIBLE); | 1807 | msleep(50); |
1813 | schedule_timeout(HZ / 20); /* 50 msec */ | ||
1814 | spin_lock_irq(&chip->reg_lock); | 1808 | spin_lock_irq(&chip->reg_lock); |
1815 | offset = __apu_get_register(chip, apu, 5); | 1809 | offset = __apu_get_register(chip, apu, 5); |
1816 | do_gettimeofday(&stop_time); | 1810 | do_gettimeofday(&stop_time); |
@@ -2093,7 +2087,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip) | |||
2093 | outw(0x0000, ioaddr + 0x60); /* write 0 to gpio 0 */ | 2087 | outw(0x0000, ioaddr + 0x60); /* write 0 to gpio 0 */ |
2094 | udelay(20); | 2088 | udelay(20); |
2095 | outw(0x0001, ioaddr + 0x60); /* write 1 to gpio 1 */ | 2089 | outw(0x0001, ioaddr + 0x60); /* write 1 to gpio 1 */ |
2096 | big_mdelay(20); | 2090 | msleep(20); |
2097 | 2091 | ||
2098 | outw(save_68 | 0x1, ioaddr + 0x68); /* now restore .. */ | 2092 | outw(save_68 | 0x1, ioaddr + 0x68); /* now restore .. */ |
2099 | outw((inw(ioaddr + 0x38) & 0xfffc) | 0x1, ioaddr + 0x38); | 2093 | outw((inw(ioaddr + 0x38) & 0xfffc) | 0x1, ioaddr + 0x38); |
@@ -2109,7 +2103,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip) | |||
2109 | outw(0x0001, ioaddr + 0x60); /* write 1 to gpio */ | 2103 | outw(0x0001, ioaddr + 0x60); /* write 1 to gpio */ |
2110 | udelay(20); | 2104 | udelay(20); |
2111 | outw(0x0009, ioaddr + 0x60); /* write 9 to gpio */ | 2105 | outw(0x0009, ioaddr + 0x60); /* write 9 to gpio */ |
2112 | big_mdelay(500); | 2106 | msleep(500); |
2113 | //outw(inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38); | 2107 | //outw(inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38); |
2114 | outw(inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a); | 2108 | outw(inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a); |
2115 | outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c); | 2109 | outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c); |
@@ -2135,7 +2129,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip) | |||
2135 | 2129 | ||
2136 | if (w > 10000) { | 2130 | if (w > 10000) { |
2137 | outb(inb(ioaddr + 0x37) | 0x08, ioaddr + 0x37); /* do a software reset */ | 2131 | outb(inb(ioaddr + 0x37) | 0x08, ioaddr + 0x37); /* do a software reset */ |
2138 | big_mdelay(500); /* oh my.. */ | 2132 | msleep(500); /* oh my.. */ |
2139 | outb(inb(ioaddr + 0x37) & ~0x08, | 2133 | outb(inb(ioaddr + 0x37) & ~0x08, |
2140 | ioaddr + 0x37); | 2134 | ioaddr + 0x37); |
2141 | udelay(1); | 2135 | udelay(1); |
@@ -2559,6 +2553,7 @@ static struct ess_device_list pm_whitelist[] __devinitdata = { | |||
2559 | { TYPE_MAESTRO2E, 0x103c }, | 2553 | { TYPE_MAESTRO2E, 0x103c }, |
2560 | { TYPE_MAESTRO2E, 0x1179 }, | 2554 | { TYPE_MAESTRO2E, 0x1179 }, |
2561 | { TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */ | 2555 | { TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */ |
2556 | { TYPE_MAESTRO2E, 0x1558 }, | ||
2562 | }; | 2557 | }; |
2563 | 2558 | ||
2564 | static struct ess_device_list mpu_blacklist[] __devinitdata = { | 2559 | static struct ess_device_list mpu_blacklist[] __devinitdata = { |
@@ -2795,7 +2790,7 @@ static struct pci_driver driver = { | |||
2795 | 2790 | ||
2796 | static int __init alsa_card_es1968_init(void) | 2791 | static int __init alsa_card_es1968_init(void) |
2797 | { | 2792 | { |
2798 | return pci_module_init(&driver); | 2793 | return pci_register_driver(&driver); |
2799 | } | 2794 | } |
2800 | 2795 | ||
2801 | static void __exit alsa_card_es1968_exit(void) | 2796 | static void __exit alsa_card_es1968_exit(void) |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 08e7c5a296d5..ff10e637a95e 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -195,6 +195,7 @@ struct _snd_fm801 { | |||
195 | 195 | ||
196 | static struct pci_device_id snd_fm801_ids[] = { | 196 | static struct pci_device_id snd_fm801_ids[] = { |
197 | { 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */ | 197 | { 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */ |
198 | { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */ | ||
198 | { 0, } | 199 | { 0, } |
199 | }; | 200 | }; |
200 | 201 | ||
@@ -1468,7 +1469,7 @@ static struct pci_driver driver = { | |||
1468 | 1469 | ||
1469 | static int __init alsa_card_fm801_init(void) | 1470 | static int __init alsa_card_fm801_init(void) |
1470 | { | 1471 | { |
1471 | return pci_module_init(&driver); | 1472 | return pci_register_driver(&driver); |
1472 | } | 1473 | } |
1473 | 1474 | ||
1474 | static void __exit alsa_card_fm801_exit(void) | 1475 | static void __exit alsa_card_fm801_exit(void) |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 570a59d33b41..bd8cb33c4fb4 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | snd-hda-intel-objs := hda_intel.o | 1 | snd-hda-intel-objs := hda_intel.o |
2 | snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o | 2 | snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o |
3 | ifdef CONFIG_PROC_FS | 3 | ifdef CONFIG_PROC_FS |
4 | snd-hda-codec-objs += hda_proc.o | 4 | snd-hda-codec-objs += hda_proc.o |
5 | endif | 5 | endif |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 9ed117ac0c09..e2cf02387289 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -49,8 +49,10 @@ struct hda_vendor_id { | |||
49 | /* codec vendor labels */ | 49 | /* codec vendor labels */ |
50 | static struct hda_vendor_id hda_vendor_ids[] = { | 50 | static struct hda_vendor_id hda_vendor_ids[] = { |
51 | { 0x10ec, "Realtek" }, | 51 | { 0x10ec, "Realtek" }, |
52 | { 0x11d4, "Analog Devices" }, | ||
52 | { 0x13f6, "C-Media" }, | 53 | { 0x13f6, "C-Media" }, |
53 | { 0x434d, "C-Media" }, | 54 | { 0x434d, "C-Media" }, |
55 | { 0x8384, "SigmaTel" }, | ||
54 | {} /* terminator */ | 56 | {} /* terminator */ |
55 | }; | 57 | }; |
56 | 58 | ||
@@ -508,7 +510,7 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
508 | /* FIXME: support for multiple AFGs? */ | 510 | /* FIXME: support for multiple AFGs? */ |
509 | codec->afg = look_for_afg_node(codec); | 511 | codec->afg = look_for_afg_node(codec); |
510 | if (! codec->afg) { | 512 | if (! codec->afg) { |
511 | snd_printk(KERN_ERR "hda_codec: no AFG node found\n"); | 513 | snd_printdd("hda_codec: no AFG node found\n"); |
512 | snd_hda_codec_free(codec); | 514 | snd_hda_codec_free(codec); |
513 | return -ENODEV; | 515 | return -ENODEV; |
514 | } | 516 | } |
@@ -548,6 +550,9 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
548 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, | 550 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag, |
549 | int channel_id, int format) | 551 | int channel_id, int format) |
550 | { | 552 | { |
553 | if (! nid) | ||
554 | return; | ||
555 | |||
551 | snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", | 556 | snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", |
552 | nid, stream_tag, channel_id, format); | 557 | nid, stream_tag, channel_id, format); |
553 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, | 558 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, |
@@ -561,9 +566,10 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre | |||
561 | * amp access functions | 566 | * amp access functions |
562 | */ | 567 | */ |
563 | 568 | ||
564 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + (idx) * 32 + (dir) * 64) | 569 | /* FIXME: more better hash key? */ |
570 | #define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) | ||
565 | #define INFO_AMP_CAPS (1<<0) | 571 | #define INFO_AMP_CAPS (1<<0) |
566 | #define INFO_AMP_VOL (1<<1) | 572 | #define INFO_AMP_VOL(ch) (1 << (1 + (ch))) |
567 | 573 | ||
568 | /* initialize the hash table */ | 574 | /* initialize the hash table */ |
569 | static void init_amp_hash(struct hda_codec *codec) | 575 | static void init_amp_hash(struct hda_codec *codec) |
@@ -622,28 +628,29 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction) | |||
622 | 628 | ||
623 | /* | 629 | /* |
624 | * read the current volume to info | 630 | * read the current volume to info |
625 | * if the cache exists, read from the cache. | 631 | * if the cache exists, read the cache value. |
626 | */ | 632 | */ |
627 | static void get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, | 633 | static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, |
628 | hda_nid_t nid, int ch, int direction, int index) | 634 | hda_nid_t nid, int ch, int direction, int index) |
629 | { | 635 | { |
630 | u32 val, parm; | 636 | u32 val, parm; |
631 | 637 | ||
632 | if (info->status & (INFO_AMP_VOL << ch)) | 638 | if (info->status & INFO_AMP_VOL(ch)) |
633 | return; | 639 | return info->vol[ch]; |
634 | 640 | ||
635 | parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; | 641 | parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT; |
636 | parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; | 642 | parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; |
637 | parm |= index; | 643 | parm |= index; |
638 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm); | 644 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm); |
639 | info->vol[ch] = val & 0xff; | 645 | info->vol[ch] = val & 0xff; |
640 | info->status |= INFO_AMP_VOL << ch; | 646 | info->status |= INFO_AMP_VOL(ch); |
647 | return info->vol[ch]; | ||
641 | } | 648 | } |
642 | 649 | ||
643 | /* | 650 | /* |
644 | * write the current volume in info to the h/w | 651 | * write the current volume in info to the h/w and update the cache |
645 | */ | 652 | */ |
646 | static void put_vol_mute(struct hda_codec *codec, | 653 | static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info, |
647 | hda_nid_t nid, int ch, int direction, int index, int val) | 654 | hda_nid_t nid, int ch, int direction, int index, int val) |
648 | { | 655 | { |
649 | u32 parm; | 656 | u32 parm; |
@@ -653,30 +660,34 @@ static void put_vol_mute(struct hda_codec *codec, | |||
653 | parm |= index << AC_AMP_SET_INDEX_SHIFT; | 660 | parm |= index << AC_AMP_SET_INDEX_SHIFT; |
654 | parm |= val; | 661 | parm |= val; |
655 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm); | 662 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm); |
663 | info->vol[ch] = val; | ||
656 | } | 664 | } |
657 | 665 | ||
658 | /* | 666 | /* |
659 | * read/write AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. | 667 | * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. |
660 | */ | 668 | */ |
661 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index) | 669 | static int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index) |
662 | { | 670 | { |
663 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); | 671 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); |
664 | if (! info) | 672 | if (! info) |
665 | return 0; | 673 | return 0; |
666 | get_vol_mute(codec, info, nid, ch, direction, index); | 674 | return get_vol_mute(codec, info, nid, ch, direction, index); |
667 | return info->vol[ch]; | ||
668 | } | 675 | } |
669 | 676 | ||
670 | int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val) | 677 | /* |
678 | * update the AMP value, mask = bit mask to set, val = the value | ||
679 | */ | ||
680 | static int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int mask, int val) | ||
671 | { | 681 | { |
672 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); | 682 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); |
683 | |||
673 | if (! info) | 684 | if (! info) |
674 | return 0; | 685 | return 0; |
675 | get_vol_mute(codec, info, nid, ch, direction, idx); | 686 | val &= mask; |
687 | val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask; | ||
676 | if (info->vol[ch] == val && ! codec->in_resume) | 688 | if (info->vol[ch] == val && ! codec->in_resume) |
677 | return 0; | 689 | return 0; |
678 | put_vol_mute(codec, nid, ch, direction, idx, val); | 690 | put_vol_mute(codec, info, nid, ch, direction, idx, val); |
679 | info->vol[ch] = val; | ||
680 | return 1; | 691 | return 1; |
681 | } | 692 | } |
682 | 693 | ||
@@ -735,21 +746,15 @@ int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
735 | int chs = get_amp_channels(kcontrol); | 746 | int chs = get_amp_channels(kcontrol); |
736 | int dir = get_amp_direction(kcontrol); | 747 | int dir = get_amp_direction(kcontrol); |
737 | int idx = get_amp_index(kcontrol); | 748 | int idx = get_amp_index(kcontrol); |
738 | int val; | ||
739 | long *valp = ucontrol->value.integer.value; | 749 | long *valp = ucontrol->value.integer.value; |
740 | int change = 0; | 750 | int change = 0; |
741 | 751 | ||
742 | if (chs & 1) { | 752 | if (chs & 1) |
743 | val = *valp & 0x7f; | 753 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
744 | val |= snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80; | 754 | 0x7f, *valp); |
745 | change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val); | 755 | if (chs & 2) |
746 | valp++; | 756 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
747 | } | 757 | 0x7f, valp[1]); |
748 | if (chs & 2) { | ||
749 | val = *valp & 0x7f; | ||
750 | val |= snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80; | ||
751 | change |= snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val); | ||
752 | } | ||
753 | return change; | 758 | return change; |
754 | } | 759 | } |
755 | 760 | ||
@@ -788,21 +793,15 @@ int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
788 | int chs = get_amp_channels(kcontrol); | 793 | int chs = get_amp_channels(kcontrol); |
789 | int dir = get_amp_direction(kcontrol); | 794 | int dir = get_amp_direction(kcontrol); |
790 | int idx = get_amp_index(kcontrol); | 795 | int idx = get_amp_index(kcontrol); |
791 | int val; | ||
792 | long *valp = ucontrol->value.integer.value; | 796 | long *valp = ucontrol->value.integer.value; |
793 | int change = 0; | 797 | int change = 0; |
794 | 798 | ||
795 | if (chs & 1) { | 799 | if (chs & 1) |
796 | val = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f; | 800 | change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx, |
797 | val |= *valp ? 0 : 0x80; | 801 | 0x80, *valp ? 0 : 0x80); |
798 | change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val); | 802 | if (chs & 2) |
799 | valp++; | 803 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
800 | } | 804 | 0x80, valp[1] ? 0 : 0x80); |
801 | if (chs & 2) { | ||
802 | val = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f; | ||
803 | val |= *valp ? 0 : 0x80; | ||
804 | change = snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val); | ||
805 | } | ||
806 | return change; | 805 | return change; |
807 | } | 806 | } |
808 | 807 | ||
@@ -1448,10 +1447,6 @@ static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream | |||
1448 | snd_assert(info->nid, return -EINVAL); | 1447 | snd_assert(info->nid, return -EINVAL); |
1449 | info->ops.prepare = hda_pcm_default_prepare; | 1448 | info->ops.prepare = hda_pcm_default_prepare; |
1450 | } | 1449 | } |
1451 | if (info->ops.prepare == NULL) { | ||
1452 | snd_assert(info->nid, return -EINVAL); | ||
1453 | info->ops.prepare = hda_pcm_default_prepare; | ||
1454 | } | ||
1455 | if (info->ops.cleanup == NULL) { | 1450 | if (info->ops.cleanup == NULL) { |
1456 | snd_assert(info->nid, return -EINVAL); | 1451 | snd_assert(info->nid, return -EINVAL); |
1457 | info->ops.cleanup = hda_pcm_default_cleanup; | 1452 | info->ops.cleanup = hda_pcm_default_cleanup; |
@@ -1525,12 +1520,12 @@ int snd_hda_build_pcms(struct hda_bus *bus) | |||
1525 | * | 1520 | * |
1526 | * If no entries are matching, the function returns a negative value. | 1521 | * If no entries are matching, the function returns a negative value. |
1527 | */ | 1522 | */ |
1528 | int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl) | 1523 | int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl) |
1529 | { | 1524 | { |
1530 | struct hda_board_config *c; | 1525 | const struct hda_board_config *c; |
1531 | 1526 | ||
1532 | if (codec->bus->modelname) { | 1527 | if (codec->bus->modelname) { |
1533 | for (c = tbl; c->modelname || c->pci_vendor; c++) { | 1528 | for (c = tbl; c->modelname || c->pci_subvendor; c++) { |
1534 | if (c->modelname && | 1529 | if (c->modelname && |
1535 | ! strcmp(codec->bus->modelname, c->modelname)) { | 1530 | ! strcmp(codec->bus->modelname, c->modelname)) { |
1536 | snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname); | 1531 | snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname); |
@@ -1543,9 +1538,10 @@ int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config | |||
1543 | u16 subsystem_vendor, subsystem_device; | 1538 | u16 subsystem_vendor, subsystem_device; |
1544 | pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); | 1539 | pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); |
1545 | pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device); | 1540 | pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device); |
1546 | for (c = tbl; c->modelname || c->pci_vendor; c++) { | 1541 | for (c = tbl; c->modelname || c->pci_subvendor; c++) { |
1547 | if (c->pci_vendor == subsystem_vendor && | 1542 | if (c->pci_subvendor == subsystem_vendor && |
1548 | c->pci_device == subsystem_device) | 1543 | (! c->pci_subdevice /* all match */|| |
1544 | (c->pci_subdevice == subsystem_device))) | ||
1549 | return c->config; | 1545 | return c->config; |
1550 | } | 1546 | } |
1551 | } | 1547 | } |
@@ -1687,11 +1683,12 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o | |||
1687 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); | 1683 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); |
1688 | /* surrounds */ | 1684 | /* surrounds */ |
1689 | for (i = 1; i < mout->num_dacs; i++) { | 1685 | for (i = 1; i < mout->num_dacs; i++) { |
1690 | if (i == HDA_REAR && chs == 2) /* copy front to rear */ | 1686 | if (chs >= (i + 1) * 2) /* independent out */ |
1691 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format); | ||
1692 | else if (chs >= (i + 1) * 2) /* independent out */ | ||
1693 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, | 1687 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, |
1694 | format); | 1688 | format); |
1689 | else /* copy front */ | ||
1690 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, | ||
1691 | format); | ||
1695 | } | 1692 | } |
1696 | return 0; | 1693 | return 0; |
1697 | } | 1694 | } |
@@ -1717,6 +1714,105 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o | |||
1717 | return 0; | 1714 | return 0; |
1718 | } | 1715 | } |
1719 | 1716 | ||
1717 | /* | ||
1718 | * Helper for automatic ping configuration | ||
1719 | */ | ||
1720 | /* parse all pin widgets and store the useful pin nids to cfg */ | ||
1721 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg) | ||
1722 | { | ||
1723 | hda_nid_t nid, nid_start; | ||
1724 | int i, j, nodes; | ||
1725 | short seq, sequences[4], assoc_line_out; | ||
1726 | |||
1727 | memset(cfg, 0, sizeof(*cfg)); | ||
1728 | |||
1729 | memset(sequences, 0, sizeof(sequences)); | ||
1730 | assoc_line_out = 0; | ||
1731 | |||
1732 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); | ||
1733 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | ||
1734 | unsigned int wid_caps = snd_hda_param_read(codec, nid, | ||
1735 | AC_PAR_AUDIO_WIDGET_CAP); | ||
1736 | unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
1737 | unsigned int def_conf; | ||
1738 | short assoc, loc; | ||
1739 | |||
1740 | /* read all default configuration for pin complex */ | ||
1741 | if (wid_type != AC_WID_PIN) | ||
1742 | continue; | ||
1743 | def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
1744 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | ||
1745 | continue; | ||
1746 | loc = get_defcfg_location(def_conf); | ||
1747 | switch (get_defcfg_device(def_conf)) { | ||
1748 | case AC_JACK_LINE_OUT: | ||
1749 | case AC_JACK_SPEAKER: | ||
1750 | seq = get_defcfg_sequence(def_conf); | ||
1751 | assoc = get_defcfg_association(def_conf); | ||
1752 | if (! assoc) | ||
1753 | continue; | ||
1754 | if (! assoc_line_out) | ||
1755 | assoc_line_out = assoc; | ||
1756 | else if (assoc_line_out != assoc) | ||
1757 | continue; | ||
1758 | if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins)) | ||
1759 | continue; | ||
1760 | cfg->line_out_pins[cfg->line_outs] = nid; | ||
1761 | sequences[cfg->line_outs] = seq; | ||
1762 | cfg->line_outs++; | ||
1763 | break; | ||
1764 | case AC_JACK_HP_OUT: | ||
1765 | cfg->hp_pin = nid; | ||
1766 | break; | ||
1767 | case AC_JACK_MIC_IN: | ||
1768 | if (loc == AC_JACK_LOC_FRONT) | ||
1769 | cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid; | ||
1770 | else | ||
1771 | cfg->input_pins[AUTO_PIN_MIC] = nid; | ||
1772 | break; | ||
1773 | case AC_JACK_LINE_IN: | ||
1774 | if (loc == AC_JACK_LOC_FRONT) | ||
1775 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; | ||
1776 | else | ||
1777 | cfg->input_pins[AUTO_PIN_LINE] = nid; | ||
1778 | break; | ||
1779 | case AC_JACK_CD: | ||
1780 | cfg->input_pins[AUTO_PIN_CD] = nid; | ||
1781 | break; | ||
1782 | case AC_JACK_AUX: | ||
1783 | cfg->input_pins[AUTO_PIN_AUX] = nid; | ||
1784 | break; | ||
1785 | case AC_JACK_SPDIF_OUT: | ||
1786 | cfg->dig_out_pin = nid; | ||
1787 | break; | ||
1788 | case AC_JACK_SPDIF_IN: | ||
1789 | cfg->dig_in_pin = nid; | ||
1790 | break; | ||
1791 | } | ||
1792 | } | ||
1793 | |||
1794 | /* sort by sequence */ | ||
1795 | for (i = 0; i < cfg->line_outs; i++) | ||
1796 | for (j = i + 1; j < cfg->line_outs; j++) | ||
1797 | if (sequences[i] > sequences[j]) { | ||
1798 | seq = sequences[i]; | ||
1799 | sequences[i] = sequences[j]; | ||
1800 | sequences[j] = seq; | ||
1801 | nid = cfg->line_out_pins[i]; | ||
1802 | cfg->line_out_pins[i] = cfg->line_out_pins[j]; | ||
1803 | cfg->line_out_pins[j] = nid; | ||
1804 | } | ||
1805 | |||
1806 | /* Swap surround and CLFE: the association order is front/CLFE/surr/back */ | ||
1807 | if (cfg->line_outs >= 3) { | ||
1808 | nid = cfg->line_out_pins[1]; | ||
1809 | cfg->line_out_pins[1] = cfg->line_out_pins[2]; | ||
1810 | cfg->line_out_pins[2] = nid; | ||
1811 | } | ||
1812 | |||
1813 | return 0; | ||
1814 | } | ||
1815 | |||
1720 | #ifdef CONFIG_PM | 1816 | #ifdef CONFIG_PM |
1721 | /* | 1817 | /* |
1722 | * power management | 1818 | * power management |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index c9e9dc9c7c98..dd0d99d2ad27 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -75,6 +75,9 @@ enum { | |||
75 | #define AC_VERB_GET_DIGI_CONVERT 0x0f0d | 75 | #define AC_VERB_GET_DIGI_CONVERT 0x0f0d |
76 | #define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f | 76 | #define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f |
77 | /* f10-f1a: GPIO */ | 77 | /* f10-f1a: GPIO */ |
78 | #define AC_VERB_GET_GPIO_DATA 0x0f15 | ||
79 | #define AC_VERB_GET_GPIO_MASK 0x0f16 | ||
80 | #define AC_VERB_GET_GPIO_DIRECTION 0x0f17 | ||
78 | #define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c | 81 | #define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c |
79 | 82 | ||
80 | /* | 83 | /* |
@@ -97,6 +100,9 @@ enum { | |||
97 | #define AC_VERB_SET_DIGI_CONVERT_1 0x70d | 100 | #define AC_VERB_SET_DIGI_CONVERT_1 0x70d |
98 | #define AC_VERB_SET_DIGI_CONVERT_2 0x70e | 101 | #define AC_VERB_SET_DIGI_CONVERT_2 0x70e |
99 | #define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f | 102 | #define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f |
103 | #define AC_VERB_SET_GPIO_DATA 0x715 | ||
104 | #define AC_VERB_SET_GPIO_MASK 0x716 | ||
105 | #define AC_VERB_SET_GPIO_DIRECTION 0x717 | ||
100 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c | 106 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c |
101 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d | 107 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d |
102 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e | 108 | #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e |
@@ -176,16 +182,15 @@ enum { | |||
176 | #define AC_PINCAP_OUT (1<<4) /* output capable */ | 182 | #define AC_PINCAP_OUT (1<<4) /* output capable */ |
177 | #define AC_PINCAP_IN (1<<5) /* input capable */ | 183 | #define AC_PINCAP_IN (1<<5) /* input capable */ |
178 | #define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */ | 184 | #define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */ |
179 | #define AC_PINCAP_VREF (7<<8) | 185 | #define AC_PINCAP_VREF (0x37<<8) |
180 | #define AC_PINCAP_VREF_SHIFT 8 | 186 | #define AC_PINCAP_VREF_SHIFT 8 |
181 | #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ | 187 | #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ |
182 | /* Vref status (used in pin cap and pin ctl) */ | 188 | /* Vref status (used in pin cap) */ |
183 | #define AC_PIN_VREF_HIZ (1<<0) /* Hi-Z */ | 189 | #define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */ |
184 | #define AC_PIN_VREF_50 (1<<1) /* 50% */ | 190 | #define AC_PINCAP_VREF_50 (1<<1) /* 50% */ |
185 | #define AC_PIN_VREF_GRD (1<<2) /* ground */ | 191 | #define AC_PINCAP_VREF_GRD (1<<2) /* ground */ |
186 | #define AC_PIN_VREF_80 (1<<4) /* 80% */ | 192 | #define AC_PINCAP_VREF_80 (1<<4) /* 80% */ |
187 | #define AC_PIN_VREF_100 (1<<5) /* 100% */ | 193 | #define AC_PINCAP_VREF_100 (1<<5) /* 100% */ |
188 | |||
189 | 194 | ||
190 | /* Amplifier capabilities */ | 195 | /* Amplifier capabilities */ |
191 | #define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */ | 196 | #define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */ |
@@ -248,14 +253,24 @@ enum { | |||
248 | 253 | ||
249 | /* Pin widget control - 8bit */ | 254 | /* Pin widget control - 8bit */ |
250 | #define AC_PINCTL_VREFEN (0x7<<0) | 255 | #define AC_PINCTL_VREFEN (0x7<<0) |
256 | #define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ | ||
257 | #define AC_PINCTL_VREF_50 1 /* 50% */ | ||
258 | #define AC_PINCTL_VREF_GRD 2 /* ground */ | ||
259 | #define AC_PINCTL_VREF_80 4 /* 80% */ | ||
260 | #define AC_PINCTL_VREF_100 5 /* 100% */ | ||
251 | #define AC_PINCTL_IN_EN (1<<5) | 261 | #define AC_PINCTL_IN_EN (1<<5) |
252 | #define AC_PINCTL_OUT_EN (1<<6) | 262 | #define AC_PINCTL_OUT_EN (1<<6) |
253 | #define AC_PINCTL_HP_EN (1<<7) | 263 | #define AC_PINCTL_HP_EN (1<<7) |
254 | 264 | ||
265 | /* Unsolicited response - 8bit */ | ||
266 | #define AC_USRSP_EN (1<<7) | ||
267 | |||
255 | /* configuration default - 32bit */ | 268 | /* configuration default - 32bit */ |
256 | #define AC_DEFCFG_SEQUENCE (0xf<<0) | 269 | #define AC_DEFCFG_SEQUENCE (0xf<<0) |
257 | #define AC_DEFCFG_DEF_ASSOC (0xf<<4) | 270 | #define AC_DEFCFG_DEF_ASSOC (0xf<<4) |
271 | #define AC_DEFCFG_ASSOC_SHIFT 4 | ||
258 | #define AC_DEFCFG_MISC (0xf<<8) | 272 | #define AC_DEFCFG_MISC (0xf<<8) |
273 | #define AC_DEFCFG_MISC_SHIFT 8 | ||
259 | #define AC_DEFCFG_COLOR (0xf<<12) | 274 | #define AC_DEFCFG_COLOR (0xf<<12) |
260 | #define AC_DEFCFG_COLOR_SHIFT 12 | 275 | #define AC_DEFCFG_COLOR_SHIFT 12 |
261 | #define AC_DEFCFG_CONN_TYPE (0xf<<16) | 276 | #define AC_DEFCFG_CONN_TYPE (0xf<<16) |
@@ -413,7 +428,7 @@ struct hda_bus { | |||
413 | 428 | ||
414 | /* codec linked list */ | 429 | /* codec linked list */ |
415 | struct list_head codec_list; | 430 | struct list_head codec_list; |
416 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS]; /* caddr -> codec */ | 431 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */ |
417 | 432 | ||
418 | struct semaphore cmd_mutex; | 433 | struct semaphore cmd_mutex; |
419 | 434 | ||
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 69f7b6c4cf83..2d046abb5911 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -44,7 +44,7 @@ struct hda_gnode { | |||
44 | struct list_head list; | 44 | struct list_head list; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | /* pathc-specific record */ | 47 | /* patch-specific record */ |
48 | struct hda_gspec { | 48 | struct hda_gspec { |
49 | struct hda_gnode *dac_node; /* DAC node */ | 49 | struct hda_gnode *dac_node; /* DAC node */ |
50 | struct hda_gnode *out_pin_node; /* Output pin (Line-Out) node */ | 50 | struct hda_gnode *out_pin_node; /* Output pin (Line-Out) node */ |
@@ -68,8 +68,8 @@ struct hda_gspec { | |||
68 | /* | 68 | /* |
69 | * retrieve the default device type from the default config value | 69 | * retrieve the default device type from the default config value |
70 | */ | 70 | */ |
71 | #define get_defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | 71 | #define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) |
72 | #define get_defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | 72 | #define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) |
73 | 73 | ||
74 | /* | 74 | /* |
75 | * destructor | 75 | * destructor |
@@ -323,7 +323,7 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, | |||
323 | if (! (node->pin_caps & AC_PINCAP_OUT)) | 323 | if (! (node->pin_caps & AC_PINCAP_OUT)) |
324 | continue; | 324 | continue; |
325 | if (jack_type >= 0) { | 325 | if (jack_type >= 0) { |
326 | if (jack_type != get_defcfg_type(node)) | 326 | if (jack_type != defcfg_type(node)) |
327 | continue; | 327 | continue; |
328 | if (node->wid_caps & AC_WCAP_DIGITAL) | 328 | if (node->wid_caps & AC_WCAP_DIGITAL) |
329 | continue; /* skip SPDIF */ | 329 | continue; /* skip SPDIF */ |
@@ -418,15 +418,15 @@ static int capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc | |||
418 | */ | 418 | */ |
419 | static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) | 419 | static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) |
420 | { | 420 | { |
421 | unsigned int location = get_defcfg_location(node); | 421 | unsigned int location = defcfg_location(node); |
422 | switch (get_defcfg_type(node)) { | 422 | switch (defcfg_type(node)) { |
423 | case AC_JACK_LINE_IN: | 423 | case AC_JACK_LINE_IN: |
424 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) | 424 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) |
425 | return "Front Line"; | 425 | return "Front Line"; |
426 | return "Line"; | 426 | return "Line"; |
427 | case AC_JACK_CD: | 427 | case AC_JACK_CD: |
428 | if (pinctl) | 428 | if (pinctl) |
429 | *pinctl |= AC_PIN_VREF_GRD; | 429 | *pinctl |= AC_PINCTL_VREF_GRD; |
430 | return "CD"; | 430 | return "CD"; |
431 | case AC_JACK_AUX: | 431 | case AC_JACK_AUX: |
432 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) | 432 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 959953ca320a..288ab0764830 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -51,6 +51,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | |||
51 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | 51 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; |
52 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 52 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
53 | static char *model[SNDRV_CARDS]; | 53 | static char *model[SNDRV_CARDS]; |
54 | static int position_fix[SNDRV_CARDS]; | ||
54 | 55 | ||
55 | module_param_array(index, int, NULL, 0444); | 56 | module_param_array(index, int, NULL, 0444); |
56 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); | 57 | MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); |
@@ -60,12 +61,17 @@ module_param_array(enable, bool, NULL, 0444); | |||
60 | MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); | 61 | MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); |
61 | module_param_array(model, charp, NULL, 0444); | 62 | module_param_array(model, charp, NULL, 0444); |
62 | MODULE_PARM_DESC(model, "Use the given board model."); | 63 | MODULE_PARM_DESC(model, "Use the given board model."); |
64 | module_param_array(position_fix, int, NULL, 0444); | ||
65 | MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)."); | ||
63 | 66 | ||
64 | MODULE_LICENSE("GPL"); | 67 | MODULE_LICENSE("GPL"); |
65 | MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," | 68 | MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," |
66 | "{Intel, ICH6M}," | 69 | "{Intel, ICH6M}," |
67 | "{Intel, ICH7}," | 70 | "{Intel, ICH7}," |
68 | "{Intel, ESB2}}"); | 71 | "{Intel, ESB2}," |
72 | "{ATI, SB450}," | ||
73 | "{VIA, VT8251}," | ||
74 | "{VIA, VT8237A}}"); | ||
69 | MODULE_DESCRIPTION("Intel HDA driver"); | 75 | MODULE_DESCRIPTION("Intel HDA driver"); |
70 | 76 | ||
71 | #define SFX "hda-intel: " | 77 | #define SFX "hda-intel: " |
@@ -150,7 +156,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
150 | 156 | ||
151 | /* STATESTS int mask: SD2,SD1,SD0 */ | 157 | /* STATESTS int mask: SD2,SD1,SD0 */ |
152 | #define STATESTS_INT_MASK 0x07 | 158 | #define STATESTS_INT_MASK 0x07 |
153 | #define AZX_MAX_CODECS 3 | 159 | #define AZX_MAX_CODECS 4 |
154 | 160 | ||
155 | /* SD_CTL bits */ | 161 | /* SD_CTL bits */ |
156 | #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ | 162 | #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ |
@@ -172,6 +178,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
172 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ | 178 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ |
173 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ | 179 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ |
174 | 180 | ||
181 | /* GCTL unsolicited response enable bit */ | ||
182 | #define ICH6_GCTL_UREN (1<<8) | ||
183 | |||
175 | /* GCTL reset bit */ | 184 | /* GCTL reset bit */ |
176 | #define ICH6_GCTL_RESET (1<<0) | 185 | #define ICH6_GCTL_RESET (1<<0) |
177 | 186 | ||
@@ -183,6 +192,18 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
183 | #define ICH6_MAX_CORB_ENTRIES 256 | 192 | #define ICH6_MAX_CORB_ENTRIES 256 |
184 | #define ICH6_MAX_RIRB_ENTRIES 256 | 193 | #define ICH6_MAX_RIRB_ENTRIES 256 |
185 | 194 | ||
195 | /* position fix mode */ | ||
196 | enum { | ||
197 | POS_FIX_FIFO, | ||
198 | POS_FIX_NONE, | ||
199 | POS_FIX_POSBUF | ||
200 | }; | ||
201 | |||
202 | /* Defines for ATI HD Audio support in SB450 south bridge */ | ||
203 | #define ATI_SB450_HDAUDIO_PCI_DEVICE_ID 0x437b | ||
204 | #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 | ||
205 | #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 | ||
206 | |||
186 | 207 | ||
187 | /* | 208 | /* |
188 | * Use CORB/RIRB for communication from/to codecs. | 209 | * Use CORB/RIRB for communication from/to codecs. |
@@ -191,12 +212,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
191 | #define USE_CORB_RIRB | 212 | #define USE_CORB_RIRB |
192 | 213 | ||
193 | /* | 214 | /* |
194 | * Define this if use the position buffer instead of reading SD_LPIB | ||
195 | * It's not used as default since SD_LPIB seems to give more accurate position | ||
196 | */ | ||
197 | /* #define USE_POSBUF */ | ||
198 | |||
199 | /* | ||
200 | */ | 215 | */ |
201 | 216 | ||
202 | typedef struct snd_azx azx_t; | 217 | typedef struct snd_azx azx_t; |
@@ -271,6 +286,10 @@ struct snd_azx { | |||
271 | struct snd_dma_buffer bdl; | 286 | struct snd_dma_buffer bdl; |
272 | struct snd_dma_buffer rb; | 287 | struct snd_dma_buffer rb; |
273 | struct snd_dma_buffer posbuf; | 288 | struct snd_dma_buffer posbuf; |
289 | |||
290 | /* flags */ | ||
291 | int position_fix; | ||
292 | unsigned int initialized: 1; | ||
274 | }; | 293 | }; |
275 | 294 | ||
276 | /* | 295 | /* |
@@ -546,6 +565,9 @@ static int azx_reset(azx_t *chip) | |||
546 | return -EBUSY; | 565 | return -EBUSY; |
547 | } | 566 | } |
548 | 567 | ||
568 | /* Accept unsolicited responses */ | ||
569 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN); | ||
570 | |||
549 | /* detect codecs */ | 571 | /* detect codecs */ |
550 | if (! chip->codec_mask) { | 572 | if (! chip->codec_mask) { |
551 | chip->codec_mask = azx_readw(chip, STATESTS); | 573 | chip->codec_mask = azx_readw(chip, STATESTS); |
@@ -638,7 +660,7 @@ static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev) | |||
638 | */ | 660 | */ |
639 | static void azx_init_chip(azx_t *chip) | 661 | static void azx_init_chip(azx_t *chip) |
640 | { | 662 | { |
641 | unsigned char tcsel_reg; | 663 | unsigned char tcsel_reg, ati_misc_cntl2; |
642 | 664 | ||
643 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) | 665 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) |
644 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS | 666 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS |
@@ -657,11 +679,20 @@ static void azx_init_chip(azx_t *chip) | |||
657 | /* initialize the codec command I/O */ | 679 | /* initialize the codec command I/O */ |
658 | azx_init_cmd_io(chip); | 680 | azx_init_cmd_io(chip); |
659 | 681 | ||
660 | #ifdef USE_POSBUF | 682 | if (chip->position_fix == POS_FIX_POSBUF) { |
661 | /* program the position buffer */ | 683 | /* program the position buffer */ |
662 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); | 684 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); |
663 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); | 685 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); |
664 | #endif | 686 | } |
687 | |||
688 | /* For ATI SB450 azalia HD audio, we need to enable snoop */ | ||
689 | if (chip->pci->vendor == PCI_VENDOR_ID_ATI && | ||
690 | chip->pci->device == ATI_SB450_HDAUDIO_PCI_DEVICE_ID) { | ||
691 | pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | ||
692 | &ati_misc_cntl2); | ||
693 | pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | ||
694 | (ati_misc_cntl2 & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP); | ||
695 | } | ||
665 | } | 696 | } |
666 | 697 | ||
667 | 698 | ||
@@ -791,11 +822,12 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev) | |||
791 | /* upper BDL address */ | 822 | /* upper BDL address */ |
792 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); | 823 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); |
793 | 824 | ||
794 | #ifdef USE_POSBUF | 825 | if (chip->position_fix == POS_FIX_POSBUF) { |
795 | /* enable the position buffer */ | 826 | /* enable the position buffer */ |
796 | if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 827 | if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) |
797 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); | 828 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); |
798 | #endif | 829 | } |
830 | |||
799 | /* set the interrupt enable bits in the descriptor control register */ | 831 | /* set the interrupt enable bits in the descriptor control register */ |
800 | azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); | 832 | azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); |
801 | 833 | ||
@@ -1036,16 +1068,20 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | |||
1036 | 1068 | ||
1037 | static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream) | 1069 | static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream) |
1038 | { | 1070 | { |
1071 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
1072 | azx_t *chip = apcm->chip; | ||
1039 | azx_dev_t *azx_dev = get_azx_dev(substream); | 1073 | azx_dev_t *azx_dev = get_azx_dev(substream); |
1040 | unsigned int pos; | 1074 | unsigned int pos; |
1041 | 1075 | ||
1042 | #ifdef USE_POSBUF | 1076 | if (chip->position_fix == POS_FIX_POSBUF) { |
1043 | /* use the position buffer */ | 1077 | /* use the position buffer */ |
1044 | pos = *azx_dev->posbuf; | 1078 | pos = *azx_dev->posbuf; |
1045 | #else | 1079 | } else { |
1046 | /* read LPIB */ | 1080 | /* read LPIB */ |
1047 | pos = azx_sd_readl(azx_dev, SD_LPIB) + azx_dev->fifo_size; | 1081 | pos = azx_sd_readl(azx_dev, SD_LPIB); |
1048 | #endif | 1082 | if (chip->position_fix == POS_FIX_FIFO) |
1083 | pos += azx_dev->fifo_size; | ||
1084 | } | ||
1049 | if (pos >= azx_dev->bufsize) | 1085 | if (pos >= azx_dev->bufsize) |
1050 | pos = 0; | 1086 | pos = 0; |
1051 | return bytes_to_frames(substream->runtime, pos); | 1087 | return bytes_to_frames(substream->runtime, pos); |
@@ -1155,9 +1191,8 @@ static int __devinit azx_init_stream(azx_t *chip) | |||
1155 | azx_dev_t *azx_dev = &chip->azx_dev[i]; | 1191 | azx_dev_t *azx_dev = &chip->azx_dev[i]; |
1156 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); | 1192 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); |
1157 | azx_dev->bdl_addr = chip->bdl.addr + off; | 1193 | azx_dev->bdl_addr = chip->bdl.addr + off; |
1158 | #ifdef USE_POSBUF | 1194 | if (chip->position_fix == POS_FIX_POSBUF) |
1159 | azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); | 1195 | azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); |
1160 | #endif | ||
1161 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | 1196 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ |
1162 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); | 1197 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); |
1163 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ | 1198 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ |
@@ -1207,7 +1242,7 @@ static int azx_resume(snd_card_t *card) | |||
1207 | */ | 1242 | */ |
1208 | static int azx_free(azx_t *chip) | 1243 | static int azx_free(azx_t *chip) |
1209 | { | 1244 | { |
1210 | if (chip->remap_addr) { | 1245 | if (chip->initialized) { |
1211 | int i; | 1246 | int i; |
1212 | 1247 | ||
1213 | for (i = 0; i < MAX_ICH6_DEV; i++) | 1248 | for (i = 0; i < MAX_ICH6_DEV; i++) |
@@ -1237,10 +1272,8 @@ static int azx_free(azx_t *chip) | |||
1237 | snd_dma_free_pages(&chip->bdl); | 1272 | snd_dma_free_pages(&chip->bdl); |
1238 | if (chip->rb.area) | 1273 | if (chip->rb.area) |
1239 | snd_dma_free_pages(&chip->rb); | 1274 | snd_dma_free_pages(&chip->rb); |
1240 | #ifdef USE_POSBUF | ||
1241 | if (chip->posbuf.area) | 1275 | if (chip->posbuf.area) |
1242 | snd_dma_free_pages(&chip->posbuf); | 1276 | snd_dma_free_pages(&chip->posbuf); |
1243 | #endif | ||
1244 | pci_release_regions(chip->pci); | 1277 | pci_release_regions(chip->pci); |
1245 | pci_disable_device(chip->pci); | 1278 | pci_disable_device(chip->pci); |
1246 | kfree(chip); | 1279 | kfree(chip); |
@@ -1256,7 +1289,8 @@ static int azx_dev_free(snd_device_t *device) | |||
1256 | /* | 1289 | /* |
1257 | * constructor | 1290 | * constructor |
1258 | */ | 1291 | */ |
1259 | static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip) | 1292 | static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, |
1293 | int posfix, azx_t **rchip) | ||
1260 | { | 1294 | { |
1261 | azx_t *chip; | 1295 | azx_t *chip; |
1262 | int err = 0; | 1296 | int err = 0; |
@@ -1283,6 +1317,8 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r | |||
1283 | chip->pci = pci; | 1317 | chip->pci = pci; |
1284 | chip->irq = -1; | 1318 | chip->irq = -1; |
1285 | 1319 | ||
1320 | chip->position_fix = posfix; | ||
1321 | |||
1286 | if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { | 1322 | if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { |
1287 | kfree(chip); | 1323 | kfree(chip); |
1288 | pci_disable_device(pci); | 1324 | pci_disable_device(pci); |
@@ -1314,14 +1350,14 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r | |||
1314 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); | 1350 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); |
1315 | goto errout; | 1351 | goto errout; |
1316 | } | 1352 | } |
1317 | #ifdef USE_POSBUF | 1353 | if (chip->position_fix == POS_FIX_POSBUF) { |
1318 | /* allocate memory for the position buffer */ | 1354 | /* allocate memory for the position buffer */ |
1319 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 1355 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), |
1320 | MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) { | 1356 | MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) { |
1321 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); | 1357 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); |
1322 | goto errout; | 1358 | goto errout; |
1359 | } | ||
1323 | } | 1360 | } |
1324 | #endif | ||
1325 | /* allocate CORB/RIRB */ | 1361 | /* allocate CORB/RIRB */ |
1326 | if ((err = azx_alloc_cmd_io(chip)) < 0) | 1362 | if ((err = azx_alloc_cmd_io(chip)) < 0) |
1327 | goto errout; | 1363 | goto errout; |
@@ -1332,6 +1368,8 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r | |||
1332 | /* initialize chip */ | 1368 | /* initialize chip */ |
1333 | azx_init_chip(chip); | 1369 | azx_init_chip(chip); |
1334 | 1370 | ||
1371 | chip->initialized = 1; | ||
1372 | |||
1335 | /* codec detection */ | 1373 | /* codec detection */ |
1336 | if (! chip->codec_mask) { | 1374 | if (! chip->codec_mask) { |
1337 | snd_printk(KERN_ERR SFX "no codecs found!\n"); | 1375 | snd_printk(KERN_ERR SFX "no codecs found!\n"); |
@@ -1372,7 +1410,7 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * | |||
1372 | return -ENOMEM; | 1410 | return -ENOMEM; |
1373 | } | 1411 | } |
1374 | 1412 | ||
1375 | if ((err = azx_create(card, pci, &chip)) < 0) { | 1413 | if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) { |
1376 | snd_card_free(card); | 1414 | snd_card_free(card); |
1377 | return err; | 1415 | return err; |
1378 | } | 1416 | } |
@@ -1424,6 +1462,9 @@ static struct pci_device_id azx_ids[] = { | |||
1424 | { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */ | 1462 | { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */ |
1425 | { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */ | 1463 | { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */ |
1426 | { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */ | 1464 | { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */ |
1465 | { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */ | ||
1466 | { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */ | ||
1467 | { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ALI 5461? */ | ||
1427 | { 0, } | 1468 | { 0, } |
1428 | }; | 1469 | }; |
1429 | MODULE_DEVICE_TABLE(pci, azx_ids); | 1470 | MODULE_DEVICE_TABLE(pci, azx_ids); |
@@ -1439,7 +1480,7 @@ static struct pci_driver driver = { | |||
1439 | 1480 | ||
1440 | static int __init alsa_card_azx_init(void) | 1481 | static int __init alsa_card_azx_init(void) |
1441 | { | 1482 | { |
1442 | return pci_module_init(&driver); | 1483 | return pci_register_driver(&driver); |
1443 | } | 1484 | } |
1444 | 1485 | ||
1445 | static void __exit alsa_card_azx_exit(void) | 1486 | static void __exit alsa_card_azx_exit(void) |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 7c7b849875a0..810cfd2d9bba 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -126,11 +126,11 @@ static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; } | |||
126 | struct hda_board_config { | 126 | struct hda_board_config { |
127 | const char *modelname; | 127 | const char *modelname; |
128 | int config; | 128 | int config; |
129 | unsigned short pci_vendor; | 129 | unsigned short pci_subvendor; |
130 | unsigned short pci_device; | 130 | unsigned short pci_subdevice; |
131 | }; | 131 | }; |
132 | 132 | ||
133 | int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl); | 133 | int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl); |
134 | int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew); | 134 | int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew); |
135 | 135 | ||
136 | /* | 136 | /* |
@@ -158,4 +158,35 @@ struct hda_bus_unsolicited { | |||
158 | struct work_struct work; | 158 | struct work_struct work; |
159 | }; | 159 | }; |
160 | 160 | ||
161 | /* | ||
162 | * Helper for automatic ping configuration | ||
163 | */ | ||
164 | |||
165 | enum { | ||
166 | AUTO_PIN_MIC, | ||
167 | AUTO_PIN_FRONT_MIC, | ||
168 | AUTO_PIN_LINE, | ||
169 | AUTO_PIN_FRONT_LINE, | ||
170 | AUTO_PIN_CD, | ||
171 | AUTO_PIN_AUX, | ||
172 | AUTO_PIN_LAST | ||
173 | }; | ||
174 | |||
175 | struct auto_pin_cfg { | ||
176 | int line_outs; | ||
177 | hda_nid_t line_out_pins[4]; /* sorted in the order of Front/Surr/CLFE/Side */ | ||
178 | hda_nid_t hp_pin; | ||
179 | hda_nid_t input_pins[AUTO_PIN_LAST]; | ||
180 | hda_nid_t dig_out_pin; | ||
181 | hda_nid_t dig_in_pin; | ||
182 | }; | ||
183 | |||
184 | #define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) | ||
185 | #define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT) | ||
186 | #define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | ||
187 | #define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE) | ||
188 | #define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | ||
189 | |||
190 | int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg); | ||
191 | |||
161 | #endif /* __SOUND_HDA_LOCAL_H */ | 192 | #endif /* __SOUND_HDA_LOCAL_H */ |
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h index cf6abce42bc9..a5de684b6944 100644 --- a/sound/pci/hda/hda_patch.h +++ b/sound/pci/hda/hda_patch.h | |||
@@ -8,10 +8,13 @@ extern struct hda_codec_preset snd_hda_preset_realtek[]; | |||
8 | extern struct hda_codec_preset snd_hda_preset_cmedia[]; | 8 | extern struct hda_codec_preset snd_hda_preset_cmedia[]; |
9 | /* Analog Devices codecs */ | 9 | /* Analog Devices codecs */ |
10 | extern struct hda_codec_preset snd_hda_preset_analog[]; | 10 | extern struct hda_codec_preset snd_hda_preset_analog[]; |
11 | /* SigmaTel codecs */ | ||
12 | extern struct hda_codec_preset snd_hda_preset_sigmatel[]; | ||
11 | 13 | ||
12 | static const struct hda_codec_preset *hda_preset_tables[] = { | 14 | static const struct hda_codec_preset *hda_preset_tables[] = { |
13 | snd_hda_preset_realtek, | 15 | snd_hda_preset_realtek, |
14 | snd_hda_preset_cmedia, | 16 | snd_hda_preset_cmedia, |
15 | snd_hda_preset_analog, | 17 | snd_hda_preset_analog, |
18 | snd_hda_preset_sigmatel, | ||
16 | NULL | 19 | NULL |
17 | }; | 20 | }; |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 4d5db7faad8d..de1217bd8e68 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -68,21 +68,27 @@ static void print_amp_caps(snd_info_buffer_t *buffer, | |||
68 | 68 | ||
69 | static void print_amp_vals(snd_info_buffer_t *buffer, | 69 | static void print_amp_vals(snd_info_buffer_t *buffer, |
70 | struct hda_codec *codec, hda_nid_t nid, | 70 | struct hda_codec *codec, hda_nid_t nid, |
71 | int dir, int stereo) | 71 | int dir, int stereo, int indices) |
72 | { | 72 | { |
73 | unsigned int val; | 73 | unsigned int val; |
74 | if (stereo) { | 74 | int i; |
75 | |||
76 | if (dir == HDA_OUTPUT) | ||
77 | dir = AC_AMP_GET_OUTPUT; | ||
78 | else | ||
79 | dir = AC_AMP_GET_INPUT; | ||
80 | for (i = 0; i < indices; i++) { | ||
81 | snd_iprintf(buffer, " ["); | ||
82 | if (stereo) { | ||
83 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, | ||
84 | AC_AMP_GET_LEFT | dir | i); | ||
85 | snd_iprintf(buffer, "0x%02x ", val); | ||
86 | } | ||
75 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, | 87 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, |
76 | AC_AMP_GET_LEFT | | 88 | AC_AMP_GET_RIGHT | dir | i); |
77 | (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : | 89 | snd_iprintf(buffer, "0x%02x]", val); |
78 | AC_AMP_GET_INPUT)); | ||
79 | snd_iprintf(buffer, "0x%02x ", val); | ||
80 | } | 90 | } |
81 | val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, | 91 | snd_iprintf(buffer, "\n"); |
82 | AC_AMP_GET_RIGHT | | ||
83 | (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : | ||
84 | AC_AMP_GET_INPUT)); | ||
85 | snd_iprintf(buffer, "0x%02x\n", val); | ||
86 | } | 92 | } |
87 | 93 | ||
88 | static void print_pcm_caps(snd_info_buffer_t *buffer, | 94 | static void print_pcm_caps(snd_info_buffer_t *buffer, |
@@ -157,6 +163,7 @@ static const char *get_jack_color(u32 cfg) | |||
157 | static void print_pin_caps(snd_info_buffer_t *buffer, | 163 | static void print_pin_caps(snd_info_buffer_t *buffer, |
158 | struct hda_codec *codec, hda_nid_t nid) | 164 | struct hda_codec *codec, hda_nid_t nid) |
159 | { | 165 | { |
166 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; | ||
160 | static char *jack_types[16] = { | 167 | static char *jack_types[16] = { |
161 | "Line Out", "Speaker", "HP Out", "CD", | 168 | "Line Out", "Speaker", "HP Out", "CD", |
162 | "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", | 169 | "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", |
@@ -176,7 +183,8 @@ static void print_pin_caps(snd_info_buffer_t *buffer, | |||
176 | snd_iprintf(buffer, " HP"); | 183 | snd_iprintf(buffer, " HP"); |
177 | snd_iprintf(buffer, "\n"); | 184 | snd_iprintf(buffer, "\n"); |
178 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 185 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); |
179 | snd_iprintf(buffer, " Pin Default 0x%08x: %s at %s %s\n", caps, | 186 | snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, |
187 | jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], | ||
180 | jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT], | 188 | jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT], |
181 | jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3], | 189 | jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3], |
182 | get_jack_location(caps)); | 190 | get_jack_location(caps)); |
@@ -215,6 +223,9 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer) | |||
215 | unsigned int wid_caps = snd_hda_param_read(codec, nid, | 223 | unsigned int wid_caps = snd_hda_param_read(codec, nid, |
216 | AC_PAR_AUDIO_WIDGET_CAP); | 224 | AC_PAR_AUDIO_WIDGET_CAP); |
217 | unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | 225 | unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; |
226 | int conn_len = 0; | ||
227 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; | ||
228 | |||
218 | snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid, | 229 | snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid, |
219 | get_wid_type_name(wid_type), wid_caps); | 230 | get_wid_type_name(wid_type), wid_caps); |
220 | if (wid_caps & AC_WCAP_STEREO) | 231 | if (wid_caps & AC_WCAP_STEREO) |
@@ -229,19 +240,23 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer) | |||
229 | snd_iprintf(buffer, " Amp-Out"); | 240 | snd_iprintf(buffer, " Amp-Out"); |
230 | snd_iprintf(buffer, "\n"); | 241 | snd_iprintf(buffer, "\n"); |
231 | 242 | ||
243 | if (wid_caps & AC_WCAP_CONN_LIST) | ||
244 | conn_len = snd_hda_get_connections(codec, nid, conn, | ||
245 | HDA_MAX_CONNECTIONS); | ||
246 | |||
232 | if (wid_caps & AC_WCAP_IN_AMP) { | 247 | if (wid_caps & AC_WCAP_IN_AMP) { |
233 | snd_iprintf(buffer, " Amp-In caps: "); | 248 | snd_iprintf(buffer, " Amp-In caps: "); |
234 | print_amp_caps(buffer, codec, nid, HDA_INPUT); | 249 | print_amp_caps(buffer, codec, nid, HDA_INPUT); |
235 | snd_iprintf(buffer, " Amp-In vals: "); | 250 | snd_iprintf(buffer, " Amp-In vals: "); |
236 | print_amp_vals(buffer, codec, nid, HDA_INPUT, | 251 | print_amp_vals(buffer, codec, nid, HDA_INPUT, |
237 | wid_caps & AC_WCAP_STEREO); | 252 | wid_caps & AC_WCAP_STEREO, conn_len); |
238 | } | 253 | } |
239 | if (wid_caps & AC_WCAP_OUT_AMP) { | 254 | if (wid_caps & AC_WCAP_OUT_AMP) { |
240 | snd_iprintf(buffer, " Amp-Out caps: "); | 255 | snd_iprintf(buffer, " Amp-Out caps: "); |
241 | print_amp_caps(buffer, codec, nid, HDA_OUTPUT); | 256 | print_amp_caps(buffer, codec, nid, HDA_OUTPUT); |
242 | snd_iprintf(buffer, " Amp-Out vals: "); | 257 | snd_iprintf(buffer, " Amp-Out vals: "); |
243 | print_amp_vals(buffer, codec, nid, HDA_OUTPUT, | 258 | print_amp_vals(buffer, codec, nid, HDA_OUTPUT, |
244 | wid_caps & AC_WCAP_STEREO); | 259 | wid_caps & AC_WCAP_STEREO, 1); |
245 | } | 260 | } |
246 | 261 | ||
247 | if (wid_type == AC_WID_PIN) { | 262 | if (wid_type == AC_WID_PIN) { |
@@ -265,14 +280,17 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer) | |||
265 | } | 280 | } |
266 | 281 | ||
267 | if (wid_caps & AC_WCAP_CONN_LIST) { | 282 | if (wid_caps & AC_WCAP_CONN_LIST) { |
268 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; | 283 | int c, curr = -1; |
269 | int c, conn_len; | 284 | if (conn_len > 1 && wid_type != AC_WID_AUD_MIX) |
270 | conn_len = snd_hda_get_connections(codec, nid, conn, | 285 | curr = snd_hda_codec_read(codec, nid, 0, |
271 | HDA_MAX_CONNECTIONS); | 286 | AC_VERB_GET_CONNECT_SEL, 0); |
272 | snd_iprintf(buffer, " Connection: %d\n", conn_len); | 287 | snd_iprintf(buffer, " Connection: %d\n", conn_len); |
273 | snd_iprintf(buffer, " "); | 288 | snd_iprintf(buffer, " "); |
274 | for (c = 0; c < conn_len; c++) | 289 | for (c = 0; c < conn_len; c++) { |
275 | snd_iprintf(buffer, " 0x%02x", conn[c]); | 290 | snd_iprintf(buffer, " 0x%02x", conn[c]); |
291 | if (c == curr) | ||
292 | snd_iprintf(buffer, "*"); | ||
293 | } | ||
276 | snd_iprintf(buffer, "\n"); | 294 | snd_iprintf(buffer, "\n"); |
277 | } | 295 | } |
278 | } | 296 | } |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 75d23849f71a..2fd05bb84136 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * HD audio interface patch for AD1986A | 2 | * HD audio interface patch for AD1981HD, AD1983, AD1986A |
3 | * | 3 | * |
4 | * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de> | 4 | * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de> |
5 | * | 5 | * |
@@ -27,13 +27,239 @@ | |||
27 | #include "hda_codec.h" | 27 | #include "hda_codec.h" |
28 | #include "hda_local.h" | 28 | #include "hda_local.h" |
29 | 29 | ||
30 | struct ad1986a_spec { | 30 | struct ad198x_spec { |
31 | struct semaphore amp_mutex; /* PCM volume/mute control mutex */ | 31 | struct semaphore amp_mutex; /* PCM volume/mute control mutex */ |
32 | struct hda_multi_out multiout; /* playback */ | 32 | struct hda_multi_out multiout; /* playback */ |
33 | hda_nid_t adc_nid; | ||
34 | const struct hda_input_mux *input_mux; | ||
33 | unsigned int cur_mux; /* capture source */ | 35 | unsigned int cur_mux; /* capture source */ |
36 | unsigned int spdif_route; | ||
37 | snd_kcontrol_new_t *mixers; | ||
38 | const struct hda_verb *init_verbs; | ||
34 | struct hda_pcm pcm_rec[2]; /* PCM information */ | 39 | struct hda_pcm pcm_rec[2]; /* PCM information */ |
35 | }; | 40 | }; |
36 | 41 | ||
42 | /* | ||
43 | * input MUX handling (common part) | ||
44 | */ | ||
45 | static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
46 | { | ||
47 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
48 | struct ad198x_spec *spec = codec->spec; | ||
49 | |||
50 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | ||
51 | } | ||
52 | |||
53 | static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
54 | { | ||
55 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
56 | struct ad198x_spec *spec = codec->spec; | ||
57 | |||
58 | ucontrol->value.enumerated.item[0] = spec->cur_mux; | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
63 | { | ||
64 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
65 | struct ad198x_spec *spec = codec->spec; | ||
66 | |||
67 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
68 | spec->adc_nid, &spec->cur_mux); | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * initialization (common callbacks) | ||
73 | */ | ||
74 | static int ad198x_init(struct hda_codec *codec) | ||
75 | { | ||
76 | struct ad198x_spec *spec = codec->spec; | ||
77 | snd_hda_sequence_write(codec, spec->init_verbs); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int ad198x_build_controls(struct hda_codec *codec) | ||
82 | { | ||
83 | struct ad198x_spec *spec = codec->spec; | ||
84 | int err; | ||
85 | |||
86 | err = snd_hda_add_new_ctls(codec, spec->mixers); | ||
87 | if (err < 0) | ||
88 | return err; | ||
89 | if (spec->multiout.dig_out_nid) | ||
90 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | ||
91 | if (err < 0) | ||
92 | return err; | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Analog playback callbacks | ||
98 | */ | ||
99 | static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
100 | struct hda_codec *codec, | ||
101 | snd_pcm_substream_t *substream) | ||
102 | { | ||
103 | struct ad198x_spec *spec = codec->spec; | ||
104 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); | ||
105 | } | ||
106 | |||
107 | static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
108 | struct hda_codec *codec, | ||
109 | unsigned int stream_tag, | ||
110 | unsigned int format, | ||
111 | snd_pcm_substream_t *substream) | ||
112 | { | ||
113 | struct ad198x_spec *spec = codec->spec; | ||
114 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | ||
115 | format, substream); | ||
116 | } | ||
117 | |||
118 | static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
119 | struct hda_codec *codec, | ||
120 | snd_pcm_substream_t *substream) | ||
121 | { | ||
122 | struct ad198x_spec *spec = codec->spec; | ||
123 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Digital out | ||
128 | */ | ||
129 | static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
130 | struct hda_codec *codec, | ||
131 | snd_pcm_substream_t *substream) | ||
132 | { | ||
133 | struct ad198x_spec *spec = codec->spec; | ||
134 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
135 | } | ||
136 | |||
137 | static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
138 | struct hda_codec *codec, | ||
139 | snd_pcm_substream_t *substream) | ||
140 | { | ||
141 | struct ad198x_spec *spec = codec->spec; | ||
142 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * Analog capture | ||
147 | */ | ||
148 | static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
149 | struct hda_codec *codec, | ||
150 | unsigned int stream_tag, | ||
151 | unsigned int format, | ||
152 | snd_pcm_substream_t *substream) | ||
153 | { | ||
154 | struct ad198x_spec *spec = codec->spec; | ||
155 | snd_hda_codec_setup_stream(codec, spec->adc_nid, stream_tag, 0, format); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
160 | struct hda_codec *codec, | ||
161 | snd_pcm_substream_t *substream) | ||
162 | { | ||
163 | struct ad198x_spec *spec = codec->spec; | ||
164 | snd_hda_codec_setup_stream(codec, spec->adc_nid, 0, 0, 0); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | |||
169 | /* | ||
170 | */ | ||
171 | static struct hda_pcm_stream ad198x_pcm_analog_playback = { | ||
172 | .substreams = 1, | ||
173 | .channels_min = 2, | ||
174 | .channels_max = 6, | ||
175 | .nid = 0, /* fill later */ | ||
176 | .ops = { | ||
177 | .open = ad198x_playback_pcm_open, | ||
178 | .prepare = ad198x_playback_pcm_prepare, | ||
179 | .cleanup = ad198x_playback_pcm_cleanup | ||
180 | }, | ||
181 | }; | ||
182 | |||
183 | static struct hda_pcm_stream ad198x_pcm_analog_capture = { | ||
184 | .substreams = 2, | ||
185 | .channels_min = 2, | ||
186 | .channels_max = 2, | ||
187 | .nid = 0, /* fill later */ | ||
188 | .ops = { | ||
189 | .prepare = ad198x_capture_pcm_prepare, | ||
190 | .cleanup = ad198x_capture_pcm_cleanup | ||
191 | }, | ||
192 | }; | ||
193 | |||
194 | static struct hda_pcm_stream ad198x_pcm_digital_playback = { | ||
195 | .substreams = 1, | ||
196 | .channels_min = 2, | ||
197 | .channels_max = 2, | ||
198 | .nid = 0, /* fill later */ | ||
199 | .ops = { | ||
200 | .open = ad198x_dig_playback_pcm_open, | ||
201 | .close = ad198x_dig_playback_pcm_close | ||
202 | }, | ||
203 | }; | ||
204 | |||
205 | static int ad198x_build_pcms(struct hda_codec *codec) | ||
206 | { | ||
207 | struct ad198x_spec *spec = codec->spec; | ||
208 | struct hda_pcm *info = spec->pcm_rec; | ||
209 | |||
210 | codec->num_pcms = 1; | ||
211 | codec->pcm_info = info; | ||
212 | |||
213 | info->name = "AD198x Analog"; | ||
214 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback; | ||
215 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels; | ||
216 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; | ||
217 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture; | ||
218 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nid; | ||
219 | |||
220 | if (spec->multiout.dig_out_nid) { | ||
221 | info++; | ||
222 | codec->num_pcms++; | ||
223 | info->name = "AD198x Digital"; | ||
224 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; | ||
225 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | ||
226 | } | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static void ad198x_free(struct hda_codec *codec) | ||
232 | { | ||
233 | kfree(codec->spec); | ||
234 | } | ||
235 | |||
236 | #ifdef CONFIG_PM | ||
237 | static int ad198x_resume(struct hda_codec *codec) | ||
238 | { | ||
239 | struct ad198x_spec *spec = codec->spec; | ||
240 | |||
241 | ad198x_init(codec); | ||
242 | snd_hda_resume_ctls(codec, spec->mixers); | ||
243 | snd_hda_resume_spdif_out(codec); | ||
244 | return 0; | ||
245 | } | ||
246 | #endif | ||
247 | |||
248 | static struct hda_codec_ops ad198x_patch_ops = { | ||
249 | .build_controls = ad198x_build_controls, | ||
250 | .build_pcms = ad198x_build_pcms, | ||
251 | .init = ad198x_init, | ||
252 | .free = ad198x_free, | ||
253 | #ifdef CONFIG_PM | ||
254 | .resume = ad198x_resume, | ||
255 | #endif | ||
256 | }; | ||
257 | |||
258 | |||
259 | /* | ||
260 | * AD1986A specific | ||
261 | */ | ||
262 | |||
37 | #define AD1986A_SPDIF_OUT 0x02 | 263 | #define AD1986A_SPDIF_OUT 0x02 |
38 | #define AD1986A_FRONT_DAC 0x03 | 264 | #define AD1986A_FRONT_DAC 0x03 |
39 | #define AD1986A_SURR_DAC 0x04 | 265 | #define AD1986A_SURR_DAC 0x04 |
@@ -68,7 +294,7 @@ static struct hda_input_mux ad1986a_capture_source = { | |||
68 | static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 294 | static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
69 | { | 295 | { |
70 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 296 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
71 | struct ad1986a_spec *ad = codec->spec; | 297 | struct ad198x_spec *ad = codec->spec; |
72 | 298 | ||
73 | down(&ad->amp_mutex); | 299 | down(&ad->amp_mutex); |
74 | snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); | 300 | snd_hda_mixer_amp_volume_get(kcontrol, ucontrol); |
@@ -79,7 +305,7 @@ static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ | |||
79 | static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 305 | static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
80 | { | 306 | { |
81 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 307 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
82 | struct ad1986a_spec *ad = codec->spec; | 308 | struct ad198x_spec *ad = codec->spec; |
83 | int i, change = 0; | 309 | int i, change = 0; |
84 | 310 | ||
85 | down(&ad->amp_mutex); | 311 | down(&ad->amp_mutex); |
@@ -92,12 +318,12 @@ static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ | |||
92 | return change; | 318 | return change; |
93 | } | 319 | } |
94 | 320 | ||
95 | #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_volume_info | 321 | #define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info |
96 | 322 | ||
97 | static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 323 | static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
98 | { | 324 | { |
99 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 325 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
100 | struct ad1986a_spec *ad = codec->spec; | 326 | struct ad198x_spec *ad = codec->spec; |
101 | 327 | ||
102 | down(&ad->amp_mutex); | 328 | down(&ad->amp_mutex); |
103 | snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | 329 | snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); |
@@ -108,7 +334,7 @@ static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
108 | static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 334 | static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
109 | { | 335 | { |
110 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 336 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
111 | struct ad1986a_spec *ad = codec->spec; | 337 | struct ad198x_spec *ad = codec->spec; |
112 | int i, change = 0; | 338 | int i, change = 0; |
113 | 339 | ||
114 | down(&ad->amp_mutex); | 340 | down(&ad->amp_mutex); |
@@ -122,32 +348,6 @@ static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
122 | } | 348 | } |
123 | 349 | ||
124 | /* | 350 | /* |
125 | * input MUX handling | ||
126 | */ | ||
127 | static int ad1986a_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
128 | { | ||
129 | return snd_hda_input_mux_info(&ad1986a_capture_source, uinfo); | ||
130 | } | ||
131 | |||
132 | static int ad1986a_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
133 | { | ||
134 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
135 | struct ad1986a_spec *spec = codec->spec; | ||
136 | |||
137 | ucontrol->value.enumerated.item[0] = spec->cur_mux; | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int ad1986a_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
142 | { | ||
143 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
144 | struct ad1986a_spec *spec = codec->spec; | ||
145 | |||
146 | return snd_hda_input_mux_put(codec, &ad1986a_capture_source, ucontrol, | ||
147 | AD1986A_ADC, &spec->cur_mux); | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * mixers | 351 | * mixers |
152 | */ | 352 | */ |
153 | static snd_kcontrol_new_t ad1986a_mixers[] = { | 353 | static snd_kcontrol_new_t ad1986a_mixers[] = { |
@@ -194,9 +394,9 @@ static snd_kcontrol_new_t ad1986a_mixers[] = { | |||
194 | { | 394 | { |
195 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 395 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
196 | .name = "Capture Source", | 396 | .name = "Capture Source", |
197 | .info = ad1986a_mux_enum_info, | 397 | .info = ad198x_mux_enum_info, |
198 | .get = ad1986a_mux_enum_get, | 398 | .get = ad198x_mux_enum_get, |
199 | .put = ad1986a_mux_enum_put, | 399 | .put = ad198x_mux_enum_put, |
200 | }, | 400 | }, |
201 | HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT), | 401 | HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT), |
202 | { } /* end */ | 402 | { } /* end */ |
@@ -241,183 +441,328 @@ static struct hda_verb ad1986a_init_verbs[] = { | |||
241 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 441 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
242 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 442 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
243 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 443 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
444 | /* HP Pin */ | ||
445 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | ||
446 | /* Front, Surround, CLFE Pins */ | ||
447 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
448 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
449 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
450 | /* Mono Pin */ | ||
451 | {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
452 | /* Mic Pin */ | ||
453 | {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
454 | /* Line, Aux, CD, Beep-In Pin */ | ||
455 | {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
456 | {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
457 | {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
458 | {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
459 | {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
244 | { } /* end */ | 460 | { } /* end */ |
245 | }; | 461 | }; |
246 | 462 | ||
247 | 463 | ||
248 | static int ad1986a_init(struct hda_codec *codec) | 464 | static int patch_ad1986a(struct hda_codec *codec) |
249 | { | 465 | { |
250 | snd_hda_sequence_write(codec, ad1986a_init_verbs); | 466 | struct ad198x_spec *spec; |
251 | return 0; | ||
252 | } | ||
253 | 467 | ||
254 | static int ad1986a_build_controls(struct hda_codec *codec) | 468 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
255 | { | 469 | if (spec == NULL) |
256 | int err; | 470 | return -ENOMEM; |
471 | |||
472 | init_MUTEX(&spec->amp_mutex); | ||
473 | codec->spec = spec; | ||
474 | |||
475 | spec->multiout.max_channels = 6; | ||
476 | spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); | ||
477 | spec->multiout.dac_nids = ad1986a_dac_nids; | ||
478 | spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; | ||
479 | spec->adc_nid = AD1986A_ADC; | ||
480 | spec->input_mux = &ad1986a_capture_source; | ||
481 | spec->mixers = ad1986a_mixers; | ||
482 | spec->init_verbs = ad1986a_init_verbs; | ||
483 | |||
484 | codec->patch_ops = ad198x_patch_ops; | ||
257 | 485 | ||
258 | err = snd_hda_add_new_ctls(codec, ad1986a_mixers); | ||
259 | if (err < 0) | ||
260 | return err; | ||
261 | err = snd_hda_create_spdif_out_ctls(codec, AD1986A_SPDIF_OUT); | ||
262 | if (err < 0) | ||
263 | return err; | ||
264 | return 0; | 486 | return 0; |
265 | } | 487 | } |
266 | 488 | ||
267 | /* | 489 | /* |
268 | * Analog playback callbacks | 490 | * AD1983 specific |
269 | */ | 491 | */ |
270 | static int ad1986a_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
271 | struct hda_codec *codec, | ||
272 | snd_pcm_substream_t *substream) | ||
273 | { | ||
274 | struct ad1986a_spec *spec = codec->spec; | ||
275 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); | ||
276 | } | ||
277 | 492 | ||
278 | static int ad1986a_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 493 | #define AD1983_SPDIF_OUT 0x02 |
279 | struct hda_codec *codec, | 494 | #define AD1983_DAC 0x03 |
280 | unsigned int stream_tag, | 495 | #define AD1983_ADC 0x04 |
281 | unsigned int format, | ||
282 | snd_pcm_substream_t *substream) | ||
283 | { | ||
284 | struct ad1986a_spec *spec = codec->spec; | ||
285 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | ||
286 | format, substream); | ||
287 | } | ||
288 | 496 | ||
289 | static int ad1986a_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | 497 | static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC }; |
290 | struct hda_codec *codec, | 498 | |
291 | snd_pcm_substream_t *substream) | 499 | static struct hda_input_mux ad1983_capture_source = { |
292 | { | 500 | .num_items = 4, |
293 | struct ad1986a_spec *spec = codec->spec; | 501 | .items = { |
294 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | 502 | { "Mic", 0x0 }, |
295 | } | 503 | { "Line", 0x1 }, |
504 | { "Mix", 0x2 }, | ||
505 | { "Mix Mono", 0x3 }, | ||
506 | }, | ||
507 | }; | ||
296 | 508 | ||
297 | /* | 509 | /* |
298 | * Digital out | 510 | * SPDIF playback route |
299 | */ | 511 | */ |
300 | static int ad1986a_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | 512 | static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) |
301 | struct hda_codec *codec, | ||
302 | snd_pcm_substream_t *substream) | ||
303 | { | 513 | { |
304 | struct ad1986a_spec *spec = codec->spec; | 514 | static char *texts[] = { "PCM", "ADC" }; |
305 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | 515 | |
516 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
517 | uinfo->count = 1; | ||
518 | uinfo->value.enumerated.items = 2; | ||
519 | if (uinfo->value.enumerated.item > 1) | ||
520 | uinfo->value.enumerated.item = 1; | ||
521 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
522 | return 0; | ||
306 | } | 523 | } |
307 | 524 | ||
308 | static int ad1986a_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | 525 | static int ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
309 | struct hda_codec *codec, | ||
310 | snd_pcm_substream_t *substream) | ||
311 | { | 526 | { |
312 | struct ad1986a_spec *spec = codec->spec; | 527 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
313 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 528 | struct ad198x_spec *spec = codec->spec; |
314 | } | ||
315 | 529 | ||
316 | /* | 530 | ucontrol->value.enumerated.item[0] = spec->spdif_route; |
317 | * Analog capture | ||
318 | */ | ||
319 | static int ad1986a_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
320 | struct hda_codec *codec, | ||
321 | unsigned int stream_tag, | ||
322 | unsigned int format, | ||
323 | snd_pcm_substream_t *substream) | ||
324 | { | ||
325 | snd_hda_codec_setup_stream(codec, AD1986A_ADC, stream_tag, 0, format); | ||
326 | return 0; | 531 | return 0; |
327 | } | 532 | } |
328 | 533 | ||
329 | static int ad1986a_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | 534 | static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
330 | struct hda_codec *codec, | ||
331 | snd_pcm_substream_t *substream) | ||
332 | { | 535 | { |
333 | snd_hda_codec_setup_stream(codec, AD1986A_ADC, 0, 0, 0); | 536 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
537 | struct ad198x_spec *spec = codec->spec; | ||
538 | |||
539 | if (spec->spdif_route != ucontrol->value.enumerated.item[0]) { | ||
540 | spec->spdif_route = ucontrol->value.enumerated.item[0]; | ||
541 | snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0, | ||
542 | AC_VERB_SET_CONNECT_SEL, spec->spdif_route); | ||
543 | return 1; | ||
544 | } | ||
334 | return 0; | 545 | return 0; |
335 | } | 546 | } |
336 | 547 | ||
337 | 548 | static snd_kcontrol_new_t ad1983_mixers[] = { | |
338 | /* | 549 | HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), |
339 | */ | 550 | HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), |
340 | static struct hda_pcm_stream ad1986a_pcm_analog_playback = { | 551 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), |
341 | .substreams = 1, | 552 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), |
342 | .channels_min = 2, | 553 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), |
343 | .channels_max = 6, | 554 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), |
344 | .nid = AD1986A_FRONT_DAC, /* NID to query formats and rates */ | 555 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), |
345 | .ops = { | 556 | HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), |
346 | .open = ad1986a_playback_pcm_open, | 557 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), |
347 | .prepare = ad1986a_playback_pcm_prepare, | 558 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), |
348 | .cleanup = ad1986a_playback_pcm_cleanup | 559 | HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
560 | HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
561 | HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT), | ||
562 | HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT), | ||
563 | HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT), | ||
564 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | ||
565 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | ||
566 | { | ||
567 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
568 | .name = "Capture Source", | ||
569 | .info = ad198x_mux_enum_info, | ||
570 | .get = ad198x_mux_enum_get, | ||
571 | .put = ad198x_mux_enum_put, | ||
349 | }, | 572 | }, |
350 | }; | 573 | { |
351 | 574 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | |
352 | static struct hda_pcm_stream ad1986a_pcm_analog_capture = { | 575 | .name = "IEC958 Playback Route", |
353 | .substreams = 2, | 576 | .info = ad1983_spdif_route_info, |
354 | .channels_min = 2, | 577 | .get = ad1983_spdif_route_get, |
355 | .channels_max = 2, | 578 | .put = ad1983_spdif_route_put, |
356 | .nid = AD1986A_ADC, /* NID to query formats and rates */ | ||
357 | .ops = { | ||
358 | .prepare = ad1986a_capture_pcm_prepare, | ||
359 | .cleanup = ad1986a_capture_pcm_cleanup | ||
360 | }, | 579 | }, |
580 | { } /* end */ | ||
361 | }; | 581 | }; |
362 | 582 | ||
363 | static struct hda_pcm_stream ad1986a_pcm_digital_playback = { | 583 | static struct hda_verb ad1983_init_verbs[] = { |
364 | .substreams = 1, | 584 | /* Front, HP, Mono; mute as default */ |
365 | .channels_min = 2, | 585 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
366 | .channels_max = 2, | 586 | {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
367 | .nid = AD1986A_SPDIF_OUT, | 587 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
368 | .ops = { | 588 | /* Beep, PCM, Mic, Line-In: mute */ |
369 | .open = ad1986a_dig_playback_pcm_open, | 589 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
370 | .close = ad1986a_dig_playback_pcm_close | 590 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
371 | }, | 591 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, |
592 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
593 | /* Front, HP selectors; from Mix */ | ||
594 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
595 | {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
596 | /* Mono selector; from Mix */ | ||
597 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
598 | /* Mic selector; Mic */ | ||
599 | {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
600 | /* Line-in selector: Line-in */ | ||
601 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
602 | /* Mic boost: 0dB */ | ||
603 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
604 | /* Record selector: mic */ | ||
605 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
606 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
607 | /* SPDIF route: PCM */ | ||
608 | {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
609 | /* Front Pin */ | ||
610 | {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
611 | /* HP Pin */ | ||
612 | {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | ||
613 | /* Mono Pin */ | ||
614 | {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
615 | /* Mic Pin */ | ||
616 | {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
617 | /* Line Pin */ | ||
618 | {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
619 | { } /* end */ | ||
372 | }; | 620 | }; |
373 | 621 | ||
374 | static int ad1986a_build_pcms(struct hda_codec *codec) | 622 | static int patch_ad1983(struct hda_codec *codec) |
375 | { | 623 | { |
376 | struct ad1986a_spec *spec = codec->spec; | 624 | struct ad198x_spec *spec; |
377 | struct hda_pcm *info = spec->pcm_rec; | ||
378 | 625 | ||
379 | codec->num_pcms = 2; | 626 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
380 | codec->pcm_info = info; | 627 | if (spec == NULL) |
628 | return -ENOMEM; | ||
381 | 629 | ||
382 | info->name = "AD1986A Analog"; | 630 | init_MUTEX(&spec->amp_mutex); |
383 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_analog_playback; | 631 | codec->spec = spec; |
384 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1986a_pcm_analog_capture; | 632 | |
385 | info++; | 633 | spec->multiout.max_channels = 2; |
634 | spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids); | ||
635 | spec->multiout.dac_nids = ad1983_dac_nids; | ||
636 | spec->multiout.dig_out_nid = AD1983_SPDIF_OUT; | ||
637 | spec->adc_nid = AD1983_ADC; | ||
638 | spec->input_mux = &ad1983_capture_source; | ||
639 | spec->mixers = ad1983_mixers; | ||
640 | spec->init_verbs = ad1983_init_verbs; | ||
641 | spec->spdif_route = 0; | ||
386 | 642 | ||
387 | info->name = "AD1986A Digital"; | 643 | codec->patch_ops = ad198x_patch_ops; |
388 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_digital_playback; | ||
389 | 644 | ||
390 | return 0; | 645 | return 0; |
391 | } | 646 | } |
392 | 647 | ||
393 | static void ad1986a_free(struct hda_codec *codec) | ||
394 | { | ||
395 | kfree(codec->spec); | ||
396 | } | ||
397 | 648 | ||
398 | #ifdef CONFIG_PM | 649 | /* |
399 | static int ad1986a_resume(struct hda_codec *codec) | 650 | * AD1981 HD specific |
400 | { | 651 | */ |
401 | ad1986a_init(codec); | ||
402 | snd_hda_resume_ctls(codec, ad1986a_mixers); | ||
403 | snd_hda_resume_spdif_out(codec); | ||
404 | return 0; | ||
405 | } | ||
406 | #endif | ||
407 | 652 | ||
408 | static struct hda_codec_ops ad1986a_patch_ops = { | 653 | #define AD1981_SPDIF_OUT 0x02 |
409 | .build_controls = ad1986a_build_controls, | 654 | #define AD1981_DAC 0x03 |
410 | .build_pcms = ad1986a_build_pcms, | 655 | #define AD1981_ADC 0x04 |
411 | .init = ad1986a_init, | 656 | |
412 | .free = ad1986a_free, | 657 | static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC }; |
413 | #ifdef CONFIG_PM | 658 | |
414 | .resume = ad1986a_resume, | 659 | /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */ |
415 | #endif | 660 | static struct hda_input_mux ad1981_capture_source = { |
661 | .num_items = 7, | ||
662 | .items = { | ||
663 | { "Front Mic", 0x0 }, | ||
664 | { "Line", 0x1 }, | ||
665 | { "Mix", 0x2 }, | ||
666 | { "Mix Mono", 0x3 }, | ||
667 | { "CD", 0x4 }, | ||
668 | { "Mic", 0x6 }, | ||
669 | { "Aux", 0x7 }, | ||
670 | }, | ||
416 | }; | 671 | }; |
417 | 672 | ||
418 | static int patch_ad1986a(struct hda_codec *codec) | 673 | static snd_kcontrol_new_t ad1981_mixers[] = { |
674 | HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT), | ||
675 | HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT), | ||
676 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT), | ||
677 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT), | ||
678 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT), | ||
679 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT), | ||
680 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), | ||
681 | HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
682 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), | ||
683 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
684 | HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT), | ||
685 | HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT), | ||
686 | HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT), | ||
687 | HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
688 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), | ||
689 | HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), | ||
690 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | ||
691 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
692 | HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
693 | HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
694 | HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT), | ||
695 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT), | ||
696 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | ||
697 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | ||
698 | { | ||
699 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
700 | .name = "Capture Source", | ||
701 | .info = ad198x_mux_enum_info, | ||
702 | .get = ad198x_mux_enum_get, | ||
703 | .put = ad198x_mux_enum_put, | ||
704 | }, | ||
705 | /* identical with AD1983 */ | ||
706 | { | ||
707 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
708 | .name = "IEC958 Playback Route", | ||
709 | .info = ad1983_spdif_route_info, | ||
710 | .get = ad1983_spdif_route_get, | ||
711 | .put = ad1983_spdif_route_put, | ||
712 | }, | ||
713 | { } /* end */ | ||
714 | }; | ||
715 | |||
716 | static struct hda_verb ad1981_init_verbs[] = { | ||
717 | /* Front, HP, Mono; mute as default */ | ||
718 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
719 | {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
720 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
721 | /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */ | ||
722 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
723 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
724 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
725 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
726 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
727 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
728 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
729 | /* Front, HP selectors; from Mix */ | ||
730 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
731 | {0x06, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
732 | /* Mono selector; from Mix */ | ||
733 | {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
734 | /* Mic Mixer; select Front Mic */ | ||
735 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
736 | {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
737 | /* Mic boost: 0dB */ | ||
738 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
739 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
740 | /* Record selector: Front mic */ | ||
741 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
742 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
743 | /* SPDIF route: PCM */ | ||
744 | {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
745 | /* Front Pin */ | ||
746 | {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
747 | /* HP Pin */ | ||
748 | {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | ||
749 | /* Mono Pin */ | ||
750 | {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
751 | /* Front & Rear Mic Pins */ | ||
752 | {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
753 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
754 | /* Line Pin */ | ||
755 | {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
756 | /* Digital Beep */ | ||
757 | {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
758 | /* Line-Out as Input: disabled */ | ||
759 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
760 | { } /* end */ | ||
761 | }; | ||
762 | |||
763 | static int patch_ad1981(struct hda_codec *codec) | ||
419 | { | 764 | { |
420 | struct ad1986a_spec *spec; | 765 | struct ad198x_spec *spec; |
421 | 766 | ||
422 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 767 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
423 | if (spec == NULL) | 768 | if (spec == NULL) |
@@ -426,20 +771,28 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
426 | init_MUTEX(&spec->amp_mutex); | 771 | init_MUTEX(&spec->amp_mutex); |
427 | codec->spec = spec; | 772 | codec->spec = spec; |
428 | 773 | ||
429 | spec->multiout.max_channels = 6; | 774 | spec->multiout.max_channels = 2; |
430 | spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids); | 775 | spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids); |
431 | spec->multiout.dac_nids = ad1986a_dac_nids; | 776 | spec->multiout.dac_nids = ad1981_dac_nids; |
432 | spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT; | 777 | spec->multiout.dig_out_nid = AD1981_SPDIF_OUT; |
778 | spec->adc_nid = AD1981_ADC; | ||
779 | spec->input_mux = &ad1981_capture_source; | ||
780 | spec->mixers = ad1981_mixers; | ||
781 | spec->init_verbs = ad1981_init_verbs; | ||
782 | spec->spdif_route = 0; | ||
433 | 783 | ||
434 | codec->patch_ops = ad1986a_patch_ops; | 784 | codec->patch_ops = ad198x_patch_ops; |
435 | 785 | ||
436 | return 0; | 786 | return 0; |
437 | } | 787 | } |
438 | 788 | ||
789 | |||
439 | /* | 790 | /* |
440 | * patch entries | 791 | * patch entries |
441 | */ | 792 | */ |
442 | struct hda_codec_preset snd_hda_preset_analog[] = { | 793 | struct hda_codec_preset snd_hda_preset_analog[] = { |
794 | { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, | ||
795 | { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, | ||
443 | { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, | 796 | { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, |
444 | {} /* terminator */ | 797 | {} /* terminator */ |
445 | }; | 798 | }; |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index b7cc8e4bffb7..86f195f19eef 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <sound/core.h> | 29 | #include <sound/core.h> |
30 | #include "hda_codec.h" | 30 | #include "hda_codec.h" |
31 | #include "hda_local.h" | 31 | #include "hda_local.h" |
32 | #define NUM_PINS 11 | ||
32 | 33 | ||
33 | 34 | ||
34 | /* board config type */ | 35 | /* board config type */ |
@@ -38,6 +39,7 @@ enum { | |||
38 | CMI_FULL, /* back 6-jack + front-panel 2-jack */ | 39 | CMI_FULL, /* back 6-jack + front-panel 2-jack */ |
39 | CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */ | 40 | CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */ |
40 | CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */ | 41 | CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */ |
42 | CMI_AUTO, /* let driver guess it */ | ||
41 | }; | 43 | }; |
42 | 44 | ||
43 | struct cmi_spec { | 45 | struct cmi_spec { |
@@ -48,6 +50,8 @@ struct cmi_spec { | |||
48 | 50 | ||
49 | /* playback */ | 51 | /* playback */ |
50 | struct hda_multi_out multiout; | 52 | struct hda_multi_out multiout; |
53 | hda_nid_t dac_nids[4]; /* NID for each DAC */ | ||
54 | int num_dacs; | ||
51 | 55 | ||
52 | /* capture */ | 56 | /* capture */ |
53 | hda_nid_t *adc_nids; | 57 | hda_nid_t *adc_nids; |
@@ -63,8 +67,30 @@ struct cmi_spec { | |||
63 | const struct cmi_channel_mode *channel_modes; | 67 | const struct cmi_channel_mode *channel_modes; |
64 | 68 | ||
65 | struct hda_pcm pcm_rec[2]; /* PCM information */ | 69 | struct hda_pcm pcm_rec[2]; /* PCM information */ |
70 | |||
71 | /* pin deafault configuration */ | ||
72 | hda_nid_t pin_nid[NUM_PINS]; | ||
73 | unsigned int def_conf[NUM_PINS]; | ||
74 | unsigned int pin_def_confs; | ||
75 | |||
76 | /* multichannel pins */ | ||
77 | hda_nid_t multich_pin[4]; /* max 8-channel */ | ||
78 | struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */ | ||
66 | }; | 79 | }; |
67 | 80 | ||
81 | /* amp values */ | ||
82 | #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) | ||
83 | #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) | ||
84 | #define AMP_OUT_MUTE 0xb080 | ||
85 | #define AMP_OUT_UNMUTE 0xb000 | ||
86 | #define AMP_OUT_ZERO 0xb000 | ||
87 | /* pinctl values */ | ||
88 | #define PIN_IN 0x20 | ||
89 | #define PIN_VREF80 0x24 | ||
90 | #define PIN_VREF50 0x21 | ||
91 | #define PIN_OUT 0x40 | ||
92 | #define PIN_HP 0xc0 | ||
93 | |||
68 | /* | 94 | /* |
69 | * input MUX | 95 | * input MUX |
70 | */ | 96 | */ |
@@ -102,9 +128,9 @@ static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon | |||
102 | /* 3-stack / 2 channel */ | 128 | /* 3-stack / 2 channel */ |
103 | static struct hda_verb cmi9880_ch2_init[] = { | 129 | static struct hda_verb cmi9880_ch2_init[] = { |
104 | /* set line-in PIN for input */ | 130 | /* set line-in PIN for input */ |
105 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | 131 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
106 | /* set mic PIN for input, also enable vref */ | 132 | /* set mic PIN for input, also enable vref */ |
107 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 133 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
108 | /* route front PCM (DAC1) to HP */ | 134 | /* route front PCM (DAC1) to HP */ |
109 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 135 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, |
110 | {} | 136 | {} |
@@ -113,9 +139,9 @@ static struct hda_verb cmi9880_ch2_init[] = { | |||
113 | /* 3-stack / 6 channel */ | 139 | /* 3-stack / 6 channel */ |
114 | static struct hda_verb cmi9880_ch6_init[] = { | 140 | static struct hda_verb cmi9880_ch6_init[] = { |
115 | /* set line-in PIN for output */ | 141 | /* set line-in PIN for output */ |
116 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 142 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
117 | /* set mic PIN for output */ | 143 | /* set mic PIN for output */ |
118 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 144 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
119 | /* route front PCM (DAC1) to HP */ | 145 | /* route front PCM (DAC1) to HP */ |
120 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 146 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, |
121 | {} | 147 | {} |
@@ -124,9 +150,9 @@ static struct hda_verb cmi9880_ch6_init[] = { | |||
124 | /* 3-stack+front / 8 channel */ | 150 | /* 3-stack+front / 8 channel */ |
125 | static struct hda_verb cmi9880_ch8_init[] = { | 151 | static struct hda_verb cmi9880_ch8_init[] = { |
126 | /* set line-in PIN for output */ | 152 | /* set line-in PIN for output */ |
127 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 153 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
128 | /* set mic PIN for output */ | 154 | /* set mic PIN for output */ |
129 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 155 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
130 | /* route rear-surround PCM (DAC4) to HP */ | 156 | /* route rear-surround PCM (DAC4) to HP */ |
131 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 }, | 157 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 }, |
132 | {} | 158 | {} |
@@ -269,25 +295,27 @@ static hda_nid_t cmi9880_adc_nids[2] = { | |||
269 | */ | 295 | */ |
270 | static struct hda_verb cmi9880_basic_init[] = { | 296 | static struct hda_verb cmi9880_basic_init[] = { |
271 | /* port-D for line out (rear panel) */ | 297 | /* port-D for line out (rear panel) */ |
272 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 298 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
273 | /* port-E for HP out (front panel) */ | 299 | /* port-E for HP out (front panel) */ |
274 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 300 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
275 | /* route front PCM to HP */ | 301 | /* route front PCM to HP */ |
276 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 302 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, |
277 | /* port-A for surround (rear panel) */ | 303 | /* port-A for surround (rear panel) */ |
278 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 304 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
279 | /* port-G for CLFE (rear panel) */ | 305 | /* port-G for CLFE (rear panel) */ |
280 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 306 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
307 | { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
281 | /* port-H for side (rear panel) */ | 308 | /* port-H for side (rear panel) */ |
282 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 309 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
310 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
283 | /* port-C for line-in (rear panel) */ | 311 | /* port-C for line-in (rear panel) */ |
284 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | 312 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
285 | /* port-B for mic-in (rear panel) with vref */ | 313 | /* port-B for mic-in (rear panel) with vref */ |
286 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 314 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
287 | /* port-F for mic-in (front panel) with vref */ | 315 | /* port-F for mic-in (front panel) with vref */ |
288 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 316 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
289 | /* CD-in */ | 317 | /* CD-in */ |
290 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | 318 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
291 | /* route front mic to ADC1/2 */ | 319 | /* route front mic to ADC1/2 */ |
292 | { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, | 320 | { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, |
293 | { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, | 321 | { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, |
@@ -296,23 +324,27 @@ static struct hda_verb cmi9880_basic_init[] = { | |||
296 | 324 | ||
297 | static struct hda_verb cmi9880_allout_init[] = { | 325 | static struct hda_verb cmi9880_allout_init[] = { |
298 | /* port-D for line out (rear panel) */ | 326 | /* port-D for line out (rear panel) */ |
299 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 327 | { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
300 | /* port-E for HP out (front panel) */ | 328 | /* port-E for HP out (front panel) */ |
301 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 329 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
302 | /* route front PCM to HP */ | 330 | /* route front PCM to HP */ |
303 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | 331 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, |
304 | /* port-A for side (rear panel) */ | 332 | /* port-A for side (rear panel) */ |
305 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 333 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
306 | /* port-G for CLFE (rear panel) */ | 334 | /* port-G for CLFE (rear panel) */ |
307 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 335 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
336 | { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
337 | /* port-H for side (rear panel) */ | ||
338 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, | ||
339 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
308 | /* port-C for surround (rear panel) */ | 340 | /* port-C for surround (rear panel) */ |
309 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 341 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, |
310 | /* port-B for mic-in (rear panel) with vref */ | 342 | /* port-B for mic-in (rear panel) with vref */ |
311 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 343 | { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
312 | /* port-F for mic-in (front panel) with vref */ | 344 | /* port-F for mic-in (front panel) with vref */ |
313 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 345 | { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
314 | /* CD-in */ | 346 | /* CD-in */ |
315 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | 347 | { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
316 | /* route front mic to ADC1/2 */ | 348 | /* route front mic to ADC1/2 */ |
317 | { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, | 349 | { 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 }, |
318 | { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, | 350 | { 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 }, |
@@ -347,6 +379,80 @@ static int cmi9880_build_controls(struct hda_codec *codec) | |||
347 | return 0; | 379 | return 0; |
348 | } | 380 | } |
349 | 381 | ||
382 | /* fill in the multi_dac_nids table, which will decide | ||
383 | which audio widget to use for each channel */ | ||
384 | static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) | ||
385 | { | ||
386 | struct cmi_spec *spec = codec->spec; | ||
387 | hda_nid_t nid; | ||
388 | int assigned[4]; | ||
389 | int i, j; | ||
390 | |||
391 | /* clear the table, only one c-media dac assumed here */ | ||
392 | memset(spec->dac_nids, 0, sizeof(spec->dac_nids)); | ||
393 | memset(assigned, 0, sizeof(assigned)); | ||
394 | /* check the pins we found */ | ||
395 | for (i = 0; i < cfg->line_outs; i++) { | ||
396 | nid = cfg->line_out_pins[i]; | ||
397 | /* nid 0x0b~0x0e is hardwired to audio widget 0x3~0x6 */ | ||
398 | if (nid >= 0x0b && nid <= 0x0e) { | ||
399 | spec->dac_nids[i] = (nid - 0x0b) + 0x03; | ||
400 | assigned[nid - 0x0b] = 1; | ||
401 | } | ||
402 | } | ||
403 | /* left pin can be connect to any audio widget */ | ||
404 | for (i = 0; i < cfg->line_outs; i++) { | ||
405 | nid = cfg->line_out_pins[i]; | ||
406 | if (nid <= 0x0e) | ||
407 | continue; | ||
408 | /* search for an empty channel */ | ||
409 | for (j = 0; j < cfg->line_outs; j++) { | ||
410 | if (! assigned[j]) { | ||
411 | spec->dac_nids[i] = j + 0x03; | ||
412 | assigned[j] = 1; | ||
413 | break; | ||
414 | } | ||
415 | } | ||
416 | } | ||
417 | spec->num_dacs = cfg->line_outs; | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | /* create multi_init table, which is used for multichannel initialization */ | ||
422 | static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pin_cfg *cfg) | ||
423 | { | ||
424 | struct cmi_spec *spec = codec->spec; | ||
425 | hda_nid_t nid; | ||
426 | int i, j, k, len; | ||
427 | |||
428 | /* clear the table, only one c-media dac assumed here */ | ||
429 | memset(spec->multi_init, 0, sizeof(spec->multi_init)); | ||
430 | for (j = 0, i = 0; i < cfg->line_outs; i++) { | ||
431 | hda_nid_t conn[4]; | ||
432 | nid = cfg->line_out_pins[i]; | ||
433 | /* set as output */ | ||
434 | spec->multi_init[j].nid = nid; | ||
435 | spec->multi_init[j].verb = AC_VERB_SET_PIN_WIDGET_CONTROL; | ||
436 | spec->multi_init[j].param = PIN_OUT; | ||
437 | j++; | ||
438 | if (nid > 0x0e) { | ||
439 | /* set connection */ | ||
440 | spec->multi_init[j].nid = nid; | ||
441 | spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL; | ||
442 | spec->multi_init[j].param = 0; | ||
443 | /* find the index in connect list */ | ||
444 | len = snd_hda_get_connections(codec, nid, conn, 4); | ||
445 | for (k = 0; k < len; k++) | ||
446 | if (conn[k] == spec->dac_nids[i]) { | ||
447 | spec->multi_init[j].param = k; | ||
448 | break; | ||
449 | } | ||
450 | j++; | ||
451 | } | ||
452 | } | ||
453 | return 0; | ||
454 | } | ||
455 | |||
350 | static int cmi9880_init(struct hda_codec *codec) | 456 | static int cmi9880_init(struct hda_codec *codec) |
351 | { | 457 | { |
352 | struct cmi_spec *spec = codec->spec; | 458 | struct cmi_spec *spec = codec->spec; |
@@ -354,6 +460,8 @@ static int cmi9880_init(struct hda_codec *codec) | |||
354 | snd_hda_sequence_write(codec, cmi9880_allout_init); | 460 | snd_hda_sequence_write(codec, cmi9880_allout_init); |
355 | else | 461 | else |
356 | snd_hda_sequence_write(codec, cmi9880_basic_init); | 462 | snd_hda_sequence_write(codec, cmi9880_basic_init); |
463 | if (spec->board_config == CMI_AUTO) | ||
464 | snd_hda_sequence_write(codec, spec->multi_init); | ||
357 | return 0; | 465 | return 0; |
358 | } | 466 | } |
359 | 467 | ||
@@ -540,6 +648,7 @@ static struct hda_board_config cmi9880_cfg_tbl[] = { | |||
540 | { .modelname = "full", .config = CMI_FULL }, | 648 | { .modelname = "full", .config = CMI_FULL }, |
541 | { .modelname = "full_dig", .config = CMI_FULL_DIG }, | 649 | { .modelname = "full_dig", .config = CMI_FULL_DIG }, |
542 | { .modelname = "allout", .config = CMI_ALLOUT }, | 650 | { .modelname = "allout", .config = CMI_ALLOUT }, |
651 | { .modelname = "auto", .config = CMI_AUTO }, | ||
543 | {} /* terminator */ | 652 | {} /* terminator */ |
544 | }; | 653 | }; |
545 | 654 | ||
@@ -564,10 +673,14 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
564 | codec->spec = spec; | 673 | codec->spec = spec; |
565 | spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl); | 674 | spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl); |
566 | if (spec->board_config < 0) { | 675 | if (spec->board_config < 0) { |
567 | snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n"); | 676 | snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n"); |
568 | spec->board_config = CMI_FULL_DIG; /* try everything */ | 677 | spec->board_config = CMI_AUTO; /* try everything */ |
569 | } | 678 | } |
570 | 679 | ||
680 | /* copy default DAC NIDs */ | ||
681 | memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids)); | ||
682 | spec->num_dacs = 4; | ||
683 | |||
571 | switch (spec->board_config) { | 684 | switch (spec->board_config) { |
572 | case CMI_MINIMAL: | 685 | case CMI_MINIMAL: |
573 | case CMI_MIN_FP: | 686 | case CMI_MIN_FP: |
@@ -599,10 +712,58 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
599 | spec->input_mux = &cmi9880_no_line_mux; | 712 | spec->input_mux = &cmi9880_no_line_mux; |
600 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | 713 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; |
601 | break; | 714 | break; |
715 | case CMI_AUTO: | ||
716 | { | ||
717 | unsigned int port_e, port_f, port_g, port_h; | ||
718 | unsigned int port_spdifi, port_spdifo; | ||
719 | struct auto_pin_cfg cfg; | ||
720 | |||
721 | /* collect pin default configuration */ | ||
722 | port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
723 | port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
724 | spec->front_panel = 1; | ||
725 | if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || | ||
726 | get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { | ||
727 | port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
728 | port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
729 | spec->surr_switch = 1; | ||
730 | /* no front panel */ | ||
731 | if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || | ||
732 | get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) { | ||
733 | /* no optional rear panel */ | ||
734 | spec->board_config = CMI_MINIMAL; | ||
735 | spec->front_panel = 0; | ||
736 | spec->num_ch_modes = 2; | ||
737 | } else { | ||
738 | spec->board_config = CMI_MIN_FP; | ||
739 | spec->num_ch_modes = 3; | ||
740 | } | ||
741 | spec->channel_modes = cmi9880_channel_modes; | ||
742 | spec->input_mux = &cmi9880_basic_mux; | ||
743 | spec->multiout.max_channels = cmi9880_channel_modes[0].channels; | ||
744 | } else { | ||
745 | spec->input_mux = &cmi9880_basic_mux; | ||
746 | port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
747 | port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
748 | if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) | ||
749 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | ||
750 | if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) | ||
751 | spec->dig_in_nid = CMI_DIG_IN_NID; | ||
752 | spec->multiout.max_channels = 8; | ||
753 | } | ||
754 | snd_hda_parse_pin_def_config(codec, &cfg); | ||
755 | if (cfg.line_outs) { | ||
756 | spec->multiout.max_channels = cfg.line_outs * 2; | ||
757 | cmi9880_fill_multi_dac_nids(codec, &cfg); | ||
758 | cmi9880_fill_multi_init(codec, &cfg); | ||
759 | } else | ||
760 | snd_printd("patch_cmedia: cannot detect association in defcfg\n"); | ||
761 | break; | ||
762 | } | ||
602 | } | 763 | } |
603 | 764 | ||
604 | spec->multiout.num_dacs = 4; | 765 | spec->multiout.num_dacs = spec->num_dacs; |
605 | spec->multiout.dac_nids = cmi9880_dac_nids; | 766 | spec->multiout.dac_nids = spec->dac_nids; |
606 | 767 | ||
607 | spec->adc_nids = cmi9880_adc_nids; | 768 | spec->adc_nids = cmi9880_adc_nids; |
608 | 769 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 17c5062423ae..9b8569900787 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -33,38 +33,74 @@ | |||
33 | 33 | ||
34 | /* ALC880 board config type */ | 34 | /* ALC880 board config type */ |
35 | enum { | 35 | enum { |
36 | ALC880_MINIMAL, | ||
37 | ALC880_3ST, | 36 | ALC880_3ST, |
38 | ALC880_3ST_DIG, | 37 | ALC880_3ST_DIG, |
39 | ALC880_5ST, | 38 | ALC880_5ST, |
40 | ALC880_5ST_DIG, | 39 | ALC880_5ST_DIG, |
41 | ALC880_W810, | 40 | ALC880_W810, |
41 | ALC880_Z71V, | ||
42 | ALC880_AUTO, | ||
43 | ALC880_6ST, | ||
44 | ALC880_6ST_DIG, | ||
45 | ALC880_F1734, | ||
46 | ALC880_ASUS, | ||
47 | ALC880_ASUS_DIG, | ||
48 | ALC880_ASUS_W1V, | ||
49 | ALC880_UNIWILL_DIG, | ||
50 | #ifdef CONFIG_SND_DEBUG | ||
51 | ALC880_TEST, | ||
52 | #endif | ||
53 | ALC880_MODEL_LAST /* last tag */ | ||
54 | }; | ||
55 | |||
56 | /* ALC260 models */ | ||
57 | enum { | ||
58 | ALC260_BASIC, | ||
59 | ALC260_HP, | ||
60 | ALC260_MODEL_LAST /* last tag */ | ||
42 | }; | 61 | }; |
43 | 62 | ||
63 | /* amp values */ | ||
64 | #define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8)) | ||
65 | #define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8)) | ||
66 | #define AMP_OUT_MUTE 0xb080 | ||
67 | #define AMP_OUT_UNMUTE 0xb000 | ||
68 | #define AMP_OUT_ZERO 0xb000 | ||
69 | /* pinctl values */ | ||
70 | #define PIN_IN 0x20 | ||
71 | #define PIN_VREF80 0x24 | ||
72 | #define PIN_VREF50 0x21 | ||
73 | #define PIN_OUT 0x40 | ||
74 | #define PIN_HP 0xc0 | ||
75 | |||
44 | struct alc_spec { | 76 | struct alc_spec { |
45 | /* codec parameterization */ | 77 | /* codec parameterization */ |
46 | unsigned int front_panel: 1; | 78 | snd_kcontrol_new_t *mixers[3]; /* mixer arrays */ |
47 | |||
48 | snd_kcontrol_new_t* mixers[2]; | ||
49 | unsigned int num_mixers; | 79 | unsigned int num_mixers; |
50 | 80 | ||
51 | struct hda_verb *init_verbs; | 81 | const struct hda_verb *init_verbs[3]; /* initialization verbs |
82 | * don't forget NULL termination! | ||
83 | */ | ||
84 | unsigned int num_init_verbs; | ||
52 | 85 | ||
53 | char* stream_name_analog; | 86 | char *stream_name_analog; /* analog PCM stream */ |
54 | struct hda_pcm_stream *stream_analog_playback; | 87 | struct hda_pcm_stream *stream_analog_playback; |
55 | struct hda_pcm_stream *stream_analog_capture; | 88 | struct hda_pcm_stream *stream_analog_capture; |
56 | 89 | ||
57 | char* stream_name_digital; | 90 | char *stream_name_digital; /* digital PCM stream */ |
58 | struct hda_pcm_stream *stream_digital_playback; | 91 | struct hda_pcm_stream *stream_digital_playback; |
59 | struct hda_pcm_stream *stream_digital_capture; | 92 | struct hda_pcm_stream *stream_digital_capture; |
60 | 93 | ||
61 | /* playback */ | 94 | /* playback */ |
62 | struct hda_multi_out multiout; | 95 | struct hda_multi_out multiout; /* playback set-up |
96 | * max_channels, dacs must be set | ||
97 | * dig_out_nid and hp_nid are optional | ||
98 | */ | ||
63 | 99 | ||
64 | /* capture */ | 100 | /* capture */ |
65 | unsigned int num_adc_nids; | 101 | unsigned int num_adc_nids; |
66 | hda_nid_t *adc_nids; | 102 | hda_nid_t *adc_nids; |
67 | hda_nid_t dig_in_nid; | 103 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
68 | 104 | ||
69 | /* capture source */ | 105 | /* capture source */ |
70 | const struct hda_input_mux *input_mux; | 106 | const struct hda_input_mux *input_mux; |
@@ -75,61 +111,18 @@ struct alc_spec { | |||
75 | int num_channel_mode; | 111 | int num_channel_mode; |
76 | 112 | ||
77 | /* PCM information */ | 113 | /* PCM information */ |
78 | struct hda_pcm pcm_rec[2]; | 114 | struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ |
79 | }; | ||
80 | |||
81 | /* DAC/ADC assignment */ | ||
82 | |||
83 | static hda_nid_t alc880_dac_nids[4] = { | ||
84 | /* front, rear, clfe, rear_surr */ | ||
85 | 0x02, 0x05, 0x04, 0x03 | ||
86 | }; | ||
87 | |||
88 | static hda_nid_t alc880_w810_dac_nids[3] = { | ||
89 | /* front, rear/surround, clfe */ | ||
90 | 0x02, 0x03, 0x04 | ||
91 | }; | ||
92 | |||
93 | static hda_nid_t alc880_adc_nids[3] = { | ||
94 | /* ADC0-2 */ | ||
95 | 0x07, 0x08, 0x09, | ||
96 | }; | ||
97 | |||
98 | #define ALC880_DIGOUT_NID 0x06 | ||
99 | #define ALC880_DIGIN_NID 0x0a | ||
100 | 115 | ||
101 | static hda_nid_t alc260_dac_nids[1] = { | 116 | struct semaphore bind_mutex; /* for bound controls */ |
102 | /* front */ | ||
103 | 0x02, | ||
104 | }; | ||
105 | 117 | ||
106 | static hda_nid_t alc260_adc_nids[2] = { | 118 | /* dynamic controls, init_verbs and input_mux */ |
107 | /* ADC0-1 */ | 119 | struct auto_pin_cfg autocfg; |
108 | 0x04, 0x05, | 120 | unsigned int num_kctl_alloc, num_kctl_used; |
121 | snd_kcontrol_new_t *kctl_alloc; | ||
122 | struct hda_input_mux private_imux; | ||
123 | hda_nid_t private_dac_nids[4]; | ||
109 | }; | 124 | }; |
110 | 125 | ||
111 | #define ALC260_DIGOUT_NID 0x03 | ||
112 | #define ALC260_DIGIN_NID 0x06 | ||
113 | |||
114 | static struct hda_input_mux alc880_capture_source = { | ||
115 | .num_items = 4, | ||
116 | .items = { | ||
117 | { "Mic", 0x0 }, | ||
118 | { "Front Mic", 0x3 }, | ||
119 | { "Line", 0x2 }, | ||
120 | { "CD", 0x4 }, | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | static struct hda_input_mux alc260_capture_source = { | ||
125 | .num_items = 4, | ||
126 | .items = { | ||
127 | { "Mic", 0x0 }, | ||
128 | { "Front Mic", 0x1 }, | ||
129 | { "Line", 0x2 }, | ||
130 | { "CD", 0x4 }, | ||
131 | }, | ||
132 | }; | ||
133 | 126 | ||
134 | /* | 127 | /* |
135 | * input MUX handling | 128 | * input MUX handling |
@@ -160,6 +153,7 @@ static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon | |||
160 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); | 153 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); |
161 | } | 154 | } |
162 | 155 | ||
156 | |||
163 | /* | 157 | /* |
164 | * channel mode setting | 158 | * channel mode setting |
165 | */ | 159 | */ |
@@ -168,135 +162,18 @@ struct alc_channel_mode { | |||
168 | const struct hda_verb *sequence; | 162 | const struct hda_verb *sequence; |
169 | }; | 163 | }; |
170 | 164 | ||
171 | |||
172 | /* | ||
173 | * channel source setting (2/6 channel selection for 3-stack) | ||
174 | */ | ||
175 | |||
176 | /* | ||
177 | * set the path ways for 2 channel output | ||
178 | * need to set the codec line out and mic 1 pin widgets to inputs | ||
179 | */ | ||
180 | static struct hda_verb alc880_threestack_ch2_init[] = { | ||
181 | /* set pin widget 1Ah (line in) for input */ | ||
182 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
183 | /* set pin widget 18h (mic1) for input, for mic also enable the vref */ | ||
184 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | ||
185 | /* mute the output for Line In PW */ | ||
186 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, | ||
187 | /* mute for Mic1 PW */ | ||
188 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, | ||
189 | { } /* end */ | ||
190 | }; | ||
191 | |||
192 | /* | ||
193 | * 6ch mode | ||
194 | * need to set the codec line out and mic 1 pin widgets to outputs | ||
195 | */ | ||
196 | static struct hda_verb alc880_threestack_ch6_init[] = { | ||
197 | /* set pin widget 1Ah (line in) for output */ | ||
198 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
199 | /* set pin widget 18h (mic1) for output */ | ||
200 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
201 | /* unmute the output for Line In PW */ | ||
202 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 }, | ||
203 | /* unmute for Mic1 PW */ | ||
204 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 }, | ||
205 | /* for rear channel output using Line In 1 | ||
206 | * set select widget connection (nid = 0x12) - to summer node | ||
207 | * for rear NID = 0x0f...offset 3 in connection list | ||
208 | */ | ||
209 | { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 }, | ||
210 | /* for Mic1 - retask for center/lfe */ | ||
211 | /* set select widget connection (nid = 0x10) - to summer node for | ||
212 | * front CLFE NID = 0x0e...offset 2 in connection list | ||
213 | */ | ||
214 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 }, | ||
215 | { } /* end */ | ||
216 | }; | ||
217 | |||
218 | static struct alc_channel_mode alc880_threestack_modes[2] = { | ||
219 | { 2, alc880_threestack_ch2_init }, | ||
220 | { 6, alc880_threestack_ch6_init }, | ||
221 | }; | ||
222 | |||
223 | |||
224 | /* | ||
225 | * channel source setting (6/8 channel selection for 5-stack) | ||
226 | */ | ||
227 | |||
228 | /* set the path ways for 6 channel output | ||
229 | * need to set the codec line out and mic 1 pin widgets to inputs | ||
230 | */ | ||
231 | static struct hda_verb alc880_fivestack_ch6_init[] = { | ||
232 | /* set pin widget 1Ah (line in) for input */ | ||
233 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | ||
234 | /* mute the output for Line In PW */ | ||
235 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, | ||
236 | { } /* end */ | ||
237 | }; | ||
238 | |||
239 | /* need to set the codec line out and mic 1 pin widgets to outputs */ | ||
240 | static struct hda_verb alc880_fivestack_ch8_init[] = { | ||
241 | /* set pin widget 1Ah (line in) for output */ | ||
242 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | ||
243 | /* unmute the output for Line In PW */ | ||
244 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 }, | ||
245 | /* output for surround channel output using Line In 1 */ | ||
246 | /* set select widget connection (nid = 0x12) - to summer node | ||
247 | * for surr_rear NID = 0x0d...offset 1 in connection list | ||
248 | */ | ||
249 | { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 }, | ||
250 | { } /* end */ | ||
251 | }; | ||
252 | |||
253 | static struct alc_channel_mode alc880_fivestack_modes[2] = { | ||
254 | { 6, alc880_fivestack_ch6_init }, | ||
255 | { 8, alc880_fivestack_ch8_init }, | ||
256 | }; | ||
257 | |||
258 | /* | ||
259 | * channel source setting for W810 system | ||
260 | * | ||
261 | * W810 has rear IO for: | ||
262 | * Front (DAC 02) | ||
263 | * Surround (DAC 03) | ||
264 | * Center/LFE (DAC 04) | ||
265 | * Digital out (06) | ||
266 | * | ||
267 | * The system also has a pair of internal speakers, and a headphone jack. | ||
268 | * These are both connected to Line2 on the codec, hence to DAC 02. | ||
269 | * | ||
270 | * There is a variable resistor to control the speaker or headphone | ||
271 | * volume. This is a hardware-only device without a software API. | ||
272 | * | ||
273 | * Plugging headphones in will disable the internal speakers. This is | ||
274 | * implemented in hardware, not via the driver using jack sense. In | ||
275 | * a similar fashion, plugging into the rear socket marked "front" will | ||
276 | * disable both the speakers and headphones. | ||
277 | * | ||
278 | * For input, there's a microphone jack, and an "audio in" jack. | ||
279 | * These may not do anything useful with this driver yet, because I | ||
280 | * haven't setup any initialization verbs for these yet... | ||
281 | */ | ||
282 | |||
283 | static struct alc_channel_mode alc880_w810_modes[1] = { | ||
284 | { 6, NULL } | ||
285 | }; | ||
286 | |||
287 | /* | ||
288 | */ | ||
289 | static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | 165 | static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) |
290 | { | 166 | { |
291 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 167 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
292 | struct alc_spec *spec = codec->spec; | 168 | struct alc_spec *spec = codec->spec; |
169 | int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; | ||
293 | 170 | ||
294 | snd_assert(spec->channel_mode, return -ENXIO); | 171 | snd_assert(spec->channel_mode, return -ENXIO); |
295 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 172 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
296 | uinfo->count = 1; | 173 | uinfo->count = 1; |
297 | uinfo->value.enumerated.items = 2; | 174 | uinfo->value.enumerated.items = items; |
298 | if (uinfo->value.enumerated.item >= 2) | 175 | if (uinfo->value.enumerated.item >= items) |
299 | uinfo->value.enumerated.item = 1; | 176 | uinfo->value.enumerated.item = items - 1; |
300 | sprintf(uinfo->value.enumerated.name, "%dch", | 177 | sprintf(uinfo->value.enumerated.name, "%dch", |
301 | spec->channel_mode[uinfo->value.enumerated.item].channels); | 178 | spec->channel_mode[uinfo->value.enumerated.item].channels); |
302 | return 0; | 179 | return 0; |
@@ -306,10 +183,16 @@ static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc | |||
306 | { | 183 | { |
307 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 184 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
308 | struct alc_spec *spec = codec->spec; | 185 | struct alc_spec *spec = codec->spec; |
186 | int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; | ||
187 | int i; | ||
309 | 188 | ||
310 | snd_assert(spec->channel_mode, return -ENXIO); | 189 | snd_assert(spec->channel_mode, return -ENXIO); |
311 | ucontrol->value.enumerated.item[0] = | 190 | for (i = 0; i < items; i++) { |
312 | (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1; | 191 | if (spec->multiout.max_channels == spec->channel_mode[i].channels) { |
192 | ucontrol->value.enumerated.item[0] = i; | ||
193 | break; | ||
194 | } | ||
195 | } | ||
313 | return 0; | 196 | return 0; |
314 | } | 197 | } |
315 | 198 | ||
@@ -335,21 +218,149 @@ static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc | |||
335 | 218 | ||
336 | 219 | ||
337 | /* | 220 | /* |
221 | * bound volume controls | ||
222 | * | ||
223 | * bind multiple volumes (# indices, from 0) | ||
224 | */ | ||
225 | |||
226 | #define AMP_VAL_IDX_SHIFT 19 | ||
227 | #define AMP_VAL_IDX_MASK (0x0f<<19) | ||
228 | |||
229 | static int alc_bind_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
230 | { | ||
231 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
232 | struct alc_spec *spec = codec->spec; | ||
233 | unsigned long pval; | ||
234 | |||
235 | down(&spec->bind_mutex); | ||
236 | pval = kcontrol->private_value; | ||
237 | kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ | ||
238 | snd_hda_mixer_amp_switch_info(kcontrol, uinfo); | ||
239 | kcontrol->private_value = pval; | ||
240 | up(&spec->bind_mutex); | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int alc_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
245 | { | ||
246 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
247 | struct alc_spec *spec = codec->spec; | ||
248 | unsigned long pval; | ||
249 | |||
250 | down(&spec->bind_mutex); | ||
251 | pval = kcontrol->private_value; | ||
252 | kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ | ||
253 | snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); | ||
254 | kcontrol->private_value = pval; | ||
255 | up(&spec->bind_mutex); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int alc_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
260 | { | ||
261 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
262 | struct alc_spec *spec = codec->spec; | ||
263 | unsigned long pval; | ||
264 | int i, indices, change = 0; | ||
265 | |||
266 | down(&spec->bind_mutex); | ||
267 | pval = kcontrol->private_value; | ||
268 | indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; | ||
269 | for (i = 0; i < indices; i++) { | ||
270 | kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT); | ||
271 | change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
272 | } | ||
273 | kcontrol->private_value = pval; | ||
274 | up(&spec->bind_mutex); | ||
275 | return change; | ||
276 | } | ||
277 | |||
278 | #define ALC_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ | ||
279 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
280 | .info = alc_bind_switch_info, \ | ||
281 | .get = alc_bind_switch_get, \ | ||
282 | .put = alc_bind_switch_put, \ | ||
283 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } | ||
284 | |||
285 | #define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir) | ||
286 | |||
287 | |||
288 | /* | ||
289 | * ALC880 3-stack model | ||
290 | * | ||
291 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) | ||
292 | * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b | ||
293 | * HP = 0x19 | ||
338 | */ | 294 | */ |
339 | 295 | ||
340 | /* 3-stack mode | 296 | static hda_nid_t alc880_dac_nids[4] = { |
341 | * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b | 297 | /* front, rear, clfe, rear_surr */ |
342 | * HP=0x19 | 298 | 0x02, 0x05, 0x04, 0x03 |
299 | }; | ||
300 | |||
301 | static hda_nid_t alc880_adc_nids[3] = { | ||
302 | /* ADC0-2 */ | ||
303 | 0x07, 0x08, 0x09, | ||
304 | }; | ||
305 | |||
306 | /* The datasheet says the node 0x07 is connected from inputs, | ||
307 | * but it shows zero connection in the real implementation on some devices. | ||
343 | */ | 308 | */ |
344 | static snd_kcontrol_new_t alc880_base_mixer[] = { | 309 | static hda_nid_t alc880_adc_nids_alt[2] = { |
310 | /* ADC1-2 */ | ||
311 | 0x08, 0x09, | ||
312 | }; | ||
313 | |||
314 | #define ALC880_DIGOUT_NID 0x06 | ||
315 | #define ALC880_DIGIN_NID 0x0a | ||
316 | |||
317 | static struct hda_input_mux alc880_capture_source = { | ||
318 | .num_items = 4, | ||
319 | .items = { | ||
320 | { "Mic", 0x0 }, | ||
321 | { "Front Mic", 0x3 }, | ||
322 | { "Line", 0x2 }, | ||
323 | { "CD", 0x4 }, | ||
324 | }, | ||
325 | }; | ||
326 | |||
327 | /* channel source setting (2/6 channel selection for 3-stack) */ | ||
328 | /* 2ch mode */ | ||
329 | static struct hda_verb alc880_threestack_ch2_init[] = { | ||
330 | /* set line-in to input, mute it */ | ||
331 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
332 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
333 | /* set mic-in to input vref 80%, mute it */ | ||
334 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
335 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
336 | { } /* end */ | ||
337 | }; | ||
338 | |||
339 | /* 6ch mode */ | ||
340 | static struct hda_verb alc880_threestack_ch6_init[] = { | ||
341 | /* set line-in to output, unmute it */ | ||
342 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
343 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
344 | /* set mic-in to output, unmute it */ | ||
345 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
346 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
347 | { } /* end */ | ||
348 | }; | ||
349 | |||
350 | static struct alc_channel_mode alc880_threestack_modes[2] = { | ||
351 | { 2, alc880_threestack_ch2_init }, | ||
352 | { 6, alc880_threestack_ch6_init }, | ||
353 | }; | ||
354 | |||
355 | static snd_kcontrol_new_t alc880_three_stack_mixer[] = { | ||
345 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 356 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
346 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 357 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
347 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | 358 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), |
348 | HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT), | 359 | ALC_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), |
349 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | 360 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), |
350 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 361 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
351 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT), | 362 | ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), |
352 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT), | 363 | ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), |
353 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 364 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
354 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 365 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
355 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 366 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
@@ -360,12 +371,25 @@ static snd_kcontrol_new_t alc880_base_mixer[] = { | |||
360 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), | 371 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), |
361 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 372 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
362 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 373 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
363 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
364 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), | 374 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), |
375 | { | ||
376 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
377 | .name = "Channel Mode", | ||
378 | .info = alc880_ch_mode_info, | ||
379 | .get = alc880_ch_mode_get, | ||
380 | .put = alc880_ch_mode_put, | ||
381 | }, | ||
382 | { } /* end */ | ||
383 | }; | ||
384 | |||
385 | /* capture mixer elements */ | ||
386 | static snd_kcontrol_new_t alc880_capture_mixer[] = { | ||
365 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | 387 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), |
366 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | 388 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), |
367 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | 389 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), |
368 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | 390 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), |
391 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | ||
392 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | ||
369 | { | 393 | { |
370 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 394 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
371 | /* The multiple "Capture Source" controls confuse alsamixer | 395 | /* The multiple "Capture Source" controls confuse alsamixer |
@@ -374,65 +398,125 @@ static snd_kcontrol_new_t alc880_base_mixer[] = { | |||
374 | */ | 398 | */ |
375 | /* .name = "Capture Source", */ | 399 | /* .name = "Capture Source", */ |
376 | .name = "Input Source", | 400 | .name = "Input Source", |
377 | .count = 2, | 401 | .count = 3, |
378 | .info = alc_mux_enum_info, | 402 | .info = alc_mux_enum_info, |
379 | .get = alc_mux_enum_get, | 403 | .get = alc_mux_enum_get, |
380 | .put = alc_mux_enum_put, | 404 | .put = alc_mux_enum_put, |
381 | }, | 405 | }, |
406 | { } /* end */ | ||
407 | }; | ||
408 | |||
409 | /* capture mixer elements (in case NID 0x07 not available) */ | ||
410 | static snd_kcontrol_new_t alc880_capture_alt_mixer[] = { | ||
411 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
412 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
413 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
414 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
382 | { | 415 | { |
383 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 416 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
384 | .name = "Channel Mode", | 417 | /* The multiple "Capture Source" controls confuse alsamixer |
385 | .info = alc880_ch_mode_info, | 418 | * So call somewhat different.. |
386 | .get = alc880_ch_mode_get, | 419 | * FIXME: the controls appear in the "playback" view! |
387 | .put = alc880_ch_mode_put, | 420 | */ |
421 | /* .name = "Capture Source", */ | ||
422 | .name = "Input Source", | ||
423 | .count = 2, | ||
424 | .info = alc_mux_enum_info, | ||
425 | .get = alc_mux_enum_get, | ||
426 | .put = alc_mux_enum_put, | ||
388 | }, | 427 | }, |
389 | { } /* end */ | 428 | { } /* end */ |
390 | }; | 429 | }; |
391 | 430 | ||
392 | /* 5-stack mode | 431 | |
393 | * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16 | 432 | |
394 | * Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19 | 433 | /* |
434 | * ALC880 5-stack model | ||
435 | * | ||
436 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd) | ||
437 | * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 | ||
438 | * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 | ||
395 | */ | 439 | */ |
440 | |||
441 | /* additional mixers to alc880_three_stack_mixer */ | ||
396 | static snd_kcontrol_new_t alc880_five_stack_mixer[] = { | 442 | static snd_kcontrol_new_t alc880_five_stack_mixer[] = { |
443 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
444 | ALC_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT), | ||
445 | { } /* end */ | ||
446 | }; | ||
447 | |||
448 | /* channel source setting (6/8 channel selection for 5-stack) */ | ||
449 | /* 6ch mode */ | ||
450 | static struct hda_verb alc880_fivestack_ch6_init[] = { | ||
451 | /* set line-in to input, mute it */ | ||
452 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
453 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
454 | { } /* end */ | ||
455 | }; | ||
456 | |||
457 | /* 8ch mode */ | ||
458 | static struct hda_verb alc880_fivestack_ch8_init[] = { | ||
459 | /* set line-in to output, unmute it */ | ||
460 | { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
461 | { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
462 | { } /* end */ | ||
463 | }; | ||
464 | |||
465 | static struct alc_channel_mode alc880_fivestack_modes[2] = { | ||
466 | { 6, alc880_fivestack_ch6_init }, | ||
467 | { 8, alc880_fivestack_ch8_init }, | ||
468 | }; | ||
469 | |||
470 | |||
471 | /* | ||
472 | * ALC880 6-stack model | ||
473 | * | ||
474 | * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f) | ||
475 | * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, | ||
476 | * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b | ||
477 | */ | ||
478 | |||
479 | static hda_nid_t alc880_6st_dac_nids[4] = { | ||
480 | /* front, rear, clfe, rear_surr */ | ||
481 | 0x02, 0x03, 0x04, 0x05 | ||
482 | }; | ||
483 | |||
484 | static struct hda_input_mux alc880_6stack_capture_source = { | ||
485 | .num_items = 4, | ||
486 | .items = { | ||
487 | { "Mic", 0x0 }, | ||
488 | { "Front Mic", 0x1 }, | ||
489 | { "Line", 0x2 }, | ||
490 | { "CD", 0x4 }, | ||
491 | }, | ||
492 | }; | ||
493 | |||
494 | /* fixed 8-channels */ | ||
495 | static struct alc_channel_mode alc880_sixstack_modes[1] = { | ||
496 | { 8, NULL }, | ||
497 | }; | ||
498 | |||
499 | static snd_kcontrol_new_t alc880_six_stack_mixer[] = { | ||
397 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 500 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
398 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 501 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
399 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | 502 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
400 | HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT), | 503 | ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), |
401 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | 504 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), |
402 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 505 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
403 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), | 506 | ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), |
404 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), | 507 | ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), |
405 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 508 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), |
406 | HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT), | 509 | ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), |
407 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 510 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
408 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 511 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
409 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 512 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
410 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | 513 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), |
411 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 514 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
412 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 515 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
413 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT), | 516 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
414 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT), | 517 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
415 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 518 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
416 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 519 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
417 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
418 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), | ||
419 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | ||
420 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | ||
421 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | ||
422 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | ||
423 | { | ||
424 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
425 | /* The multiple "Capture Source" controls confuse alsamixer | ||
426 | * So call somewhat different.. | ||
427 | * FIXME: the controls appear in the "playback" view! | ||
428 | */ | ||
429 | /* .name = "Capture Source", */ | ||
430 | .name = "Input Source", | ||
431 | .count = 2, | ||
432 | .info = alc_mux_enum_info, | ||
433 | .get = alc_mux_enum_get, | ||
434 | .put = alc_mux_enum_put, | ||
435 | }, | ||
436 | { | 520 | { |
437 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 521 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
438 | .name = "Channel Mode", | 522 | .name = "Channel Mode", |
@@ -443,39 +527,169 @@ static snd_kcontrol_new_t alc880_five_stack_mixer[] = { | |||
443 | { } /* end */ | 527 | { } /* end */ |
444 | }; | 528 | }; |
445 | 529 | ||
530 | |||
531 | /* | ||
532 | * ALC880 W810 model | ||
533 | * | ||
534 | * W810 has rear IO for: | ||
535 | * Front (DAC 02) | ||
536 | * Surround (DAC 03) | ||
537 | * Center/LFE (DAC 04) | ||
538 | * Digital out (06) | ||
539 | * | ||
540 | * The system also has a pair of internal speakers, and a headphone jack. | ||
541 | * These are both connected to Line2 on the codec, hence to DAC 02. | ||
542 | * | ||
543 | * There is a variable resistor to control the speaker or headphone | ||
544 | * volume. This is a hardware-only device without a software API. | ||
545 | * | ||
546 | * Plugging headphones in will disable the internal speakers. This is | ||
547 | * implemented in hardware, not via the driver using jack sense. In | ||
548 | * a similar fashion, plugging into the rear socket marked "front" will | ||
549 | * disable both the speakers and headphones. | ||
550 | * | ||
551 | * For input, there's a microphone jack, and an "audio in" jack. | ||
552 | * These may not do anything useful with this driver yet, because I | ||
553 | * haven't setup any initialization verbs for these yet... | ||
554 | */ | ||
555 | |||
556 | static hda_nid_t alc880_w810_dac_nids[3] = { | ||
557 | /* front, rear/surround, clfe */ | ||
558 | 0x02, 0x03, 0x04 | ||
559 | }; | ||
560 | |||
561 | /* fixed 6 channels */ | ||
562 | static struct alc_channel_mode alc880_w810_modes[1] = { | ||
563 | { 6, NULL } | ||
564 | }; | ||
565 | |||
566 | /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */ | ||
446 | static snd_kcontrol_new_t alc880_w810_base_mixer[] = { | 567 | static snd_kcontrol_new_t alc880_w810_base_mixer[] = { |
447 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 568 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
448 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 569 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
449 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 570 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
450 | HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 571 | ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), |
451 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | 572 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), |
452 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 573 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
453 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), | 574 | ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), |
454 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), | 575 | ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), |
455 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 576 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
456 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | 577 | { } /* end */ |
457 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | 578 | }; |
458 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | 579 | |
459 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | 580 | |
460 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | 581 | /* |
461 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | 582 | * Z710V model |
583 | * | ||
584 | * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) | ||
585 | * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a | ||
586 | */ | ||
587 | |||
588 | static hda_nid_t alc880_z71v_dac_nids[1] = { | ||
589 | 0x02 | ||
590 | }; | ||
591 | #define ALC880_Z71V_HP_DAC 0x03 | ||
592 | |||
593 | /* fixed 2 channels */ | ||
594 | static struct alc_channel_mode alc880_2_jack_modes[1] = { | ||
595 | { 2, NULL } | ||
596 | }; | ||
597 | |||
598 | static snd_kcontrol_new_t alc880_z71v_mixer[] = { | ||
599 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
600 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
601 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
602 | ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT), | ||
603 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
604 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
605 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
606 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
607 | { } /* end */ | ||
608 | }; | ||
609 | |||
610 | |||
611 | /* FIXME! */ | ||
612 | /* | ||
613 | * ALC880 F1734 model | ||
614 | * | ||
615 | * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d) | ||
616 | * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18 | ||
617 | */ | ||
618 | |||
619 | static hda_nid_t alc880_f1734_dac_nids[1] = { | ||
620 | 0x03 | ||
621 | }; | ||
622 | #define ALC880_F1734_HP_DAC 0x02 | ||
623 | |||
624 | static snd_kcontrol_new_t alc880_f1734_mixer[] = { | ||
625 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
626 | ALC_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), | ||
627 | HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
628 | ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT), | ||
629 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
630 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
631 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
632 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
633 | { } /* end */ | ||
634 | }; | ||
635 | |||
636 | |||
637 | /* FIXME! */ | ||
638 | /* | ||
639 | * ALC880 ASUS model | ||
640 | * | ||
641 | * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) | ||
642 | * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, | ||
643 | * Mic = 0x18, Line = 0x1a | ||
644 | */ | ||
645 | |||
646 | #define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */ | ||
647 | #define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */ | ||
648 | |||
649 | static snd_kcontrol_new_t alc880_asus_mixer[] = { | ||
650 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
651 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
652 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
653 | ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
654 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
655 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
656 | ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
657 | ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
658 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
659 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
660 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
661 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
662 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
663 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
462 | { | 664 | { |
463 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 665 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
464 | /* The multiple "Capture Source" controls confuse alsamixer | 666 | .name = "Channel Mode", |
465 | * So call somewhat different.. | 667 | .info = alc880_ch_mode_info, |
466 | * FIXME: the controls appear in the "playback" view! | 668 | .get = alc880_ch_mode_get, |
467 | */ | 669 | .put = alc880_ch_mode_put, |
468 | /* .name = "Capture Source", */ | ||
469 | .name = "Input Source", | ||
470 | .count = 3, | ||
471 | .info = alc_mux_enum_info, | ||
472 | .get = alc_mux_enum_get, | ||
473 | .put = alc_mux_enum_put, | ||
474 | }, | 670 | }, |
475 | { } /* end */ | 671 | { } /* end */ |
476 | }; | 672 | }; |
477 | 673 | ||
674 | /* FIXME! */ | ||
675 | /* | ||
676 | * ALC880 ASUS W1V model | ||
677 | * | ||
678 | * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e) | ||
679 | * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16, | ||
680 | * Mic = 0x18, Line = 0x1a, Line2 = 0x1b | ||
681 | */ | ||
682 | |||
683 | /* additional mixers to alc880_asus_mixer */ | ||
684 | static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = { | ||
685 | HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT), | ||
686 | HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT), | ||
687 | { } /* end */ | ||
688 | }; | ||
689 | |||
690 | |||
478 | /* | 691 | /* |
692 | * build control elements | ||
479 | */ | 693 | */ |
480 | static int alc_build_controls(struct hda_codec *codec) | 694 | static int alc_build_controls(struct hda_codec *codec) |
481 | { | 695 | { |
@@ -502,227 +716,297 @@ static int alc_build_controls(struct hda_codec *codec) | |||
502 | return 0; | 716 | return 0; |
503 | } | 717 | } |
504 | 718 | ||
719 | |||
505 | /* | 720 | /* |
506 | * initialize the codec volumes, etc | 721 | * initialize the codec volumes, etc |
507 | */ | 722 | */ |
508 | 723 | ||
509 | static struct hda_verb alc880_init_verbs_three_stack[] = { | 724 | /* |
510 | /* Line In pin widget for input */ | 725 | * generic initialization of ADC, input mixers and output mixers |
511 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 726 | */ |
512 | /* CD pin widget for input */ | 727 | static struct hda_verb alc880_volume_init_verbs[] = { |
513 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 728 | /* |
514 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | 729 | * Unmute ADC0-2 and set the default input to mic-in |
515 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 730 | */ |
516 | /* Mic2 (front panel) pin widget for input and vref at 80% */ | 731 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
517 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 732 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
518 | /* unmute amp left and right */ | 733 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, |
519 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 734 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
520 | /* set connection select to line in (default select for this ADC) */ | 735 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
521 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x02}, | 736 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
522 | /* unmute front mixer amp left (volume = 0) */ | 737 | |
523 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 738 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback |
524 | /* mute pin widget amp left and right (no gain on this amp) */ | 739 | * mixer widget |
525 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
526 | /* unmute rear mixer amp left and right (volume = 0) */ | ||
527 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
528 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
529 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
530 | /* unmute rear mixer amp left and right (volume = 0) */ | ||
531 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
532 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
533 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
534 | |||
535 | /* using rear surround as the path for headphone output */ | ||
536 | /* unmute rear surround mixer amp left and right (volume = 0) */ | ||
537 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
538 | /* PASD 3 stack boards use the Mic 2 as the headphone output */ | ||
539 | /* need to program the selector associated with the Mic 2 pin widget to | ||
540 | * surround path (index 0x01) for headphone output */ | ||
541 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
542 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
543 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
544 | /* need to retask the Mic 2 pin widget to output */ | ||
545 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
546 | |||
547 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B) | ||
548 | * to support the input path of analog loopback | ||
549 | * Note: PASD motherboards uses the Line In 2 as the input for front panel | 740 | * Note: PASD motherboards uses the Line In 2 as the input for front panel |
550 | * mic (mic 2) | 741 | * mic (mic 2) |
551 | */ | 742 | */ |
552 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ | 743 | /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ |
553 | /* unmute CD */ | 744 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
554 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 745 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
555 | /* unmute Line In */ | 746 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
556 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 747 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, |
557 | /* unmute Mic 1 */ | 748 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
558 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 749 | |
559 | /* unmute Line In 2 (for PASD boards Mic 2) */ | 750 | /* |
560 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, | 751 | * Set up output mixers (0x0c - 0x0f) |
561 | |||
562 | /* Unmute input amps for the line out paths to support the output path of | ||
563 | * analog loopback | ||
564 | * the mixers on the output path has 2 inputs, one from the DAC and one | ||
565 | * from the mixer | ||
566 | */ | 752 | */ |
567 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 753 | /* set vol=0 to output mixers */ |
568 | /* Unmute Front out path */ | 754 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
569 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 755 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
570 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 756 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
571 | /* Unmute Surround (used as HP) out path */ | 757 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
572 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 758 | /* set up input amps for analog loopback */ |
573 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 759 | /* Amp Indices: DAC = 0, mixer = 1 */ |
574 | /* Unmute C/LFE out path */ | 760 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
575 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 761 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
576 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */ | 762 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
577 | /* Unmute rear Surround out path */ | 763 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
578 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 764 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
579 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 765 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
766 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
767 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
580 | 768 | ||
581 | { } | 769 | { } |
582 | }; | 770 | }; |
583 | 771 | ||
584 | static struct hda_verb alc880_init_verbs_five_stack[] = { | 772 | /* |
585 | /* Line In pin widget for input */ | 773 | * 3-stack pin configuration: |
586 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 774 | * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b |
587 | /* CD pin widget for input */ | 775 | */ |
588 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 776 | static struct hda_verb alc880_pin_3stack_init_verbs[] = { |
589 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | 777 | /* |
590 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 778 | * preset connection lists of input pins |
591 | /* Mic2 (front panel) pin widget for input and vref at 80% */ | 779 | * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround |
592 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
593 | /* unmute amp left and right */ | ||
594 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
595 | /* set connection select to line in (default select for this ADC) */ | ||
596 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
597 | /* unmute front mixer amp left and right (volume = 0) */ | ||
598 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
599 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
600 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
601 | /* five rear and clfe */ | ||
602 | /* unmute rear mixer amp left and right (volume = 0) */ | ||
603 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
604 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
605 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
606 | /* unmute clfe mixer amp left and right (volume = 0) */ | ||
607 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
608 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
609 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
610 | |||
611 | /* using rear surround as the path for headphone output */ | ||
612 | /* unmute rear surround mixer amp left and right (volume = 0) */ | ||
613 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
614 | /* PASD 3 stack boards use the Mic 2 as the headphone output */ | ||
615 | /* need to program the selector associated with the Mic 2 pin widget to | ||
616 | * surround path (index 0x01) for headphone output | ||
617 | */ | ||
618 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
619 | /* mute pin widget amp left and right (no gain on this amp) */ | ||
620 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
621 | /* need to retask the Mic 2 pin widget to output */ | ||
622 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
623 | |||
624 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer | ||
625 | * widget(nid=0x0B) to support the input path of analog loopback | ||
626 | */ | 780 | */ |
627 | /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */ | 781 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ |
628 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/ | 782 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ |
629 | /* unmute CD */ | 783 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ |
630 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 784 | |
631 | /* unmute Line In */ | 785 | /* |
632 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 786 | * Set pin mode and muting |
633 | /* unmute Mic 1 */ | ||
634 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
635 | /* unmute Line In 2 (for PASD boards Mic 2) */ | ||
636 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, | ||
637 | |||
638 | /* Unmute input amps for the line out paths to support the output path of | ||
639 | * analog loopback | ||
640 | * the mixers on the output path has 2 inputs, one from the DAC and | ||
641 | * one from the mixer | ||
642 | */ | 787 | */ |
643 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 788 | /* set front pin widgets 0x14 for output */ |
644 | /* Unmute Front out path */ | 789 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
645 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 790 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
646 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 791 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ |
647 | /* Unmute Surround (used as HP) out path */ | 792 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
648 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 793 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
649 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 794 | /* Mic2 (as headphone out) for HP output */ |
650 | /* Unmute C/LFE out path */ | 795 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
651 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 796 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
652 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */ | 797 | /* Line In pin widget for input */ |
653 | /* Unmute rear Surround out path */ | 798 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
654 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 799 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
655 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 800 | /* Line2 (as front mic) pin widget for input and vref at 80% */ |
801 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
802 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
803 | /* CD pin widget for input */ | ||
804 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
656 | 805 | ||
657 | { } | 806 | { } |
658 | }; | 807 | }; |
659 | 808 | ||
660 | static struct hda_verb alc880_w810_init_verbs[] = { | 809 | /* |
661 | /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ | 810 | * 5-stack pin configuration: |
662 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 811 | * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19, |
663 | 812 | * line-in/side = 0x1a, f-mic = 0x1b | |
664 | /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */ | 813 | */ |
665 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, | 814 | static struct hda_verb alc880_pin_5stack_init_verbs[] = { |
666 | 815 | /* | |
667 | /* front channel selector/amp: output 0: unmuted, max volume */ | 816 | * preset connection lists of input pins |
668 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 817 | * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround |
669 | 818 | */ | |
670 | /* front out pin: muted, (no volume selection) */ | 819 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ |
671 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 820 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */ |
672 | |||
673 | /* front out pin: NOT headphone enable, out enable, vref disabled */ | ||
674 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
675 | 821 | ||
822 | /* | ||
823 | * Set pin mode and muting | ||
824 | */ | ||
825 | /* set pin widgets 0x14-0x17 for output */ | ||
826 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
827 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
828 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
829 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
830 | /* unmute pins for output (no gain on this amp) */ | ||
831 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
832 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
833 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
834 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
676 | 835 | ||
677 | /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ | 836 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ |
678 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 837 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
838 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
839 | /* Mic2 (as headphone out) for HP output */ | ||
840 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
841 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
842 | /* Line In pin widget for input */ | ||
843 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
844 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
845 | /* Line2 (as front mic) pin widget for input and vref at 80% */ | ||
846 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
847 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
848 | /* CD pin widget for input */ | ||
849 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
679 | 850 | ||
680 | /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */ | 851 | { } |
681 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, | 852 | }; |
682 | 853 | ||
683 | /* surround channel selector/amp: output 0: unmuted, max volume */ | 854 | /* |
684 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 855 | * W810 pin configuration: |
856 | * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b | ||
857 | */ | ||
858 | static struct hda_verb alc880_pin_w810_init_verbs[] = { | ||
859 | /* hphone/speaker input selector: front DAC */ | ||
860 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
685 | 861 | ||
686 | /* surround out pin: muted, (no volume selection) */ | 862 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
687 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 863 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
864 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
865 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
866 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
867 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
688 | 868 | ||
689 | /* surround out pin: NOT headphone enable, out enable, vref disabled */ | 869 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
690 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 870 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
691 | 871 | ||
872 | { } | ||
873 | }; | ||
692 | 874 | ||
693 | /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ | 875 | /* |
694 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 876 | * Z71V pin configuration: |
877 | * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?) | ||
878 | */ | ||
879 | static struct hda_verb alc880_pin_z71v_init_verbs[] = { | ||
880 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
881 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
882 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
883 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
695 | 884 | ||
696 | /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */ | 885 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
697 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, | 886 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
887 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
888 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
698 | 889 | ||
699 | /* c/lfe channel selector/amp: output 0: unmuted, max volume */ | 890 | { } |
700 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 891 | }; |
701 | 892 | ||
702 | /* c/lfe out pin: muted, (no volume selection) */ | 893 | /* |
703 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 894 | * 6-stack pin configuration: |
895 | * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19, | ||
896 | * line = 0x1a, HP = 0x1b | ||
897 | */ | ||
898 | static struct hda_verb alc880_pin_6stack_init_verbs[] = { | ||
899 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
900 | |||
901 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
902 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
903 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
904 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
905 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
906 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
907 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
908 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
909 | |||
910 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
911 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
912 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
913 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
914 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
915 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
916 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
917 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
918 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
919 | |||
920 | { } | ||
921 | }; | ||
704 | 922 | ||
705 | /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */ | 923 | /* FIXME! */ |
706 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 924 | /* |
925 | * F1734 pin configuration: | ||
926 | * HP = 0x14, speaker-out = 0x15, mic = 0x18 | ||
927 | */ | ||
928 | static struct hda_verb alc880_pin_f1734_init_verbs[] = { | ||
929 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
930 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
931 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
932 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
933 | |||
934 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
935 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
936 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
937 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
938 | |||
939 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
940 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
941 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
942 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
943 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
944 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
945 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
946 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
947 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
707 | 948 | ||
949 | { } | ||
950 | }; | ||
708 | 951 | ||
709 | /* hphone/speaker input selector: front DAC */ | 952 | /* FIXME! */ |
710 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, | 953 | /* |
954 | * ASUS pin configuration: | ||
955 | * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a | ||
956 | */ | ||
957 | static struct hda_verb alc880_pin_asus_init_verbs[] = { | ||
958 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
959 | {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
960 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
961 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
962 | |||
963 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
964 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
965 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
966 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
967 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
968 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
969 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
970 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
971 | |||
972 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
973 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
974 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
975 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
976 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
977 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
978 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
979 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
980 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
981 | |||
982 | { } | ||
983 | }; | ||
711 | 984 | ||
712 | /* hphone/speaker out pin: muted, (no volume selection) */ | 985 | /* Enable GPIO mask and set output */ |
713 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 986 | static struct hda_verb alc880_gpio1_init_verbs[] = { |
987 | {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, | ||
988 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
989 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
990 | }; | ||
714 | 991 | ||
715 | /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */ | 992 | /* Enable GPIO mask and set output */ |
716 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 993 | static struct hda_verb alc880_gpio2_init_verbs[] = { |
994 | {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, | ||
995 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, | ||
996 | {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, | ||
997 | }; | ||
717 | 998 | ||
718 | 999 | ||
719 | { } | 1000 | /* |
720 | }; | 1001 | */ |
721 | 1002 | ||
722 | static int alc_init(struct hda_codec *codec) | 1003 | static int alc_init(struct hda_codec *codec) |
723 | { | 1004 | { |
724 | struct alc_spec *spec = codec->spec; | 1005 | struct alc_spec *spec = codec->spec; |
725 | snd_hda_sequence_write(codec, spec->init_verbs); | 1006 | unsigned int i; |
1007 | |||
1008 | for (i = 0; i < spec->num_init_verbs; i++) | ||
1009 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | ||
726 | return 0; | 1010 | return 0; |
727 | } | 1011 | } |
728 | 1012 | ||
@@ -736,9 +1020,8 @@ static int alc_resume(struct hda_codec *codec) | |||
736 | int i; | 1020 | int i; |
737 | 1021 | ||
738 | alc_init(codec); | 1022 | alc_init(codec); |
739 | for (i = 0; i < spec->num_mixers; i++) { | 1023 | for (i = 0; i < spec->num_mixers; i++) |
740 | snd_hda_resume_ctls(codec, spec->mixers[i]); | 1024 | snd_hda_resume_ctls(codec, spec->mixers[i]); |
741 | } | ||
742 | if (spec->multiout.dig_out_nid) | 1025 | if (spec->multiout.dig_out_nid) |
743 | snd_hda_resume_spdif_out(codec); | 1026 | snd_hda_resume_spdif_out(codec); |
744 | if (spec->dig_in_nid) | 1027 | if (spec->dig_in_nid) |
@@ -830,7 +1113,7 @@ static struct hda_pcm_stream alc880_pcm_analog_playback = { | |||
830 | .substreams = 1, | 1113 | .substreams = 1, |
831 | .channels_min = 2, | 1114 | .channels_min = 2, |
832 | .channels_max = 8, | 1115 | .channels_max = 8, |
833 | .nid = 0x02, /* NID to query formats and rates */ | 1116 | /* NID is set in alc_build_pcms */ |
834 | .ops = { | 1117 | .ops = { |
835 | .open = alc880_playback_pcm_open, | 1118 | .open = alc880_playback_pcm_open, |
836 | .prepare = alc880_playback_pcm_prepare, | 1119 | .prepare = alc880_playback_pcm_prepare, |
@@ -842,7 +1125,7 @@ static struct hda_pcm_stream alc880_pcm_analog_capture = { | |||
842 | .substreams = 2, | 1125 | .substreams = 2, |
843 | .channels_min = 2, | 1126 | .channels_min = 2, |
844 | .channels_max = 2, | 1127 | .channels_max = 2, |
845 | .nid = 0x07, /* NID to query formats and rates */ | 1128 | /* NID is set in alc_build_pcms */ |
846 | .ops = { | 1129 | .ops = { |
847 | .prepare = alc880_capture_pcm_prepare, | 1130 | .prepare = alc880_capture_pcm_prepare, |
848 | .cleanup = alc880_capture_pcm_cleanup | 1131 | .cleanup = alc880_capture_pcm_cleanup |
@@ -878,7 +1161,9 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
878 | 1161 | ||
879 | info->name = spec->stream_name_analog; | 1162 | info->name = spec->stream_name_analog; |
880 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); | 1163 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); |
1164 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; | ||
881 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); | 1165 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); |
1166 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; | ||
882 | 1167 | ||
883 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0; | 1168 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0; |
884 | for (i = 0; i < spec->num_channel_mode; i++) { | 1169 | for (i = 0; i < spec->num_channel_mode; i++) { |
@@ -906,7 +1191,18 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
906 | 1191 | ||
907 | static void alc_free(struct hda_codec *codec) | 1192 | static void alc_free(struct hda_codec *codec) |
908 | { | 1193 | { |
909 | kfree(codec->spec); | 1194 | struct alc_spec *spec = codec->spec; |
1195 | unsigned int i; | ||
1196 | |||
1197 | if (! spec) | ||
1198 | return; | ||
1199 | |||
1200 | if (spec->kctl_alloc) { | ||
1201 | for (i = 0; i < spec->num_kctl_used; i++) | ||
1202 | kfree(spec->kctl_alloc[i].name); | ||
1203 | kfree(spec->kctl_alloc); | ||
1204 | } | ||
1205 | kfree(spec); | ||
910 | } | 1206 | } |
911 | 1207 | ||
912 | /* | 1208 | /* |
@@ -921,153 +1217,929 @@ static struct hda_codec_ops alc_patch_ops = { | |||
921 | #endif | 1217 | #endif |
922 | }; | 1218 | }; |
923 | 1219 | ||
1220 | |||
1221 | /* | ||
1222 | * Test configuration for debugging | ||
1223 | * | ||
1224 | * Almost all inputs/outputs are enabled. I/O pins can be configured via | ||
1225 | * enum controls. | ||
1226 | */ | ||
1227 | #ifdef CONFIG_SND_DEBUG | ||
1228 | static hda_nid_t alc880_test_dac_nids[4] = { | ||
1229 | 0x02, 0x03, 0x04, 0x05 | ||
1230 | }; | ||
1231 | |||
1232 | static struct hda_input_mux alc880_test_capture_source = { | ||
1233 | .num_items = 5, | ||
1234 | .items = { | ||
1235 | { "In-1", 0x0 }, | ||
1236 | { "In-2", 0x1 }, | ||
1237 | { "In-3", 0x2 }, | ||
1238 | { "In-4", 0x3 }, | ||
1239 | { "CD", 0x4 }, | ||
1240 | }, | ||
1241 | }; | ||
1242 | |||
1243 | static struct alc_channel_mode alc880_test_modes[4] = { | ||
1244 | { 2, NULL }, | ||
1245 | { 4, NULL }, | ||
1246 | { 6, NULL }, | ||
1247 | { 8, NULL }, | ||
1248 | }; | ||
1249 | |||
1250 | static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
1251 | { | ||
1252 | static char *texts[] = { | ||
1253 | "N/A", "Line Out", "HP Out", | ||
1254 | "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" | ||
1255 | }; | ||
1256 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1257 | uinfo->count = 1; | ||
1258 | uinfo->value.enumerated.items = 8; | ||
1259 | if (uinfo->value.enumerated.item >= 8) | ||
1260 | uinfo->value.enumerated.item = 7; | ||
1261 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1265 | static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1266 | { | ||
1267 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1268 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1269 | unsigned int pin_ctl, item = 0; | ||
1270 | |||
1271 | pin_ctl = snd_hda_codec_read(codec, nid, 0, | ||
1272 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1273 | if (pin_ctl & AC_PINCTL_OUT_EN) { | ||
1274 | if (pin_ctl & AC_PINCTL_HP_EN) | ||
1275 | item = 2; | ||
1276 | else | ||
1277 | item = 1; | ||
1278 | } else if (pin_ctl & AC_PINCTL_IN_EN) { | ||
1279 | switch (pin_ctl & AC_PINCTL_VREFEN) { | ||
1280 | case AC_PINCTL_VREF_HIZ: item = 3; break; | ||
1281 | case AC_PINCTL_VREF_50: item = 4; break; | ||
1282 | case AC_PINCTL_VREF_GRD: item = 5; break; | ||
1283 | case AC_PINCTL_VREF_80: item = 6; break; | ||
1284 | case AC_PINCTL_VREF_100: item = 7; break; | ||
1285 | } | ||
1286 | } | ||
1287 | ucontrol->value.enumerated.item[0] = item; | ||
1288 | return 0; | ||
1289 | } | ||
1290 | |||
1291 | static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1292 | { | ||
1293 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1294 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1295 | static unsigned int ctls[] = { | ||
1296 | 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, | ||
1297 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, | ||
1298 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, | ||
1299 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, | ||
1300 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, | ||
1301 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, | ||
1302 | }; | ||
1303 | unsigned int old_ctl, new_ctl; | ||
1304 | |||
1305 | old_ctl = snd_hda_codec_read(codec, nid, 0, | ||
1306 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1307 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; | ||
1308 | if (old_ctl != new_ctl) { | ||
1309 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); | ||
1310 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1311 | ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000); | ||
1312 | return 1; | ||
1313 | } | ||
1314 | return 0; | ||
1315 | } | ||
1316 | |||
1317 | static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
1318 | { | ||
1319 | static char *texts[] = { | ||
1320 | "Front", "Surround", "CLFE", "Side" | ||
1321 | }; | ||
1322 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1323 | uinfo->count = 1; | ||
1324 | uinfo->value.enumerated.items = 4; | ||
1325 | if (uinfo->value.enumerated.item >= 4) | ||
1326 | uinfo->value.enumerated.item = 3; | ||
1327 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1328 | return 0; | ||
1329 | } | ||
1330 | |||
1331 | static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1332 | { | ||
1333 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1334 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1335 | unsigned int sel; | ||
1336 | |||
1337 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); | ||
1338 | ucontrol->value.enumerated.item[0] = sel & 3; | ||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1342 | static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1343 | { | ||
1344 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1345 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1346 | unsigned int sel; | ||
1347 | |||
1348 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; | ||
1349 | if (ucontrol->value.enumerated.item[0] != sel) { | ||
1350 | sel = ucontrol->value.enumerated.item[0] & 3; | ||
1351 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); | ||
1352 | return 1; | ||
1353 | } | ||
1354 | return 0; | ||
1355 | } | ||
1356 | |||
1357 | #define PIN_CTL_TEST(xname,nid) { \ | ||
1358 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1359 | .name = xname, \ | ||
1360 | .info = alc_test_pin_ctl_info, \ | ||
1361 | .get = alc_test_pin_ctl_get, \ | ||
1362 | .put = alc_test_pin_ctl_put, \ | ||
1363 | .private_value = nid \ | ||
1364 | } | ||
1365 | |||
1366 | #define PIN_SRC_TEST(xname,nid) { \ | ||
1367 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1368 | .name = xname, \ | ||
1369 | .info = alc_test_pin_src_info, \ | ||
1370 | .get = alc_test_pin_src_get, \ | ||
1371 | .put = alc_test_pin_src_put, \ | ||
1372 | .private_value = nid \ | ||
1373 | } | ||
1374 | |||
1375 | static snd_kcontrol_new_t alc880_test_mixer[] = { | ||
1376 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
1377 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
1378 | HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), | ||
1379 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
1380 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
1381 | ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | ||
1382 | ALC_BIND_MUTE("CLFE Playback Volume", 0x0e, 2, HDA_INPUT), | ||
1383 | ALC_BIND_MUTE("Side Playback Volume", 0x0f, 2, HDA_INPUT), | ||
1384 | PIN_CTL_TEST("Front Pin Mode", 0x14), | ||
1385 | PIN_CTL_TEST("Surround Pin Mode", 0x15), | ||
1386 | PIN_CTL_TEST("CLFE Pin Mode", 0x16), | ||
1387 | PIN_CTL_TEST("Side Pin Mode", 0x17), | ||
1388 | PIN_CTL_TEST("In-1 Pin Mode", 0x18), | ||
1389 | PIN_CTL_TEST("In-2 Pin Mode", 0x19), | ||
1390 | PIN_CTL_TEST("In-3 Pin Mode", 0x1a), | ||
1391 | PIN_CTL_TEST("In-4 Pin Mode", 0x1b), | ||
1392 | PIN_SRC_TEST("In-1 Pin Source", 0x18), | ||
1393 | PIN_SRC_TEST("In-2 Pin Source", 0x19), | ||
1394 | PIN_SRC_TEST("In-3 Pin Source", 0x1a), | ||
1395 | PIN_SRC_TEST("In-4 Pin Source", 0x1b), | ||
1396 | HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
1397 | HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
1398 | HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
1399 | HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
1400 | HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), | ||
1401 | HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), | ||
1402 | HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), | ||
1403 | HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), | ||
1404 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), | ||
1405 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), | ||
1406 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
1407 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
1408 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
1409 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
1410 | { | ||
1411 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1412 | .name = "Input Source", | ||
1413 | .count = 2, | ||
1414 | .info = alc_mux_enum_info, | ||
1415 | .get = alc_mux_enum_get, | ||
1416 | .put = alc_mux_enum_put, | ||
1417 | }, | ||
1418 | { | ||
1419 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1420 | .name = "Channel Mode", | ||
1421 | .info = alc880_ch_mode_info, | ||
1422 | .get = alc880_ch_mode_get, | ||
1423 | .put = alc880_ch_mode_put, | ||
1424 | }, | ||
1425 | { } /* end */ | ||
1426 | }; | ||
1427 | |||
1428 | static struct hda_verb alc880_test_init_verbs[] = { | ||
1429 | /* Unmute inputs of 0x0c - 0x0f */ | ||
1430 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1431 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1432 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1433 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1434 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1435 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1436 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1437 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
1438 | /* Vol output for 0x0c-0x0f */ | ||
1439 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1440 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1441 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1442 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
1443 | /* Set output pins 0x14-0x17 */ | ||
1444 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1445 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1446 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1447 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1448 | /* Unmute output pins 0x14-0x17 */ | ||
1449 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1450 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1451 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1452 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1453 | /* Set input pins 0x18-0x1c */ | ||
1454 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1455 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1456 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1457 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1458 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
1459 | /* Mute input pins 0x18-0x1b */ | ||
1460 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1461 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1462 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1463 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
1464 | /* ADC set up */ | ||
1465 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1466 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1467 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1468 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1469 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1470 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1471 | /* Analog input/passthru */ | ||
1472 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
1473 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1474 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
1475 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
1476 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
1477 | { } | ||
1478 | }; | ||
1479 | #endif | ||
1480 | |||
924 | /* | 1481 | /* |
925 | */ | 1482 | */ |
926 | 1483 | ||
927 | static struct hda_board_config alc880_cfg_tbl[] = { | 1484 | static struct hda_board_config alc880_cfg_tbl[] = { |
928 | /* Back 3 jack, front 2 jack */ | 1485 | /* Back 3 jack, front 2 jack */ |
929 | { .modelname = "3stack", .config = ALC880_3ST }, | 1486 | { .modelname = "3stack", .config = ALC880_3ST }, |
930 | { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST }, | 1487 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST }, |
931 | { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST }, | 1488 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST }, |
932 | { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST }, | 1489 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST }, |
933 | { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST }, | 1490 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST }, |
934 | { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST }, | 1491 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST }, |
935 | { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST }, | 1492 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST }, |
936 | { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST }, | 1493 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST }, |
937 | { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST }, | 1494 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST }, |
938 | { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST }, | 1495 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST }, |
939 | { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST }, | 1496 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST }, |
940 | { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST }, | 1497 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST }, |
941 | { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST }, | 1498 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST }, |
942 | { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST }, | 1499 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST }, |
943 | { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST }, | 1500 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST }, |
944 | { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST }, | 1501 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST }, |
945 | { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST }, | 1502 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, |
946 | { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST }, | 1503 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, |
947 | { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST }, | 1504 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, |
948 | { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST }, | 1505 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST }, |
949 | { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST }, | 1506 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST }, |
950 | { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST }, | 1507 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST }, |
951 | { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST }, | 1508 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST }, |
952 | { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST }, | 1509 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST }, |
953 | { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST }, | 1510 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST }, |
954 | { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST }, | 1511 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST }, |
955 | { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST }, | 1512 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST }, |
956 | { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST }, | 1513 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST }, |
957 | { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST }, | 1514 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST }, |
958 | { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST }, | 1515 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST }, |
959 | { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST }, | 1516 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST }, |
960 | { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST }, | 1517 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, |
961 | { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST }, | 1518 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, |
962 | 1519 | ||
963 | /* Back 3 jack, front 2 jack (Internal add Aux-In) */ | 1520 | /* Back 3 jack, front 2 jack (Internal add Aux-In) */ |
964 | { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST }, | 1521 | { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST }, |
1522 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST }, | ||
965 | 1523 | ||
966 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ | 1524 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ |
967 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, | 1525 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, |
968 | { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG }, | 1526 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, |
969 | 1527 | ||
970 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ | 1528 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ |
971 | { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG }, | 1529 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, |
972 | { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG }, | 1530 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG }, |
973 | { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG }, | 1531 | { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG }, |
974 | 1532 | ||
975 | /* Back 5 jack, front 2 jack */ | 1533 | /* Back 5 jack, front 2 jack */ |
976 | { .modelname = "5stack", .config = ALC880_5ST }, | 1534 | { .modelname = "5stack", .config = ALC880_5ST }, |
977 | { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST }, | 1535 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST }, |
978 | { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST }, | 1536 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST }, |
979 | { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST }, | 1537 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST }, |
980 | { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST }, | 1538 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST }, |
1539 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST }, | ||
981 | 1540 | ||
982 | /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */ | 1541 | /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */ |
983 | { .modelname = "5stack-digout", .config = ALC880_5ST_DIG }, | 1542 | { .modelname = "5stack-digout", .config = ALC880_5ST_DIG }, |
984 | { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG }, | 1543 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG }, |
985 | { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG }, | 1544 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG }, |
986 | { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG }, | 1545 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG }, |
987 | { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG }, | 1546 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG }, |
988 | { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG }, | 1547 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG }, |
989 | { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG }, | 1548 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG }, |
990 | { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG }, | 1549 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG }, |
991 | { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG }, | 1550 | { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG }, |
1551 | { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG }, | ||
1552 | /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */ | ||
1553 | { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG }, | ||
1554 | /* note subvendor = 0 below */ | ||
1555 | /* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */ | ||
992 | 1556 | ||
993 | { .modelname = "w810", .config = ALC880_W810 }, | 1557 | { .modelname = "w810", .config = ALC880_W810 }, |
994 | { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 }, | 1558 | { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 }, |
1559 | |||
1560 | { .modelname = "z71v", .config = ALC880_Z71V }, | ||
1561 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V }, | ||
1562 | |||
1563 | { .modelname = "6stack", .config = ALC880_6ST }, | ||
1564 | { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */ | ||
1565 | |||
1566 | { .modelname = "6stack-digout", .config = ALC880_6ST_DIG }, | ||
1567 | { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG }, | ||
1568 | { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG }, | ||
1569 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG }, | ||
1570 | { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG }, | ||
1571 | |||
1572 | { .modelname = "asus", .config = ALC880_ASUS }, | ||
1573 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG }, | ||
1574 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG }, | ||
1575 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG }, | ||
1576 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG }, | ||
1577 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS }, | ||
1578 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG }, | ||
1579 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS }, | ||
1580 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, | ||
1581 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, | ||
1582 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, | ||
1583 | |||
1584 | { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, | ||
1585 | { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG }, | ||
1586 | |||
1587 | { .modelname = "F1734", .config = ALC880_F1734 }, | ||
1588 | { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 }, | ||
1589 | |||
1590 | #ifdef CONFIG_SND_DEBUG | ||
1591 | { .modelname = "test", .config = ALC880_TEST }, | ||
1592 | #endif | ||
995 | 1593 | ||
996 | {} | 1594 | {} |
997 | }; | 1595 | }; |
998 | 1596 | ||
1597 | /* | ||
1598 | * configuration template - to be copied to the spec instance | ||
1599 | */ | ||
1600 | struct alc_config_preset { | ||
1601 | snd_kcontrol_new_t *mixers[4]; | ||
1602 | const struct hda_verb *init_verbs[4]; | ||
1603 | unsigned int num_dacs; | ||
1604 | hda_nid_t *dac_nids; | ||
1605 | hda_nid_t dig_out_nid; /* optional */ | ||
1606 | hda_nid_t hp_nid; /* optional */ | ||
1607 | unsigned int num_adc_nids; | ||
1608 | hda_nid_t *adc_nids; | ||
1609 | unsigned int num_channel_mode; | ||
1610 | const struct alc_channel_mode *channel_mode; | ||
1611 | const struct hda_input_mux *input_mux; | ||
1612 | }; | ||
1613 | |||
1614 | static struct alc_config_preset alc880_presets[] = { | ||
1615 | [ALC880_3ST] = { | ||
1616 | .mixers = { alc880_three_stack_mixer }, | ||
1617 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, | ||
1618 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1619 | .dac_nids = alc880_dac_nids, | ||
1620 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1621 | .channel_mode = alc880_threestack_modes, | ||
1622 | .input_mux = &alc880_capture_source, | ||
1623 | }, | ||
1624 | [ALC880_3ST_DIG] = { | ||
1625 | .mixers = { alc880_three_stack_mixer }, | ||
1626 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs }, | ||
1627 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1628 | .dac_nids = alc880_dac_nids, | ||
1629 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1630 | .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), | ||
1631 | .channel_mode = alc880_threestack_modes, | ||
1632 | .input_mux = &alc880_capture_source, | ||
1633 | }, | ||
1634 | [ALC880_5ST] = { | ||
1635 | .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer}, | ||
1636 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, | ||
1637 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1638 | .dac_nids = alc880_dac_nids, | ||
1639 | .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), | ||
1640 | .channel_mode = alc880_fivestack_modes, | ||
1641 | .input_mux = &alc880_capture_source, | ||
1642 | }, | ||
1643 | [ALC880_5ST_DIG] = { | ||
1644 | .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer }, | ||
1645 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, | ||
1646 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), | ||
1647 | .dac_nids = alc880_dac_nids, | ||
1648 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1649 | .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes), | ||
1650 | .channel_mode = alc880_fivestack_modes, | ||
1651 | .input_mux = &alc880_capture_source, | ||
1652 | }, | ||
1653 | [ALC880_6ST] = { | ||
1654 | .mixers = { alc880_six_stack_mixer }, | ||
1655 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, | ||
1656 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), | ||
1657 | .dac_nids = alc880_6st_dac_nids, | ||
1658 | .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), | ||
1659 | .channel_mode = alc880_sixstack_modes, | ||
1660 | .input_mux = &alc880_6stack_capture_source, | ||
1661 | }, | ||
1662 | [ALC880_6ST_DIG] = { | ||
1663 | .mixers = { alc880_six_stack_mixer }, | ||
1664 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, | ||
1665 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), | ||
1666 | .dac_nids = alc880_6st_dac_nids, | ||
1667 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1668 | .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), | ||
1669 | .channel_mode = alc880_sixstack_modes, | ||
1670 | .input_mux = &alc880_6stack_capture_source, | ||
1671 | }, | ||
1672 | [ALC880_W810] = { | ||
1673 | .mixers = { alc880_w810_base_mixer }, | ||
1674 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs, | ||
1675 | alc880_gpio2_init_verbs }, | ||
1676 | .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), | ||
1677 | .dac_nids = alc880_w810_dac_nids, | ||
1678 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1679 | .num_channel_mode = ARRAY_SIZE(alc880_w810_modes), | ||
1680 | .channel_mode = alc880_w810_modes, | ||
1681 | .input_mux = &alc880_capture_source, | ||
1682 | }, | ||
1683 | [ALC880_Z71V] = { | ||
1684 | .mixers = { alc880_z71v_mixer }, | ||
1685 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs }, | ||
1686 | .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), | ||
1687 | .dac_nids = alc880_z71v_dac_nids, | ||
1688 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1689 | .hp_nid = 0x03, | ||
1690 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1691 | .channel_mode = alc880_2_jack_modes, | ||
1692 | .input_mux = &alc880_capture_source, | ||
1693 | }, | ||
1694 | [ALC880_F1734] = { | ||
1695 | .mixers = { alc880_f1734_mixer }, | ||
1696 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs }, | ||
1697 | .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids), | ||
1698 | .dac_nids = alc880_f1734_dac_nids, | ||
1699 | .hp_nid = 0x02, | ||
1700 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
1701 | .channel_mode = alc880_2_jack_modes, | ||
1702 | .input_mux = &alc880_capture_source, | ||
1703 | }, | ||
1704 | [ALC880_ASUS] = { | ||
1705 | .mixers = { alc880_asus_mixer }, | ||
1706 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, | ||
1707 | alc880_gpio1_init_verbs }, | ||
1708 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1709 | .dac_nids = alc880_asus_dac_nids, | ||
1710 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1711 | .channel_mode = alc880_asus_modes, | ||
1712 | .input_mux = &alc880_capture_source, | ||
1713 | }, | ||
1714 | [ALC880_ASUS_DIG] = { | ||
1715 | .mixers = { alc880_asus_mixer }, | ||
1716 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, | ||
1717 | alc880_gpio1_init_verbs }, | ||
1718 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1719 | .dac_nids = alc880_asus_dac_nids, | ||
1720 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1721 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1722 | .channel_mode = alc880_asus_modes, | ||
1723 | .input_mux = &alc880_capture_source, | ||
1724 | }, | ||
1725 | [ALC880_ASUS_W1V] = { | ||
1726 | .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, | ||
1727 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, | ||
1728 | alc880_gpio1_init_verbs }, | ||
1729 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1730 | .dac_nids = alc880_asus_dac_nids, | ||
1731 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1732 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1733 | .channel_mode = alc880_asus_modes, | ||
1734 | .input_mux = &alc880_capture_source, | ||
1735 | }, | ||
1736 | [ALC880_UNIWILL_DIG] = { | ||
1737 | .mixers = { alc880_asus_mixer }, | ||
1738 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs }, | ||
1739 | .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), | ||
1740 | .dac_nids = alc880_asus_dac_nids, | ||
1741 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1742 | .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), | ||
1743 | .channel_mode = alc880_asus_modes, | ||
1744 | .input_mux = &alc880_capture_source, | ||
1745 | }, | ||
1746 | #ifdef CONFIG_SND_DEBUG | ||
1747 | [ALC880_TEST] = { | ||
1748 | .mixers = { alc880_test_mixer }, | ||
1749 | .init_verbs = { alc880_test_init_verbs }, | ||
1750 | .num_dacs = ARRAY_SIZE(alc880_test_dac_nids), | ||
1751 | .dac_nids = alc880_test_dac_nids, | ||
1752 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
1753 | .num_channel_mode = ARRAY_SIZE(alc880_test_modes), | ||
1754 | .channel_mode = alc880_test_modes, | ||
1755 | .input_mux = &alc880_test_capture_source, | ||
1756 | }, | ||
1757 | #endif | ||
1758 | }; | ||
1759 | |||
1760 | /* | ||
1761 | * Automatic parse of I/O pins from the BIOS configuration | ||
1762 | */ | ||
1763 | |||
1764 | #define NUM_CONTROL_ALLOC 32 | ||
1765 | #define NUM_VERB_ALLOC 32 | ||
1766 | |||
1767 | enum { | ||
1768 | ALC_CTL_WIDGET_VOL, | ||
1769 | ALC_CTL_WIDGET_MUTE, | ||
1770 | ALC_CTL_BIND_MUTE, | ||
1771 | }; | ||
1772 | static snd_kcontrol_new_t alc880_control_templates[] = { | ||
1773 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | ||
1774 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | ||
1775 | ALC_BIND_MUTE(NULL, 0, 0, 0), | ||
1776 | }; | ||
1777 | |||
1778 | /* add dynamic controls */ | ||
1779 | static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val) | ||
1780 | { | ||
1781 | snd_kcontrol_new_t *knew; | ||
1782 | |||
1783 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | ||
1784 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | ||
1785 | |||
1786 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | ||
1787 | if (! knew) | ||
1788 | return -ENOMEM; | ||
1789 | if (spec->kctl_alloc) { | ||
1790 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
1791 | kfree(spec->kctl_alloc); | ||
1792 | } | ||
1793 | spec->kctl_alloc = knew; | ||
1794 | spec->num_kctl_alloc = num; | ||
1795 | } | ||
1796 | |||
1797 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
1798 | *knew = alc880_control_templates[type]; | ||
1799 | knew->name = kstrdup(name, GFP_KERNEL); | ||
1800 | if (! knew->name) | ||
1801 | return -ENOMEM; | ||
1802 | knew->private_value = val; | ||
1803 | spec->num_kctl_used++; | ||
1804 | return 0; | ||
1805 | } | ||
1806 | |||
1807 | #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) | ||
1808 | #define alc880_fixed_pin_idx(nid) ((nid) - 0x14) | ||
1809 | #define alc880_is_multi_pin(nid) ((nid) >= 0x18) | ||
1810 | #define alc880_multi_pin_idx(nid) ((nid) - 0x18) | ||
1811 | #define alc880_is_input_pin(nid) ((nid) >= 0x18) | ||
1812 | #define alc880_input_pin_idx(nid) ((nid) - 0x18) | ||
1813 | #define alc880_idx_to_dac(nid) ((nid) + 0x02) | ||
1814 | #define alc880_dac_to_idx(nid) ((nid) - 0x02) | ||
1815 | #define alc880_idx_to_mixer(nid) ((nid) + 0x0c) | ||
1816 | #define alc880_idx_to_selector(nid) ((nid) + 0x10) | ||
1817 | #define ALC880_PIN_CD_NID 0x1c | ||
1818 | |||
1819 | /* fill in the dac_nids table from the parsed pin configuration */ | ||
1820 | static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | ||
1821 | { | ||
1822 | hda_nid_t nid; | ||
1823 | int assigned[4]; | ||
1824 | int i, j; | ||
1825 | |||
1826 | memset(assigned, 0, sizeof(assigned)); | ||
1827 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
1828 | |||
1829 | /* check the pins hardwired to audio widget */ | ||
1830 | for (i = 0; i < cfg->line_outs; i++) { | ||
1831 | nid = cfg->line_out_pins[i]; | ||
1832 | if (alc880_is_fixed_pin(nid)) { | ||
1833 | int idx = alc880_fixed_pin_idx(nid); | ||
1834 | spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx); | ||
1835 | assigned[idx] = 1; | ||
1836 | } | ||
1837 | } | ||
1838 | /* left pins can be connect to any audio widget */ | ||
1839 | for (i = 0; i < cfg->line_outs; i++) { | ||
1840 | nid = cfg->line_out_pins[i]; | ||
1841 | if (alc880_is_fixed_pin(nid)) | ||
1842 | continue; | ||
1843 | /* search for an empty channel */ | ||
1844 | for (j = 0; j < cfg->line_outs; j++) { | ||
1845 | if (! assigned[j]) { | ||
1846 | spec->multiout.dac_nids[i] = alc880_idx_to_dac(j); | ||
1847 | assigned[j] = 1; | ||
1848 | break; | ||
1849 | } | ||
1850 | } | ||
1851 | } | ||
1852 | spec->multiout.num_dacs = cfg->line_outs; | ||
1853 | return 0; | ||
1854 | } | ||
1855 | |||
1856 | /* add playback controls from the parsed DAC table */ | ||
1857 | static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | ||
1858 | { | ||
1859 | char name[32]; | ||
1860 | static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; | ||
1861 | hda_nid_t nid; | ||
1862 | int i, err; | ||
1863 | |||
1864 | for (i = 0; i < cfg->line_outs; i++) { | ||
1865 | if (! spec->multiout.dac_nids[i]) | ||
1866 | continue; | ||
1867 | nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i])); | ||
1868 | if (i == 2) { | ||
1869 | /* Center/LFE */ | ||
1870 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume", | ||
1871 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | ||
1872 | return err; | ||
1873 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume", | ||
1874 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | ||
1875 | return err; | ||
1876 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch", | ||
1877 | HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0) | ||
1878 | return err; | ||
1879 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch", | ||
1880 | HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0) | ||
1881 | return err; | ||
1882 | } else { | ||
1883 | sprintf(name, "%s Playback Volume", chname[i]); | ||
1884 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
1885 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
1886 | return err; | ||
1887 | sprintf(name, "%s Playback Switch", chname[i]); | ||
1888 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name, | ||
1889 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) | ||
1890 | return err; | ||
1891 | } | ||
1892 | } | ||
1893 | |||
1894 | return 0; | ||
1895 | } | ||
1896 | |||
1897 | /* add playback controls for HP output */ | ||
1898 | static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin) | ||
1899 | { | ||
1900 | hda_nid_t nid; | ||
1901 | int err; | ||
1902 | |||
1903 | if (! pin) | ||
1904 | return 0; | ||
1905 | |||
1906 | if (alc880_is_fixed_pin(pin)) { | ||
1907 | nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); | ||
1908 | if (! spec->multiout.dac_nids[0]) { | ||
1909 | /* use this as the primary output */ | ||
1910 | spec->multiout.dac_nids[0] = nid; | ||
1911 | if (! spec->multiout.num_dacs) | ||
1912 | spec->multiout.num_dacs = 1; | ||
1913 | } else | ||
1914 | /* specify the DAC as the extra HP output */ | ||
1915 | spec->multiout.hp_nid = nid; | ||
1916 | /* control HP volume/switch on the output mixer amp */ | ||
1917 | nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); | ||
1918 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume", | ||
1919 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
1920 | return err; | ||
1921 | if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Headphone Playback Switch", | ||
1922 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0) | ||
1923 | return err; | ||
1924 | } else if (alc880_is_multi_pin(pin)) { | ||
1925 | /* set manual connection */ | ||
1926 | if (! spec->multiout.dac_nids[0]) { | ||
1927 | /* use this as the primary output */ | ||
1928 | spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin)); | ||
1929 | if (! spec->multiout.num_dacs) | ||
1930 | spec->multiout.num_dacs = 1; | ||
1931 | } | ||
1932 | /* we have only a switch on HP-out PIN */ | ||
1933 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | ||
1934 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0) | ||
1935 | return err; | ||
1936 | } | ||
1937 | return 0; | ||
1938 | } | ||
1939 | |||
1940 | /* create input playback/capture controls for the given pin */ | ||
1941 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname) | ||
1942 | { | ||
1943 | char name[32]; | ||
1944 | int err, idx; | ||
1945 | |||
1946 | sprintf(name, "%s Playback Volume", ctlname); | ||
1947 | idx = alc880_input_pin_idx(pin); | ||
1948 | if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
1949 | HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0) | ||
1950 | return err; | ||
1951 | sprintf(name, "%s Playback Switch", ctlname); | ||
1952 | if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | ||
1953 | HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0) | ||
1954 | return err; | ||
1955 | return 0; | ||
1956 | } | ||
1957 | |||
1958 | /* create playback/capture controls for input pins */ | ||
1959 | static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) | ||
1960 | { | ||
1961 | static char *labels[AUTO_PIN_LAST] = { | ||
1962 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" | ||
1963 | }; | ||
1964 | struct hda_input_mux *imux = &spec->private_imux; | ||
1965 | int i, err; | ||
1966 | |||
1967 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
1968 | if (alc880_is_input_pin(cfg->input_pins[i])) { | ||
1969 | err = new_analog_input(spec, cfg->input_pins[i], labels[i]); | ||
1970 | if (err < 0) | ||
1971 | return err; | ||
1972 | imux->items[imux->num_items].label = labels[i]; | ||
1973 | imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]); | ||
1974 | imux->num_items++; | ||
1975 | } | ||
1976 | } | ||
1977 | return 0; | ||
1978 | } | ||
1979 | |||
1980 | static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type, | ||
1981 | int dac_idx) | ||
1982 | { | ||
1983 | /* set as output */ | ||
1984 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | ||
1985 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); | ||
1986 | /* need the manual connection? */ | ||
1987 | if (alc880_is_multi_pin(nid)) { | ||
1988 | struct alc_spec *spec = codec->spec; | ||
1989 | int idx = alc880_multi_pin_idx(nid); | ||
1990 | snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0, | ||
1991 | AC_VERB_SET_CONNECT_SEL, | ||
1992 | alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx])); | ||
1993 | } | ||
1994 | } | ||
1995 | |||
1996 | static void alc880_auto_init_multi_out(struct hda_codec *codec) | ||
1997 | { | ||
1998 | struct alc_spec *spec = codec->spec; | ||
1999 | int i; | ||
2000 | |||
2001 | for (i = 0; i < spec->autocfg.line_outs; i++) { | ||
2002 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
2003 | alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); | ||
2004 | } | ||
2005 | } | ||
2006 | |||
2007 | static void alc880_auto_init_hp_out(struct hda_codec *codec) | ||
2008 | { | ||
2009 | struct alc_spec *spec = codec->spec; | ||
2010 | hda_nid_t pin; | ||
2011 | |||
2012 | pin = spec->autocfg.hp_pin; | ||
2013 | if (pin) /* connect to front */ | ||
2014 | alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | ||
2015 | } | ||
2016 | |||
2017 | static void alc880_auto_init_analog_input(struct hda_codec *codec) | ||
2018 | { | ||
2019 | struct alc_spec *spec = codec->spec; | ||
2020 | int i; | ||
2021 | |||
2022 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
2023 | hda_nid_t nid = spec->autocfg.input_pins[i]; | ||
2024 | if (alc880_is_input_pin(nid)) { | ||
2025 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
2026 | i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); | ||
2027 | if (nid != ALC880_PIN_CD_NID) | ||
2028 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
2029 | AMP_OUT_MUTE); | ||
2030 | } | ||
2031 | } | ||
2032 | } | ||
2033 | |||
2034 | /* parse the BIOS configuration and set up the alc_spec */ | ||
2035 | /* return 1 if successful, 0 if the proper config is not found, or a negative error code */ | ||
2036 | static int alc880_parse_auto_config(struct hda_codec *codec) | ||
2037 | { | ||
2038 | struct alc_spec *spec = codec->spec; | ||
2039 | int err; | ||
2040 | |||
2041 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0) | ||
2042 | return err; | ||
2043 | if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0) | ||
2044 | return err; | ||
2045 | if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) | ||
2046 | return 0; /* can't find valid BIOS pin config */ | ||
2047 | if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | ||
2048 | (err = alc880_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 || | ||
2049 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | ||
2050 | return err; | ||
2051 | |||
2052 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | ||
2053 | |||
2054 | if (spec->autocfg.dig_out_pin) | ||
2055 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | ||
2056 | if (spec->autocfg.dig_in_pin) | ||
2057 | spec->dig_in_nid = ALC880_DIGIN_NID; | ||
2058 | |||
2059 | if (spec->kctl_alloc) | ||
2060 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | ||
2061 | |||
2062 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; | ||
2063 | |||
2064 | spec->input_mux = &spec->private_imux; | ||
2065 | |||
2066 | return 1; | ||
2067 | } | ||
2068 | |||
2069 | /* init callback for auto-configuration model -- overriding the default init */ | ||
2070 | static int alc880_auto_init(struct hda_codec *codec) | ||
2071 | { | ||
2072 | alc_init(codec); | ||
2073 | alc880_auto_init_multi_out(codec); | ||
2074 | alc880_auto_init_hp_out(codec); | ||
2075 | alc880_auto_init_analog_input(codec); | ||
2076 | return 0; | ||
2077 | } | ||
2078 | |||
2079 | /* | ||
2080 | * OK, here we have finally the patch for ALC880 | ||
2081 | */ | ||
2082 | |||
999 | static int patch_alc880(struct hda_codec *codec) | 2083 | static int patch_alc880(struct hda_codec *codec) |
1000 | { | 2084 | { |
1001 | struct alc_spec *spec; | 2085 | struct alc_spec *spec; |
1002 | int board_config; | 2086 | int board_config; |
2087 | int i, err; | ||
1003 | 2088 | ||
1004 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 2089 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
1005 | if (spec == NULL) | 2090 | if (spec == NULL) |
1006 | return -ENOMEM; | 2091 | return -ENOMEM; |
1007 | 2092 | ||
2093 | init_MUTEX(&spec->bind_mutex); | ||
1008 | codec->spec = spec; | 2094 | codec->spec = spec; |
1009 | 2095 | ||
1010 | board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); | 2096 | board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); |
1011 | if (board_config < 0) { | 2097 | if (board_config < 0 || board_config >= ALC880_MODEL_LAST) { |
1012 | snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n"); | 2098 | printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n"); |
1013 | board_config = ALC880_MINIMAL; | 2099 | board_config = ALC880_AUTO; |
1014 | } | 2100 | } |
1015 | 2101 | ||
1016 | switch (board_config) { | 2102 | if (board_config == ALC880_AUTO) { |
1017 | case ALC880_W810: | 2103 | /* automatic parse from the BIOS config */ |
1018 | spec->mixers[spec->num_mixers] = alc880_w810_base_mixer; | 2104 | err = alc880_parse_auto_config(codec); |
1019 | spec->num_mixers++; | 2105 | if (err < 0) { |
1020 | break; | 2106 | alc_free(codec); |
1021 | case ALC880_5ST: | 2107 | return err; |
1022 | case ALC880_5ST_DIG: | 2108 | } else if (! err) { |
1023 | spec->mixers[spec->num_mixers] = alc880_five_stack_mixer; | 2109 | printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n"); |
1024 | spec->num_mixers++; | 2110 | board_config = ALC880_3ST; |
1025 | break; | 2111 | } |
1026 | default: | ||
1027 | spec->mixers[spec->num_mixers] = alc880_base_mixer; | ||
1028 | spec->num_mixers++; | ||
1029 | break; | ||
1030 | } | 2112 | } |
1031 | 2113 | ||
1032 | switch (board_config) { | 2114 | if (board_config != ALC880_AUTO) { |
1033 | case ALC880_3ST_DIG: | 2115 | /* set up from the preset table */ |
1034 | case ALC880_5ST_DIG: | 2116 | const struct alc_config_preset *preset; |
1035 | case ALC880_W810: | ||
1036 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | ||
1037 | break; | ||
1038 | default: | ||
1039 | break; | ||
1040 | } | ||
1041 | 2117 | ||
1042 | switch (board_config) { | 2118 | preset = &alc880_presets[board_config]; |
1043 | case ALC880_3ST: | ||
1044 | case ALC880_3ST_DIG: | ||
1045 | case ALC880_5ST: | ||
1046 | case ALC880_5ST_DIG: | ||
1047 | case ALC880_W810: | ||
1048 | spec->front_panel = 1; | ||
1049 | break; | ||
1050 | default: | ||
1051 | break; | ||
1052 | } | ||
1053 | 2119 | ||
1054 | switch (board_config) { | 2120 | for (i = 0; preset->mixers[i]; i++) { |
1055 | case ALC880_5ST: | 2121 | snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break); |
1056 | case ALC880_5ST_DIG: | 2122 | spec->mixers[spec->num_mixers++] = preset->mixers[i]; |
1057 | spec->init_verbs = alc880_init_verbs_five_stack; | 2123 | } |
1058 | spec->channel_mode = alc880_fivestack_modes; | 2124 | for (i = 0; preset->init_verbs[i]; i++) { |
1059 | spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes); | 2125 | snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break); |
1060 | break; | 2126 | spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i]; |
1061 | case ALC880_W810: | 2127 | } |
1062 | spec->init_verbs = alc880_w810_init_verbs; | 2128 | |
1063 | spec->channel_mode = alc880_w810_modes; | 2129 | spec->channel_mode = preset->channel_mode; |
1064 | spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes); | 2130 | spec->num_channel_mode = preset->num_channel_mode; |
1065 | break; | 2131 | |
1066 | default: | 2132 | spec->multiout.max_channels = spec->channel_mode[0].channels; |
1067 | spec->init_verbs = alc880_init_verbs_three_stack; | 2133 | |
1068 | spec->channel_mode = alc880_threestack_modes; | 2134 | spec->multiout.num_dacs = preset->num_dacs; |
1069 | spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes); | 2135 | spec->multiout.dac_nids = preset->dac_nids; |
1070 | break; | 2136 | spec->multiout.dig_out_nid = preset->dig_out_nid; |
2137 | spec->multiout.hp_nid = preset->hp_nid; | ||
2138 | |||
2139 | spec->input_mux = preset->input_mux; | ||
2140 | |||
2141 | spec->num_adc_nids = preset->num_adc_nids; | ||
2142 | spec->adc_nids = preset->adc_nids; | ||
1071 | } | 2143 | } |
1072 | 2144 | ||
1073 | spec->stream_name_analog = "ALC880 Analog"; | 2145 | spec->stream_name_analog = "ALC880 Analog"; |
@@ -1078,34 +2150,64 @@ static int patch_alc880(struct hda_codec *codec) | |||
1078 | spec->stream_digital_playback = &alc880_pcm_digital_playback; | 2150 | spec->stream_digital_playback = &alc880_pcm_digital_playback; |
1079 | spec->stream_digital_capture = &alc880_pcm_digital_capture; | 2151 | spec->stream_digital_capture = &alc880_pcm_digital_capture; |
1080 | 2152 | ||
1081 | spec->multiout.max_channels = spec->channel_mode[0].channels; | 2153 | if (! spec->adc_nids && spec->input_mux) { |
1082 | 2154 | /* check whether NID 0x07 is valid */ | |
1083 | switch (board_config) { | 2155 | unsigned int wcap = snd_hda_param_read(codec, alc880_adc_nids[0], |
1084 | case ALC880_W810: | 2156 | AC_PAR_AUDIO_WIDGET_CAP); |
1085 | spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids); | 2157 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */ |
1086 | spec->multiout.dac_nids = alc880_w810_dac_nids; | 2158 | if (wcap != AC_WID_AUD_IN) { |
1087 | // No dedicated headphone socket - it's shared with built-in speakers. | 2159 | spec->adc_nids = alc880_adc_nids_alt; |
1088 | break; | 2160 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt); |
1089 | default: | 2161 | spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer; |
1090 | spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids); | 2162 | spec->num_mixers++; |
1091 | spec->multiout.dac_nids = alc880_dac_nids; | 2163 | } else { |
1092 | spec->multiout.hp_nid = 0x03; /* rear-surround NID */ | 2164 | spec->adc_nids = alc880_adc_nids; |
1093 | break; | 2165 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); |
2166 | spec->mixers[spec->num_mixers] = alc880_capture_mixer; | ||
2167 | spec->num_mixers++; | ||
2168 | } | ||
1094 | } | 2169 | } |
1095 | 2170 | ||
1096 | spec->input_mux = &alc880_capture_source; | ||
1097 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); | ||
1098 | spec->adc_nids = alc880_adc_nids; | ||
1099 | |||
1100 | codec->patch_ops = alc_patch_ops; | 2171 | codec->patch_ops = alc_patch_ops; |
2172 | if (board_config == ALC880_AUTO) | ||
2173 | codec->patch_ops.init = alc880_auto_init; | ||
1101 | 2174 | ||
1102 | return 0; | 2175 | return 0; |
1103 | } | 2176 | } |
1104 | 2177 | ||
2178 | |||
1105 | /* | 2179 | /* |
1106 | * ALC260 support | 2180 | * ALC260 support |
1107 | */ | 2181 | */ |
1108 | 2182 | ||
2183 | static hda_nid_t alc260_dac_nids[1] = { | ||
2184 | /* front */ | ||
2185 | 0x02, | ||
2186 | }; | ||
2187 | |||
2188 | static hda_nid_t alc260_adc_nids[1] = { | ||
2189 | /* ADC0 */ | ||
2190 | 0x04, | ||
2191 | }; | ||
2192 | |||
2193 | static hda_nid_t alc260_hp_adc_nids[1] = { | ||
2194 | /* ADC1 */ | ||
2195 | 0x05, | ||
2196 | }; | ||
2197 | |||
2198 | #define ALC260_DIGOUT_NID 0x03 | ||
2199 | #define ALC260_DIGIN_NID 0x06 | ||
2200 | |||
2201 | static struct hda_input_mux alc260_capture_source = { | ||
2202 | .num_items = 4, | ||
2203 | .items = { | ||
2204 | { "Mic", 0x0 }, | ||
2205 | { "Front Mic", 0x1 }, | ||
2206 | { "Line", 0x2 }, | ||
2207 | { "CD", 0x4 }, | ||
2208 | }, | ||
2209 | }; | ||
2210 | |||
1109 | /* | 2211 | /* |
1110 | * This is just place-holder, so there's something for alc_build_pcms to look | 2212 | * This is just place-holder, so there's something for alc_build_pcms to look |
1111 | * at when it calculates the maximum number of channels. ALC260 has no mixer | 2213 | * at when it calculates the maximum number of channels. ALC260 has no mixer |
@@ -1116,11 +2218,9 @@ static struct alc_channel_mode alc260_modes[1] = { | |||
1116 | { 2, NULL }, | 2218 | { 2, NULL }, |
1117 | }; | 2219 | }; |
1118 | 2220 | ||
1119 | snd_kcontrol_new_t alc260_base_mixer[] = { | 2221 | static snd_kcontrol_new_t alc260_base_mixer[] = { |
1120 | HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), | 2222 | HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), |
1121 | /* use LINE2 for the output */ | 2223 | ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), |
1122 | /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */ | ||
1123 | HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
1124 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | 2224 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), |
1125 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | 2225 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), |
1126 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | 2226 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), |
@@ -1132,9 +2232,9 @@ snd_kcontrol_new_t alc260_base_mixer[] = { | |||
1132 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), | 2232 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT), |
1133 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), | 2233 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT), |
1134 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), | 2234 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), |
1135 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT), | 2235 | ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), |
1136 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), | 2236 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), |
1137 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT), | 2237 | ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT), |
1138 | HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), | 2238 | HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), |
1139 | HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), | 2239 | HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), |
1140 | { | 2240 | { |
@@ -1147,60 +2247,91 @@ snd_kcontrol_new_t alc260_base_mixer[] = { | |||
1147 | { } /* end */ | 2247 | { } /* end */ |
1148 | }; | 2248 | }; |
1149 | 2249 | ||
2250 | static snd_kcontrol_new_t alc260_hp_mixer[] = { | ||
2251 | HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), | ||
2252 | ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), | ||
2253 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | ||
2254 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | ||
2255 | HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), | ||
2256 | HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT), | ||
2257 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | ||
2258 | HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), | ||
2259 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), | ||
2260 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), | ||
2261 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), | ||
2262 | ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), | ||
2263 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), | ||
2264 | ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT), | ||
2265 | HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), | ||
2266 | HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT), | ||
2267 | { | ||
2268 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2269 | .name = "Capture Source", | ||
2270 | .info = alc_mux_enum_info, | ||
2271 | .get = alc_mux_enum_get, | ||
2272 | .put = alc_mux_enum_put, | ||
2273 | }, | ||
2274 | { } /* end */ | ||
2275 | }; | ||
2276 | |||
1150 | static struct hda_verb alc260_init_verbs[] = { | 2277 | static struct hda_verb alc260_init_verbs[] = { |
1151 | /* Line In pin widget for input */ | 2278 | /* Line In pin widget for input */ |
1152 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 2279 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
1153 | /* CD pin widget for input */ | 2280 | /* CD pin widget for input */ |
1154 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 2281 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
1155 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | 2282 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ |
1156 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 2283 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
1157 | /* Mic2 (front panel) pin widget for input and vref at 80% */ | 2284 | /* Mic2 (front panel) pin widget for input and vref at 80% */ |
1158 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 2285 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
1159 | /* LINE-2 is used for line-out in rear */ | 2286 | /* LINE-2 is used for line-out in rear */ |
1160 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2287 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1161 | /* select line-out */ | 2288 | /* select line-out */ |
1162 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | 2289 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1163 | /* LINE-OUT pin */ | 2290 | /* LINE-OUT pin */ |
1164 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2291 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1165 | /* enable HP */ | 2292 | /* enable HP */ |
1166 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2293 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
1167 | /* enable Mono */ | 2294 | /* enable Mono */ |
1168 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2295 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1169 | /* unmute amp left and right */ | 2296 | /* mute capture amp left and right */ |
1170 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 2297 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1171 | /* set connection select to line in (default select for this ADC) */ | 2298 | /* set connection select to line in (default select for this ADC) */ |
1172 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, | 2299 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x02}, |
1173 | /* unmute Line-Out mixer amp left and right (volume = 0) */ | 2300 | /* mute capture amp left and right */ |
1174 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2301 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1175 | /* mute pin widget amp left and right (no gain on this amp) */ | 2302 | /* set connection select to line in (default select for this ADC) */ |
1176 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2303 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, |
1177 | /* unmute HP mixer amp left and right (volume = 0) */ | 2304 | /* set vol=0 Line-Out mixer amp left and right */ |
1178 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2305 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1179 | /* mute pin widget amp left and right (no gain on this amp) */ | 2306 | /* unmute pin widget amp left and right (no gain on this amp) */ |
1180 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 2307 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1181 | /* unmute Mono mixer amp left and right (volume = 0) */ | 2308 | /* set vol=0 HP mixer amp left and right */ |
1182 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2309 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1183 | /* mute pin widget amp left and right (no gain on this amp) */ | 2310 | /* unmute pin widget amp left and right (no gain on this amp) */ |
1184 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 2311 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1185 | /* mute LINE-2 out */ | 2312 | /* set vol=0 Mono mixer amp left and right */ |
1186 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 2313 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
2314 | /* unmute pin widget amp left and right (no gain on this amp) */ | ||
2315 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2316 | /* unmute LINE-2 out pin */ | ||
2317 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1187 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ | 2318 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */ |
1188 | /* unmute CD */ | 2319 | /* mute CD */ |
1189 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | 2320 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, |
1190 | /* unmute Line In */ | 2321 | /* mute Line In */ |
1191 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | 2322 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, |
1192 | /* unmute Mic */ | 2323 | /* mute Mic */ |
1193 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2324 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1194 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ | 2325 | /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */ |
1195 | /* Unmute Front out path */ | 2326 | /* mute Front out path */ |
1196 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2327 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1197 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 2328 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
1198 | /* Unmute Headphone out path */ | 2329 | /* mute Headphone out path */ |
1199 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2330 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1200 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 2331 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
1201 | /* Unmute Mono out path */ | 2332 | /* mute Mono out path */ |
1202 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2333 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1203 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 2334 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
1204 | { } | 2335 | { } |
1205 | }; | 2336 | }; |
1206 | 2337 | ||
@@ -1208,30 +2339,52 @@ static struct hda_pcm_stream alc260_pcm_analog_playback = { | |||
1208 | .substreams = 1, | 2339 | .substreams = 1, |
1209 | .channels_min = 2, | 2340 | .channels_min = 2, |
1210 | .channels_max = 2, | 2341 | .channels_max = 2, |
1211 | .nid = 0x2, | ||
1212 | }; | 2342 | }; |
1213 | 2343 | ||
1214 | static struct hda_pcm_stream alc260_pcm_analog_capture = { | 2344 | static struct hda_pcm_stream alc260_pcm_analog_capture = { |
1215 | .substreams = 1, | 2345 | .substreams = 1, |
1216 | .channels_min = 2, | 2346 | .channels_min = 2, |
1217 | .channels_max = 2, | 2347 | .channels_max = 2, |
1218 | .nid = 0x4, | 2348 | }; |
2349 | |||
2350 | static struct hda_board_config alc260_cfg_tbl[] = { | ||
2351 | { .modelname = "hp", .config = ALC260_HP }, | ||
2352 | { .pci_subvendor = 0x103c, .config = ALC260_HP }, | ||
2353 | {} | ||
1219 | }; | 2354 | }; |
1220 | 2355 | ||
1221 | static int patch_alc260(struct hda_codec *codec) | 2356 | static int patch_alc260(struct hda_codec *codec) |
1222 | { | 2357 | { |
1223 | struct alc_spec *spec; | 2358 | struct alc_spec *spec; |
2359 | int board_config; | ||
1224 | 2360 | ||
1225 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 2361 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
1226 | if (spec == NULL) | 2362 | if (spec == NULL) |
1227 | return -ENOMEM; | 2363 | return -ENOMEM; |
1228 | 2364 | ||
2365 | init_MUTEX(&spec->bind_mutex); | ||
1229 | codec->spec = spec; | 2366 | codec->spec = spec; |
1230 | 2367 | ||
1231 | spec->mixers[spec->num_mixers] = alc260_base_mixer; | 2368 | board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl); |
1232 | spec->num_mixers++; | 2369 | if (board_config < 0 || board_config >= ALC260_MODEL_LAST) { |
2370 | snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n"); | ||
2371 | board_config = ALC260_BASIC; | ||
2372 | } | ||
2373 | |||
2374 | switch (board_config) { | ||
2375 | case ALC260_HP: | ||
2376 | spec->mixers[spec->num_mixers] = alc260_hp_mixer; | ||
2377 | spec->num_mixers++; | ||
2378 | break; | ||
2379 | default: | ||
2380 | spec->mixers[spec->num_mixers] = alc260_base_mixer; | ||
2381 | spec->num_mixers++; | ||
2382 | break; | ||
2383 | } | ||
2384 | |||
2385 | spec->init_verbs[0] = alc260_init_verbs; | ||
2386 | spec->num_init_verbs = 1; | ||
1233 | 2387 | ||
1234 | spec->init_verbs = alc260_init_verbs; | ||
1235 | spec->channel_mode = alc260_modes; | 2388 | spec->channel_mode = alc260_modes; |
1236 | spec->num_channel_mode = ARRAY_SIZE(alc260_modes); | 2389 | spec->num_channel_mode = ARRAY_SIZE(alc260_modes); |
1237 | 2390 | ||
@@ -1244,14 +2397,23 @@ static int patch_alc260(struct hda_codec *codec) | |||
1244 | spec->multiout.dac_nids = alc260_dac_nids; | 2397 | spec->multiout.dac_nids = alc260_dac_nids; |
1245 | 2398 | ||
1246 | spec->input_mux = &alc260_capture_source; | 2399 | spec->input_mux = &alc260_capture_source; |
1247 | spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); | 2400 | switch (board_config) { |
1248 | spec->adc_nids = alc260_adc_nids; | 2401 | case ALC260_HP: |
2402 | spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids); | ||
2403 | spec->adc_nids = alc260_hp_adc_nids; | ||
2404 | break; | ||
2405 | default: | ||
2406 | spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids); | ||
2407 | spec->adc_nids = alc260_adc_nids; | ||
2408 | break; | ||
2409 | } | ||
1249 | 2410 | ||
1250 | codec->patch_ops = alc_patch_ops; | 2411 | codec->patch_ops = alc_patch_ops; |
1251 | 2412 | ||
1252 | return 0; | 2413 | return 0; |
1253 | } | 2414 | } |
1254 | 2415 | ||
2416 | |||
1255 | /* | 2417 | /* |
1256 | * ALC882 support | 2418 | * ALC882 support |
1257 | * | 2419 | * |
@@ -1324,15 +2486,15 @@ static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u | |||
1324 | */ | 2486 | */ |
1325 | static snd_kcontrol_new_t alc882_base_mixer[] = { | 2487 | static snd_kcontrol_new_t alc882_base_mixer[] = { |
1326 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 2488 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
1327 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 2489 | ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
1328 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 2490 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
1329 | HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), | 2491 | ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), |
1330 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | 2492 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), |
1331 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | 2493 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
1332 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT), | 2494 | ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), |
1333 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), | 2495 | ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_OUTPUT), |
1334 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | 2496 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), |
1335 | HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT), | 2497 | ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), |
1336 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 2498 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
1337 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 2499 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
1338 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 2500 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
@@ -1364,89 +2526,80 @@ static snd_kcontrol_new_t alc882_base_mixer[] = { | |||
1364 | 2526 | ||
1365 | static struct hda_verb alc882_init_verbs[] = { | 2527 | static struct hda_verb alc882_init_verbs[] = { |
1366 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ | 2528 | /* Front mixer: unmute input/output amp left and right (volume = 0) */ |
1367 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2529 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1368 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2530 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2531 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1369 | /* Rear mixer */ | 2532 | /* Rear mixer */ |
1370 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2533 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1371 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2534 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2535 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1372 | /* CLFE mixer */ | 2536 | /* CLFE mixer */ |
1373 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2537 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1374 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2538 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
2539 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
1375 | /* Side mixer */ | 2540 | /* Side mixer */ |
1376 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 2541 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, |
1377 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2542 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1378 | 2543 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | |
1379 | /* Front Pin: to output mode */ | 2544 | |
1380 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2545 | /* Front Pin: output 0 (0x0c) */ |
1381 | /* Front Pin: mute amp left and right (no volume) */ | 2546 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1382 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | 2547 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1383 | /* select Front mixer (0x0c, index 0) */ | ||
1384 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | 2548 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1385 | /* Rear Pin */ | 2549 | /* Rear Pin: output 1 (0x0d) */ |
1386 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2550 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1387 | /* Rear Pin: mute amp left and right (no volume) */ | 2551 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1388 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
1389 | /* select Rear mixer (0x0d, index 1) */ | ||
1390 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | 2552 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, |
1391 | /* CLFE Pin */ | 2553 | /* CLFE Pin: output 2 (0x0e) */ |
1392 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2554 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1393 | /* CLFE Pin: mute amp left and right (no volume) */ | 2555 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1394 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
1395 | /* select CLFE mixer (0x0e, index 2) */ | ||
1396 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, | 2556 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, |
1397 | /* Side Pin */ | 2557 | /* Side Pin: output 3 (0x0f) */ |
1398 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2558 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
1399 | /* Side Pin: mute amp left and right (no volume) */ | 2559 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1400 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | ||
1401 | /* select Side mixer (0x0f, index 3) */ | ||
1402 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, | 2560 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, |
1403 | /* Headphone Pin */ | 2561 | /* Mic (rear) pin: input vref at 80% */ |
1404 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 2562 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
1405 | /* Headphone Pin: mute amp left and right (no volume) */ | 2563 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
1406 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000}, | 2564 | /* Front Mic pin: input vref at 80% */ |
1407 | /* select Front mixer (0x0c, index 0) */ | 2565 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
2566 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2567 | /* Line In pin: input */ | ||
2568 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2569 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2570 | /* Line-2 In: Headphone output (output 0 - 0x0c) */ | ||
2571 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2572 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1408 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, | 2573 | {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1409 | /* Mic (rear) pin widget for input and vref at 80% */ | ||
1410 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
1411 | /* Front Mic pin widget for input and vref at 80% */ | ||
1412 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
1413 | /* Line In pin widget for input */ | ||
1414 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
1415 | /* CD pin widget for input */ | 2574 | /* CD pin widget for input */ |
1416 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 2575 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
1417 | 2576 | ||
1418 | /* FIXME: use matrix-type input source selection */ | 2577 | /* FIXME: use matrix-type input source selection */ |
1419 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ | 2578 | /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ |
1420 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | 2579 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ |
1421 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2580 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1422 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, | 2581 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
1423 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, | 2582 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
1424 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, | 2583 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
1425 | /* Input mixer2 */ | 2584 | /* Input mixer2 */ |
1426 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2585 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1427 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, | 2586 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
1428 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, | 2587 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
1429 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, | 2588 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
1430 | /* Input mixer3 */ | 2589 | /* Input mixer3 */ |
1431 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | 2590 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1432 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))}, | 2591 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, |
1433 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))}, | 2592 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, |
1434 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, | 2593 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, |
1435 | /* ADC1: unmute amp left and right */ | 2594 | /* ADC1: mute amp left and right */ |
1436 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 2595 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1437 | /* ADC2: unmute amp left and right */ | 2596 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1438 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 2597 | /* ADC2: mute amp left and right */ |
1439 | /* ADC3: unmute amp left and right */ | 2598 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1440 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 2599 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1441 | 2600 | /* ADC3: mute amp left and right */ | |
1442 | /* Unmute front loopback */ | 2601 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
1443 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 2602 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, |
1444 | /* Unmute rear loopback */ | ||
1445 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
1446 | /* Mute CLFE loopback */ | ||
1447 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, | ||
1448 | /* Unmute side loopback */ | ||
1449 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
1450 | 2603 | ||
1451 | { } | 2604 | { } |
1452 | }; | 2605 | }; |
@@ -1459,6 +2612,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
1459 | if (spec == NULL) | 2612 | if (spec == NULL) |
1460 | return -ENOMEM; | 2613 | return -ENOMEM; |
1461 | 2614 | ||
2615 | init_MUTEX(&spec->bind_mutex); | ||
1462 | codec->spec = spec; | 2616 | codec->spec = spec; |
1463 | 2617 | ||
1464 | spec->mixers[spec->num_mixers] = alc882_base_mixer; | 2618 | spec->mixers[spec->num_mixers] = alc882_base_mixer; |
@@ -1466,8 +2620,9 @@ static int patch_alc882(struct hda_codec *codec) | |||
1466 | 2620 | ||
1467 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 2621 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; |
1468 | spec->dig_in_nid = ALC880_DIGIN_NID; | 2622 | spec->dig_in_nid = ALC880_DIGIN_NID; |
1469 | spec->front_panel = 1; | 2623 | spec->init_verbs[0] = alc882_init_verbs; |
1470 | spec->init_verbs = alc882_init_verbs; | 2624 | spec->num_init_verbs = 1; |
2625 | |||
1471 | spec->channel_mode = alc882_ch_modes; | 2626 | spec->channel_mode = alc882_ch_modes; |
1472 | spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes); | 2627 | spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes); |
1473 | 2628 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c new file mode 100644 index 000000000000..9d503da7320d --- /dev/null +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -0,0 +1,1004 @@ | |||
1 | /* | ||
2 | * Universal Interface for Intel High Definition Audio Codec | ||
3 | * | ||
4 | * HD audio interface patch for SigmaTel STAC92xx | ||
5 | * | ||
6 | * Copyright (c) 2005 Embedded Alley Solutions, Inc. | ||
7 | * <matt@embeddedalley.com> | ||
8 | * | ||
9 | * Based on patch_cmedia.c and patch_realtek.c | ||
10 | * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de> | ||
11 | * | ||
12 | * This driver is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This driver is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | #include <sound/driver.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <sound/core.h> | ||
33 | #include <sound/asoundef.h> | ||
34 | #include "hda_codec.h" | ||
35 | #include "hda_local.h" | ||
36 | |||
37 | #undef STAC_TEST | ||
38 | |||
39 | #define NUM_CONTROL_ALLOC 32 | ||
40 | #define STAC_HP_EVENT 0x37 | ||
41 | #define STAC_UNSOL_ENABLE (AC_USRSP_EN | STAC_HP_EVENT) | ||
42 | |||
43 | struct sigmatel_spec { | ||
44 | snd_kcontrol_new_t *mixers[4]; | ||
45 | unsigned int num_mixers; | ||
46 | |||
47 | unsigned int surr_switch: 1; | ||
48 | |||
49 | /* playback */ | ||
50 | struct hda_multi_out multiout; | ||
51 | hda_nid_t dac_nids[4]; | ||
52 | |||
53 | /* capture */ | ||
54 | hda_nid_t *adc_nids; | ||
55 | unsigned int num_adcs; | ||
56 | hda_nid_t *mux_nids; | ||
57 | unsigned int num_muxes; | ||
58 | hda_nid_t dig_in_nid; | ||
59 | |||
60 | #ifdef STAC_TEST | ||
61 | /* pin widgets */ | ||
62 | hda_nid_t *pin_nids; | ||
63 | unsigned int num_pins; | ||
64 | unsigned int *pin_configs; | ||
65 | #endif | ||
66 | |||
67 | /* codec specific stuff */ | ||
68 | struct hda_verb *init; | ||
69 | snd_kcontrol_new_t *mixer; | ||
70 | |||
71 | /* capture source */ | ||
72 | struct hda_input_mux *input_mux; | ||
73 | unsigned int cur_mux[2]; | ||
74 | |||
75 | /* channel mode */ | ||
76 | unsigned int num_ch_modes; | ||
77 | unsigned int cur_ch_mode; | ||
78 | |||
79 | struct hda_pcm pcm_rec[2]; /* PCM information */ | ||
80 | |||
81 | /* dynamic controls and input_mux */ | ||
82 | struct auto_pin_cfg autocfg; | ||
83 | unsigned int num_kctl_alloc, num_kctl_used; | ||
84 | snd_kcontrol_new_t *kctl_alloc; | ||
85 | struct hda_input_mux private_imux; | ||
86 | }; | ||
87 | |||
88 | static hda_nid_t stac9200_adc_nids[1] = { | ||
89 | 0x03, | ||
90 | }; | ||
91 | |||
92 | static hda_nid_t stac9200_mux_nids[1] = { | ||
93 | 0x0c, | ||
94 | }; | ||
95 | |||
96 | static hda_nid_t stac9200_dac_nids[1] = { | ||
97 | 0x02, | ||
98 | }; | ||
99 | |||
100 | static hda_nid_t stac922x_adc_nids[2] = { | ||
101 | 0x06, 0x07, | ||
102 | }; | ||
103 | |||
104 | static hda_nid_t stac922x_mux_nids[2] = { | ||
105 | 0x12, 0x13, | ||
106 | }; | ||
107 | |||
108 | #ifdef STAC_TEST | ||
109 | static hda_nid_t stac9200_pin_nids[8] = { | ||
110 | 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, | ||
111 | }; | ||
112 | |||
113 | static hda_nid_t stac922x_pin_nids[10] = { | ||
114 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
115 | 0x0f, 0x10, 0x11, 0x15, 0x1b, | ||
116 | }; | ||
117 | #endif | ||
118 | |||
119 | static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
120 | { | ||
121 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
122 | struct sigmatel_spec *spec = codec->spec; | ||
123 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | ||
124 | } | ||
125 | |||
126 | static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
127 | { | ||
128 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
129 | struct sigmatel_spec *spec = codec->spec; | ||
130 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
131 | |||
132 | ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
137 | { | ||
138 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
139 | struct sigmatel_spec *spec = codec->spec; | ||
140 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
141 | |||
142 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
143 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); | ||
144 | } | ||
145 | |||
146 | static struct hda_verb stac9200_core_init[] = { | ||
147 | /* set dac0mux for dac converter */ | ||
148 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
149 | {} | ||
150 | }; | ||
151 | |||
152 | static struct hda_verb stac922x_core_init[] = { | ||
153 | /* set master volume and direct control */ | ||
154 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | ||
155 | {} | ||
156 | }; | ||
157 | |||
158 | static int stac922x_channel_modes[3] = {2, 6, 8}; | ||
159 | |||
160 | static int stac922x_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
161 | { | ||
162 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
163 | struct sigmatel_spec *spec = codec->spec; | ||
164 | |||
165 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
166 | uinfo->count = 1; | ||
167 | uinfo->value.enumerated.items = spec->num_ch_modes; | ||
168 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
169 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
170 | sprintf(uinfo->value.enumerated.name, "%dch", | ||
171 | stac922x_channel_modes[uinfo->value.enumerated.item]); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int stac922x_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
176 | { | ||
177 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
178 | struct sigmatel_spec *spec = codec->spec; | ||
179 | |||
180 | ucontrol->value.enumerated.item[0] = spec->cur_ch_mode; | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int stac922x_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
185 | { | ||
186 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
187 | struct sigmatel_spec *spec = codec->spec; | ||
188 | |||
189 | if (ucontrol->value.enumerated.item[0] >= spec->num_ch_modes) | ||
190 | ucontrol->value.enumerated.item[0] = spec->num_ch_modes; | ||
191 | if (ucontrol->value.enumerated.item[0] == spec->cur_ch_mode && | ||
192 | ! codec->in_resume) | ||
193 | return 0; | ||
194 | |||
195 | spec->cur_ch_mode = ucontrol->value.enumerated.item[0]; | ||
196 | spec->multiout.max_channels = stac922x_channel_modes[spec->cur_ch_mode]; | ||
197 | |||
198 | return 1; | ||
199 | } | ||
200 | |||
201 | static snd_kcontrol_new_t stac9200_mixer[] = { | ||
202 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | ||
203 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | ||
204 | { | ||
205 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
206 | .name = "Input Source", | ||
207 | .count = 1, | ||
208 | .info = stac92xx_mux_enum_info, | ||
209 | .get = stac92xx_mux_enum_get, | ||
210 | .put = stac92xx_mux_enum_put, | ||
211 | }, | ||
212 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | ||
213 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | ||
214 | HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT), | ||
215 | { } /* end */ | ||
216 | }; | ||
217 | |||
218 | /* This needs to be generated dynamically based on sequence */ | ||
219 | static snd_kcontrol_new_t stac922x_mixer[] = { | ||
220 | { | ||
221 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
222 | .name = "Input Source", | ||
223 | .count = 1, | ||
224 | .info = stac92xx_mux_enum_info, | ||
225 | .get = stac92xx_mux_enum_get, | ||
226 | .put = stac92xx_mux_enum_put, | ||
227 | }, | ||
228 | HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), | ||
229 | HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT), | ||
230 | HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), | ||
231 | { } /* end */ | ||
232 | }; | ||
233 | |||
234 | static snd_kcontrol_new_t stac922x_ch_mode_mixer[] = { | ||
235 | { | ||
236 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
237 | .name = "Channel Mode", | ||
238 | .info = stac922x_ch_mode_info, | ||
239 | .get = stac922x_ch_mode_get, | ||
240 | .put = stac922x_ch_mode_put, | ||
241 | }, | ||
242 | { } /* end */ | ||
243 | }; | ||
244 | |||
245 | static int stac92xx_build_controls(struct hda_codec *codec) | ||
246 | { | ||
247 | struct sigmatel_spec *spec = codec->spec; | ||
248 | int err; | ||
249 | int i; | ||
250 | |||
251 | err = snd_hda_add_new_ctls(codec, spec->mixer); | ||
252 | if (err < 0) | ||
253 | return err; | ||
254 | |||
255 | for (i = 0; i < spec->num_mixers; i++) { | ||
256 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | ||
257 | if (err < 0) | ||
258 | return err; | ||
259 | } | ||
260 | |||
261 | if (spec->surr_switch) { | ||
262 | err = snd_hda_add_new_ctls(codec, stac922x_ch_mode_mixer); | ||
263 | if (err < 0) | ||
264 | return err; | ||
265 | } | ||
266 | if (spec->multiout.dig_out_nid) { | ||
267 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | ||
268 | if (err < 0) | ||
269 | return err; | ||
270 | } | ||
271 | if (spec->dig_in_nid) { | ||
272 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); | ||
273 | if (err < 0) | ||
274 | return err; | ||
275 | } | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | #ifdef STAC_TEST | ||
280 | static unsigned int stac9200_pin_configs[8] = { | ||
281 | 0x01c47010, 0x01447010, 0x0221401f, 0x01114010, | ||
282 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, | ||
283 | }; | ||
284 | |||
285 | static unsigned int stac922x_pin_configs[10] = { | ||
286 | 0x01014010, 0x01014011, 0x01014012, 0x0221401f, | ||
287 | 0x01813122, 0x01014014, 0x01441030, 0x01c41030, | ||
288 | 0x40000100, 0x40000100, | ||
289 | }; | ||
290 | |||
291 | static void stac92xx_set_config_regs(struct hda_codec *codec) | ||
292 | { | ||
293 | int i; | ||
294 | struct sigmatel_spec *spec = codec->spec; | ||
295 | unsigned int pin_cfg; | ||
296 | |||
297 | for (i=0; i < spec->num_pins; i++) { | ||
298 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | ||
299 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | ||
300 | spec->pin_configs[i] & 0x000000ff); | ||
301 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | ||
302 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, | ||
303 | (spec->pin_configs[i] & 0x0000ff00) >> 8); | ||
304 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | ||
305 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, | ||
306 | (spec->pin_configs[i] & 0x00ff0000) >> 16); | ||
307 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | ||
308 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | ||
309 | spec->pin_configs[i] >> 24); | ||
310 | pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0, | ||
311 | AC_VERB_GET_CONFIG_DEFAULT, | ||
312 | 0x00); | ||
313 | printk("pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg); | ||
314 | } | ||
315 | } | ||
316 | #endif | ||
317 | |||
318 | /* | ||
319 | * Analog playback callbacks | ||
320 | */ | ||
321 | static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
322 | struct hda_codec *codec, | ||
323 | snd_pcm_substream_t *substream) | ||
324 | { | ||
325 | struct sigmatel_spec *spec = codec->spec; | ||
326 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * set up the i/o for analog out | ||
331 | * when the digital out is available, copy the front out to digital out, too. | ||
332 | */ | ||
333 | static int stac92xx_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, | ||
334 | unsigned int stream_tag, | ||
335 | unsigned int format, | ||
336 | snd_pcm_substream_t *substream) | ||
337 | { | ||
338 | hda_nid_t *nids = mout->dac_nids; | ||
339 | int chs = substream->runtime->channels; | ||
340 | int i; | ||
341 | |||
342 | down(&codec->spdif_mutex); | ||
343 | if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { | ||
344 | if (chs == 2 && | ||
345 | snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && | ||
346 | ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) { | ||
347 | mout->dig_out_used = HDA_DIG_ANALOG_DUP; | ||
348 | /* setup digital receiver */ | ||
349 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, | ||
350 | stream_tag, 0, format); | ||
351 | } else { | ||
352 | mout->dig_out_used = 0; | ||
353 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); | ||
354 | } | ||
355 | } | ||
356 | up(&codec->spdif_mutex); | ||
357 | |||
358 | /* front */ | ||
359 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); | ||
360 | if (mout->hp_nid) | ||
361 | /* headphone out will just decode front left/right (stereo) */ | ||
362 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); | ||
363 | /* surrounds */ | ||
364 | if (mout->max_channels > 2) | ||
365 | for (i = 1; i < mout->num_dacs; i++) { | ||
366 | if ((mout->max_channels == 6) && (i == 3)) | ||
367 | break; | ||
368 | if (chs >= (i + 1) * 2) /* independent out */ | ||
369 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, | ||
370 | format); | ||
371 | else /* copy front */ | ||
372 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, | ||
373 | format); | ||
374 | } | ||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | |||
379 | static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
380 | struct hda_codec *codec, | ||
381 | unsigned int stream_tag, | ||
382 | unsigned int format, | ||
383 | snd_pcm_substream_t *substream) | ||
384 | { | ||
385 | struct sigmatel_spec *spec = codec->spec; | ||
386 | return stac92xx_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | ||
387 | format, substream); | ||
388 | } | ||
389 | |||
390 | static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
391 | struct hda_codec *codec, | ||
392 | snd_pcm_substream_t *substream) | ||
393 | { | ||
394 | struct sigmatel_spec *spec = codec->spec; | ||
395 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
396 | } | ||
397 | |||
398 | /* | ||
399 | * Digital playback callbacks | ||
400 | */ | ||
401 | static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
402 | struct hda_codec *codec, | ||
403 | snd_pcm_substream_t *substream) | ||
404 | { | ||
405 | struct sigmatel_spec *spec = codec->spec; | ||
406 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
407 | } | ||
408 | |||
409 | static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
410 | struct hda_codec *codec, | ||
411 | snd_pcm_substream_t *substream) | ||
412 | { | ||
413 | struct sigmatel_spec *spec = codec->spec; | ||
414 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
415 | } | ||
416 | |||
417 | |||
418 | /* | ||
419 | * Analog capture callbacks | ||
420 | */ | ||
421 | static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
422 | struct hda_codec *codec, | ||
423 | unsigned int stream_tag, | ||
424 | unsigned int format, | ||
425 | snd_pcm_substream_t *substream) | ||
426 | { | ||
427 | struct sigmatel_spec *spec = codec->spec; | ||
428 | |||
429 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | ||
430 | stream_tag, 0, format); | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
435 | struct hda_codec *codec, | ||
436 | snd_pcm_substream_t *substream) | ||
437 | { | ||
438 | struct sigmatel_spec *spec = codec->spec; | ||
439 | |||
440 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0); | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static struct hda_pcm_stream stac92xx_pcm_digital_playback = { | ||
445 | .substreams = 1, | ||
446 | .channels_min = 2, | ||
447 | .channels_max = 2, | ||
448 | /* NID is set in stac92xx_build_pcms */ | ||
449 | .ops = { | ||
450 | .open = stac92xx_dig_playback_pcm_open, | ||
451 | .close = stac92xx_dig_playback_pcm_close | ||
452 | }, | ||
453 | }; | ||
454 | |||
455 | static struct hda_pcm_stream stac92xx_pcm_digital_capture = { | ||
456 | .substreams = 1, | ||
457 | .channels_min = 2, | ||
458 | .channels_max = 2, | ||
459 | /* NID is set in stac92xx_build_pcms */ | ||
460 | }; | ||
461 | |||
462 | static struct hda_pcm_stream stac92xx_pcm_analog_playback = { | ||
463 | .substreams = 1, | ||
464 | .channels_min = 2, | ||
465 | .channels_max = 8, | ||
466 | .nid = 0x02, /* NID to query formats and rates */ | ||
467 | .ops = { | ||
468 | .open = stac92xx_playback_pcm_open, | ||
469 | .prepare = stac92xx_playback_pcm_prepare, | ||
470 | .cleanup = stac92xx_playback_pcm_cleanup | ||
471 | }, | ||
472 | }; | ||
473 | |||
474 | static struct hda_pcm_stream stac92xx_pcm_analog_capture = { | ||
475 | .substreams = 2, | ||
476 | .channels_min = 2, | ||
477 | .channels_max = 2, | ||
478 | .nid = 0x06, /* NID to query formats and rates */ | ||
479 | .ops = { | ||
480 | .prepare = stac92xx_capture_pcm_prepare, | ||
481 | .cleanup = stac92xx_capture_pcm_cleanup | ||
482 | }, | ||
483 | }; | ||
484 | |||
485 | static int stac92xx_build_pcms(struct hda_codec *codec) | ||
486 | { | ||
487 | struct sigmatel_spec *spec = codec->spec; | ||
488 | struct hda_pcm *info = spec->pcm_rec; | ||
489 | |||
490 | codec->num_pcms = 1; | ||
491 | codec->pcm_info = info; | ||
492 | |||
493 | info->name = "STAC92xx Analog"; | ||
494 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; | ||
495 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; | ||
496 | |||
497 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | ||
498 | codec->num_pcms++; | ||
499 | info++; | ||
500 | info->name = "STAC92xx Digital"; | ||
501 | if (spec->multiout.dig_out_nid) { | ||
502 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback; | ||
503 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; | ||
504 | } | ||
505 | if (spec->dig_in_nid) { | ||
506 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_digital_capture; | ||
507 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | enum { | ||
515 | STAC_CTL_WIDGET_VOL, | ||
516 | STAC_CTL_WIDGET_MUTE, | ||
517 | }; | ||
518 | |||
519 | static snd_kcontrol_new_t stac92xx_control_templates[] = { | ||
520 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | ||
521 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | ||
522 | }; | ||
523 | |||
524 | /* add dynamic controls */ | ||
525 | static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char *name, unsigned long val) | ||
526 | { | ||
527 | snd_kcontrol_new_t *knew; | ||
528 | |||
529 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | ||
530 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | ||
531 | |||
532 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | ||
533 | if (! knew) | ||
534 | return -ENOMEM; | ||
535 | if (spec->kctl_alloc) { | ||
536 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
537 | kfree(spec->kctl_alloc); | ||
538 | } | ||
539 | spec->kctl_alloc = knew; | ||
540 | spec->num_kctl_alloc = num; | ||
541 | } | ||
542 | |||
543 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
544 | *knew = stac92xx_control_templates[type]; | ||
545 | knew->name = kstrdup(name, GFP_KERNEL); | ||
546 | if (! knew->name) | ||
547 | return -ENOMEM; | ||
548 | knew->private_value = val; | ||
549 | spec->num_kctl_used++; | ||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | /* fill in the dac_nids table from the parsed pin configuration */ | ||
554 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) | ||
555 | { | ||
556 | struct sigmatel_spec *spec = codec->spec; | ||
557 | hda_nid_t nid; | ||
558 | int i; | ||
559 | |||
560 | /* check the pins hardwired to audio widget */ | ||
561 | for (i = 0; i < cfg->line_outs; i++) { | ||
562 | nid = cfg->line_out_pins[i]; | ||
563 | spec->multiout.dac_nids[i] = snd_hda_codec_read(codec, nid, 0, | ||
564 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
565 | } | ||
566 | |||
567 | spec->multiout.num_dacs = cfg->line_outs; | ||
568 | |||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | /* add playback controls from the parsed DAC table */ | ||
573 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, const struct auto_pin_cfg *cfg) | ||
574 | { | ||
575 | char name[32]; | ||
576 | static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; | ||
577 | hda_nid_t nid; | ||
578 | int i, err; | ||
579 | |||
580 | for (i = 0; i < cfg->line_outs; i++) { | ||
581 | if (! spec->multiout.dac_nids[i]) | ||
582 | continue; | ||
583 | |||
584 | nid = spec->multiout.dac_nids[i]; | ||
585 | |||
586 | if (i == 2) { | ||
587 | /* Center/LFE */ | ||
588 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Center Playback Volume", | ||
589 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | ||
590 | return err; | ||
591 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "LFE Playback Volume", | ||
592 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | ||
593 | return err; | ||
594 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Center Playback Switch", | ||
595 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | ||
596 | return err; | ||
597 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "LFE Playback Switch", | ||
598 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | ||
599 | return err; | ||
600 | } else { | ||
601 | sprintf(name, "%s Playback Volume", chname[i]); | ||
602 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | ||
603 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
604 | return err; | ||
605 | sprintf(name, "%s Playback Switch", chname[i]); | ||
606 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | ||
607 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
608 | return err; | ||
609 | } | ||
610 | } | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | /* add playback controls for HP output */ | ||
616 | static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin_cfg *cfg) | ||
617 | { | ||
618 | struct sigmatel_spec *spec = codec->spec; | ||
619 | hda_nid_t pin = cfg->hp_pin; | ||
620 | hda_nid_t nid; | ||
621 | int i, err; | ||
622 | unsigned int wid_caps; | ||
623 | |||
624 | if (! pin) | ||
625 | return 0; | ||
626 | |||
627 | wid_caps = snd_hda_param_read(codec, pin, AC_PAR_AUDIO_WIDGET_CAP); | ||
628 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
629 | /* Enable unsolicited responses on the HP widget */ | ||
630 | snd_hda_codec_write(codec, pin, 0, | ||
631 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
632 | STAC_UNSOL_ENABLE); | ||
633 | |||
634 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
635 | for (i = 0; i < cfg->line_outs; i++) { | ||
636 | if (! spec->multiout.dac_nids[i]) | ||
637 | continue; | ||
638 | if (spec->multiout.dac_nids[i] == nid) | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | spec->multiout.hp_nid = nid; | ||
643 | |||
644 | /* control HP volume/switch on the output mixer amp */ | ||
645 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Headphone Playback Volume", | ||
646 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
647 | return err; | ||
648 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | ||
649 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
650 | return err; | ||
651 | |||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | /* create playback/capture controls for input pins */ | ||
656 | static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) | ||
657 | { | ||
658 | struct sigmatel_spec *spec = codec->spec; | ||
659 | static char *labels[AUTO_PIN_LAST] = { | ||
660 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" | ||
661 | }; | ||
662 | struct hda_input_mux *imux = &spec->private_imux; | ||
663 | hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; | ||
664 | int i, j, k; | ||
665 | |||
666 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
667 | int index = -1; | ||
668 | if (cfg->input_pins[i]) { | ||
669 | imux->items[imux->num_items].label = labels[i]; | ||
670 | |||
671 | for (j=0; j<spec->num_muxes; j++) { | ||
672 | int num_cons = snd_hda_get_connections(codec, spec->mux_nids[j], con_lst, HDA_MAX_NUM_INPUTS); | ||
673 | for (k=0; k<num_cons; k++) | ||
674 | if (con_lst[k] == cfg->input_pins[i]) { | ||
675 | index = k; | ||
676 | break; | ||
677 | } | ||
678 | if (index >= 0) | ||
679 | break; | ||
680 | } | ||
681 | imux->items[imux->num_items].index = index; | ||
682 | imux->num_items++; | ||
683 | } | ||
684 | } | ||
685 | |||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) | ||
690 | |||
691 | { | ||
692 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | ||
693 | } | ||
694 | |||
695 | static void stac92xx_auto_init_multi_out(struct hda_codec *codec) | ||
696 | { | ||
697 | struct sigmatel_spec *spec = codec->spec; | ||
698 | int i; | ||
699 | |||
700 | for (i = 0; i < spec->autocfg.line_outs; i++) { | ||
701 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
702 | stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | ||
703 | } | ||
704 | } | ||
705 | |||
706 | static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | ||
707 | { | ||
708 | struct sigmatel_spec *spec = codec->spec; | ||
709 | hda_nid_t pin; | ||
710 | |||
711 | pin = spec->autocfg.hp_pin; | ||
712 | if (pin) /* connect to front */ | ||
713 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | ||
714 | } | ||
715 | |||
716 | static int stac922x_parse_auto_config(struct hda_codec *codec) | ||
717 | { | ||
718 | struct sigmatel_spec *spec = codec->spec; | ||
719 | int err; | ||
720 | |||
721 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0) | ||
722 | return err; | ||
723 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | ||
724 | return err; | ||
725 | if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) | ||
726 | return 0; /* can't find valid pin config */ | ||
727 | |||
728 | if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | ||
729 | (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 || | ||
730 | (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | ||
731 | return err; | ||
732 | |||
733 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | ||
734 | if (spec->multiout.max_channels > 2) { | ||
735 | spec->surr_switch = 1; | ||
736 | spec->cur_ch_mode = 1; | ||
737 | spec->num_ch_modes = 2; | ||
738 | if (spec->multiout.max_channels == 8) { | ||
739 | spec->cur_ch_mode++; | ||
740 | spec->num_ch_modes++; | ||
741 | } | ||
742 | } | ||
743 | |||
744 | if (spec->autocfg.dig_out_pin) { | ||
745 | spec->multiout.dig_out_nid = 0x08; | ||
746 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); | ||
747 | } | ||
748 | if (spec->autocfg.dig_in_pin) { | ||
749 | spec->dig_in_nid = 0x09; | ||
750 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); | ||
751 | } | ||
752 | |||
753 | if (spec->kctl_alloc) | ||
754 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | ||
755 | |||
756 | spec->input_mux = &spec->private_imux; | ||
757 | |||
758 | return 1; | ||
759 | } | ||
760 | |||
761 | static int stac9200_parse_auto_config(struct hda_codec *codec) | ||
762 | { | ||
763 | struct sigmatel_spec *spec = codec->spec; | ||
764 | int err; | ||
765 | |||
766 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0) | ||
767 | return err; | ||
768 | |||
769 | if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | ||
770 | return err; | ||
771 | |||
772 | if (spec->autocfg.dig_out_pin) { | ||
773 | spec->multiout.dig_out_nid = 0x05; | ||
774 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); | ||
775 | } | ||
776 | if (spec->autocfg.dig_in_pin) { | ||
777 | spec->dig_in_nid = 0x04; | ||
778 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); | ||
779 | } | ||
780 | |||
781 | if (spec->kctl_alloc) | ||
782 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | ||
783 | |||
784 | spec->input_mux = &spec->private_imux; | ||
785 | |||
786 | return 1; | ||
787 | } | ||
788 | |||
789 | static int stac92xx_init_pstate(struct hda_codec *codec) | ||
790 | { | ||
791 | hda_nid_t nid, nid_start; | ||
792 | int nodes; | ||
793 | |||
794 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_POWER_STATE, 0x00); | ||
795 | |||
796 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); | ||
797 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | ||
798 | unsigned int wid_caps = snd_hda_param_read(codec, nid, | ||
799 | AC_PAR_AUDIO_WIDGET_CAP); | ||
800 | if (wid_caps & AC_WCAP_POWER) | ||
801 | snd_hda_codec_write(codec, nid, 0, | ||
802 | AC_VERB_SET_POWER_STATE, 0x00); | ||
803 | } | ||
804 | |||
805 | mdelay(100); | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static int stac92xx_init(struct hda_codec *codec) | ||
811 | { | ||
812 | struct sigmatel_spec *spec = codec->spec; | ||
813 | |||
814 | stac92xx_init_pstate(codec); | ||
815 | |||
816 | snd_hda_sequence_write(codec, spec->init); | ||
817 | |||
818 | stac92xx_auto_init_multi_out(codec); | ||
819 | stac92xx_auto_init_hp_out(codec); | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | static void stac92xx_free(struct hda_codec *codec) | ||
825 | { | ||
826 | struct sigmatel_spec *spec = codec->spec; | ||
827 | int i; | ||
828 | |||
829 | if (! spec) | ||
830 | return; | ||
831 | |||
832 | if (spec->kctl_alloc) { | ||
833 | for (i = 0; i < spec->num_kctl_used; i++) | ||
834 | kfree(spec->kctl_alloc[i].name); | ||
835 | kfree(spec->kctl_alloc); | ||
836 | } | ||
837 | |||
838 | kfree(spec); | ||
839 | } | ||
840 | |||
841 | static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | ||
842 | unsigned int flag) | ||
843 | { | ||
844 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | ||
845 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | ||
846 | snd_hda_codec_write(codec, nid, 0, | ||
847 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
848 | pin_ctl | flag); | ||
849 | } | ||
850 | |||
851 | static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | ||
852 | unsigned int flag) | ||
853 | { | ||
854 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | ||
855 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | ||
856 | snd_hda_codec_write(codec, nid, 0, | ||
857 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
858 | pin_ctl & ~flag); | ||
859 | } | ||
860 | |||
861 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
862 | { | ||
863 | struct sigmatel_spec *spec = codec->spec; | ||
864 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
865 | int i, presence; | ||
866 | |||
867 | if ((res >> 26) != STAC_HP_EVENT) | ||
868 | return; | ||
869 | |||
870 | presence = snd_hda_codec_read(codec, cfg->hp_pin, 0, | ||
871 | AC_VERB_GET_PIN_SENSE, 0x00) >> 31; | ||
872 | |||
873 | if (presence) { | ||
874 | /* disable lineouts, enable hp */ | ||
875 | for (i = 0; i < cfg->line_outs; i++) | ||
876 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], | ||
877 | AC_PINCTL_OUT_EN); | ||
878 | stac92xx_set_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | ||
879 | } else { | ||
880 | /* enable lineouts, disable hp */ | ||
881 | for (i = 0; i < cfg->line_outs; i++) | ||
882 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], | ||
883 | AC_PINCTL_OUT_EN); | ||
884 | stac92xx_reset_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | ||
885 | } | ||
886 | } | ||
887 | |||
888 | #ifdef CONFIG_PM | ||
889 | static int stac92xx_resume(struct hda_codec *codec) | ||
890 | { | ||
891 | struct sigmatel_spec *spec = codec->spec; | ||
892 | int i; | ||
893 | |||
894 | stac92xx_init(codec); | ||
895 | for (i = 0; i < spec->num_mixers; i++) | ||
896 | snd_hda_resume_ctls(codec, spec->mixers[i]); | ||
897 | if (spec->multiout.dig_out_nid) | ||
898 | snd_hda_resume_spdif_out(codec); | ||
899 | if (spec->dig_in_nid) | ||
900 | snd_hda_resume_spdif_in(codec); | ||
901 | |||
902 | return 0; | ||
903 | } | ||
904 | #endif | ||
905 | |||
906 | static struct hda_codec_ops stac92xx_patch_ops = { | ||
907 | .build_controls = stac92xx_build_controls, | ||
908 | .build_pcms = stac92xx_build_pcms, | ||
909 | .init = stac92xx_init, | ||
910 | .free = stac92xx_free, | ||
911 | .unsol_event = stac92xx_unsol_event, | ||
912 | #ifdef CONFIG_PM | ||
913 | .resume = stac92xx_resume, | ||
914 | #endif | ||
915 | }; | ||
916 | |||
917 | static int patch_stac9200(struct hda_codec *codec) | ||
918 | { | ||
919 | struct sigmatel_spec *spec; | ||
920 | int err; | ||
921 | |||
922 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | ||
923 | if (spec == NULL) | ||
924 | return -ENOMEM; | ||
925 | |||
926 | codec->spec = spec; | ||
927 | |||
928 | #ifdef STAC_TEST | ||
929 | spec->pin_nids = stac9200_pin_nids; | ||
930 | spec->num_pins = 8; | ||
931 | spec->pin_configs = stac9200_pin_configs; | ||
932 | stac92xx_set_config_regs(codec); | ||
933 | #endif | ||
934 | spec->multiout.max_channels = 2; | ||
935 | spec->multiout.num_dacs = 1; | ||
936 | spec->multiout.dac_nids = stac9200_dac_nids; | ||
937 | spec->adc_nids = stac9200_adc_nids; | ||
938 | spec->mux_nids = stac9200_mux_nids; | ||
939 | spec->num_muxes = 1; | ||
940 | |||
941 | spec->init = stac9200_core_init; | ||
942 | spec->mixer = stac9200_mixer; | ||
943 | |||
944 | err = stac9200_parse_auto_config(codec); | ||
945 | if (err < 0) { | ||
946 | stac92xx_free(codec); | ||
947 | return err; | ||
948 | } | ||
949 | |||
950 | codec->patch_ops = stac92xx_patch_ops; | ||
951 | |||
952 | return 0; | ||
953 | } | ||
954 | |||
955 | static int patch_stac922x(struct hda_codec *codec) | ||
956 | { | ||
957 | struct sigmatel_spec *spec; | ||
958 | int err; | ||
959 | |||
960 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | ||
961 | if (spec == NULL) | ||
962 | return -ENOMEM; | ||
963 | |||
964 | codec->spec = spec; | ||
965 | |||
966 | #ifdef STAC_TEST | ||
967 | spec->num_pins = 10; | ||
968 | spec->pin_nids = stac922x_pin_nids; | ||
969 | spec->pin_configs = stac922x_pin_configs; | ||
970 | stac92xx_set_config_regs(codec); | ||
971 | #endif | ||
972 | spec->adc_nids = stac922x_adc_nids; | ||
973 | spec->mux_nids = stac922x_mux_nids; | ||
974 | spec->num_muxes = 2; | ||
975 | |||
976 | spec->init = stac922x_core_init; | ||
977 | spec->mixer = stac922x_mixer; | ||
978 | |||
979 | spec->multiout.dac_nids = spec->dac_nids; | ||
980 | |||
981 | err = stac922x_parse_auto_config(codec); | ||
982 | if (err < 0) { | ||
983 | stac92xx_free(codec); | ||
984 | return err; | ||
985 | } | ||
986 | |||
987 | codec->patch_ops = stac92xx_patch_ops; | ||
988 | |||
989 | return 0; | ||
990 | } | ||
991 | |||
992 | /* | ||
993 | * patch entries | ||
994 | */ | ||
995 | struct hda_codec_preset snd_hda_preset_sigmatel[] = { | ||
996 | { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 }, | ||
997 | { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x }, | ||
998 | { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x }, | ||
999 | { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x }, | ||
1000 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, | ||
1001 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, | ||
1002 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, | ||
1003 | {} /* terminator */ | ||
1004 | }; | ||
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c index 779951725e1e..289b0b5711e4 100644 --- a/sound/pci/ice1712/amp.c +++ b/sound/pci/ice1712/amp.c | |||
@@ -30,16 +30,39 @@ | |||
30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
31 | 31 | ||
32 | #include "ice1712.h" | 32 | #include "ice1712.h" |
33 | #include "envy24ht.h" | ||
33 | #include "amp.h" | 34 | #include "amp.h" |
34 | 35 | ||
36 | static void wm_put(ice1712_t *ice, int reg, unsigned short val) | ||
37 | { | ||
38 | unsigned short cval; | ||
39 | cval = (reg << 9) | val; | ||
40 | snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff); | ||
41 | } | ||
35 | 42 | ||
36 | static int __devinit snd_vt1724_amp_init(ice1712_t *ice) | 43 | static int __devinit snd_vt1724_amp_init(ice1712_t *ice) |
37 | { | 44 | { |
45 | static unsigned short wm_inits[] = { | ||
46 | WM_ATTEN_L, 0x0000, /* 0 db */ | ||
47 | WM_ATTEN_R, 0x0000, /* 0 db */ | ||
48 | WM_DAC_CTRL, 0x0008, /* 24bit I2S */ | ||
49 | WM_INT_CTRL, 0x0001, /* 24bit I2S */ | ||
50 | }; | ||
51 | |||
52 | unsigned int i; | ||
53 | |||
38 | /* only use basic functionality for now */ | 54 | /* only use basic functionality for now */ |
39 | 55 | ||
40 | ice->num_total_dacs = 2; /* only PSDOUT0 is connected */ | 56 | ice->num_total_dacs = 2; /* only PSDOUT0 is connected */ |
41 | ice->num_total_adcs = 2; | 57 | ice->num_total_adcs = 2; |
42 | 58 | ||
59 | /* Chaintech AV-710 has another codecs, which need initialization */ | ||
60 | /* initialize WM8728 codec */ | ||
61 | if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AV710) { | ||
62 | for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2) | ||
63 | wm_put(ice, wm_inits[i], wm_inits[i+1]); | ||
64 | } | ||
65 | |||
43 | return 0; | 66 | return 0; |
44 | } | 67 | } |
45 | 68 | ||
@@ -54,6 +77,13 @@ static int __devinit snd_vt1724_amp_add_controls(ice1712_t *ice) | |||
54 | /* entry point */ | 77 | /* entry point */ |
55 | struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = { | 78 | struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = { |
56 | { | 79 | { |
80 | .subvendor = VT1724_SUBDEVICE_AV710, | ||
81 | .name = "Chaintech AV-710", | ||
82 | .model = "av710", | ||
83 | .chip_init = snd_vt1724_amp_init, | ||
84 | .build_controls = snd_vt1724_amp_add_controls, | ||
85 | }, | ||
86 | { | ||
57 | .subvendor = VT1724_SUBDEVICE_AUDIO2000, | 87 | .subvendor = VT1724_SUBDEVICE_AUDIO2000, |
58 | .name = "AMP Ltd AUDIO2000", | 88 | .name = "AMP Ltd AUDIO2000", |
59 | .model = "amp2000", | 89 | .model = "amp2000", |
diff --git a/sound/pci/ice1712/amp.h b/sound/pci/ice1712/amp.h index d58d43383e83..a0fc89b48122 100644 --- a/sound/pci/ice1712/amp.h +++ b/sound/pci/ice1712/amp.h | |||
@@ -24,9 +24,23 @@ | |||
24 | * | 24 | * |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define AMP_AUDIO2000_DEVICE_DESC "{AMP Ltd,AUDIO2000}," | 27 | #define AMP_AUDIO2000_DEVICE_DESC "{AMP Ltd,AUDIO2000},"\ |
28 | "{Chaintech,AV-710}," | ||
28 | 29 | ||
30 | #if 0 | ||
29 | #define VT1724_SUBDEVICE_AUDIO2000 0x12142417 /* Advanced Micro Peripherals Ltd AUDIO2000 */ | 31 | #define VT1724_SUBDEVICE_AUDIO2000 0x12142417 /* Advanced Micro Peripherals Ltd AUDIO2000 */ |
32 | #else | ||
33 | #define VT1724_SUBDEVICE_AUDIO2000 0x00030003 /* a dummy ID for AMP Audio2000 */ | ||
34 | #endif | ||
35 | #define VT1724_SUBDEVICE_AV710 0x12142417 /* AV710 - the same ID with Audio2000! */ | ||
36 | |||
37 | /* WM8728 on I2C for AV710 */ | ||
38 | #define WM_DEV 0x36 | ||
39 | |||
40 | #define WM_ATTEN_L 0x00 | ||
41 | #define WM_ATTEN_R 0x01 | ||
42 | #define WM_DAC_CTRL 0x02 | ||
43 | #define WM_INT_CTRL 0x03 | ||
30 | 44 | ||
31 | extern struct snd_ice1712_card_info snd_vt1724_amp_cards[]; | 45 | extern struct snd_ice1712_card_info snd_vt1724_amp_cards[]; |
32 | 46 | ||
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 79fba6be3503..a2545a5b26c4 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -2748,7 +2748,7 @@ static struct pci_driver driver = { | |||
2748 | 2748 | ||
2749 | static int __init alsa_card_ice1712_init(void) | 2749 | static int __init alsa_card_ice1712_init(void) |
2750 | { | 2750 | { |
2751 | return pci_module_init(&driver); | 2751 | return pci_register_driver(&driver); |
2752 | } | 2752 | } |
2753 | 2753 | ||
2754 | static void __exit alsa_card_ice1712_exit(void) | 2754 | static void __exit alsa_card_ice1712_exit(void) |
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 8bb1c58c26a0..5ad4728daa7b 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -373,6 +373,11 @@ struct _snd_ice1712 { | |||
373 | unsigned short master[2]; | 373 | unsigned short master[2]; |
374 | unsigned short vol[8]; | 374 | unsigned short vol[8]; |
375 | } aureon; | 375 | } aureon; |
376 | /* AC97 register cache for Phase28 */ | ||
377 | struct phase28_spec { | ||
378 | unsigned short master[2]; | ||
379 | unsigned short vol[8]; | ||
380 | } phase28; | ||
376 | /* Hoontech-specific setting */ | 381 | /* Hoontech-specific setting */ |
377 | struct hoontech_spec { | 382 | struct hoontech_spec { |
378 | unsigned char boxbits[4]; | 383 | unsigned char boxbits[4]; |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 95500f06f0c6..79b5f12e06fc 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -2328,7 +2328,7 @@ static struct pci_driver driver = { | |||
2328 | 2328 | ||
2329 | static int __init alsa_card_ice1724_init(void) | 2329 | static int __init alsa_card_ice1724_init(void) |
2330 | { | 2330 | { |
2331 | return pci_module_init(&driver); | 2331 | return pci_register_driver(&driver); |
2332 | } | 2332 | } |
2333 | 2333 | ||
2334 | static void __exit alsa_card_ice1724_exit(void) | 2334 | static void __exit alsa_card_ice1724_exit(void) |
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c index d1f90832443c..5bf734b04fa0 100644 --- a/sound/pci/ice1712/phase.c +++ b/sound/pci/ice1712/phase.c | |||
@@ -45,6 +45,47 @@ | |||
45 | #include "envy24ht.h" | 45 | #include "envy24ht.h" |
46 | #include "phase.h" | 46 | #include "phase.h" |
47 | 47 | ||
48 | /* WM8770 registers */ | ||
49 | #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ | ||
50 | #define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */ | ||
51 | #define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */ | ||
52 | #define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */ | ||
53 | #define WM_PHASE_SWAP 0x12 /* DAC phase */ | ||
54 | #define WM_DAC_CTRL1 0x13 /* DAC control bits */ | ||
55 | #define WM_MUTE 0x14 /* mute controls */ | ||
56 | #define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */ | ||
57 | #define WM_INT_CTRL 0x16 /* interface control */ | ||
58 | #define WM_MASTER 0x17 /* master clock and mode */ | ||
59 | #define WM_POWERDOWN 0x18 /* power-down controls */ | ||
60 | #define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */ | ||
61 | #define WM_ADC_MUX 0x1b /* input MUX */ | ||
62 | #define WM_OUT_MUX1 0x1c /* output MUX */ | ||
63 | #define WM_OUT_MUX2 0x1e /* output MUX */ | ||
64 | #define WM_RESET 0x1f /* software reset */ | ||
65 | |||
66 | |||
67 | /* | ||
68 | * Logarithmic volume values for WM8770 | ||
69 | * Computed as 20 * Log10(255 / x) | ||
70 | */ | ||
71 | static unsigned char wm_vol[256] = { | ||
72 | 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23, | ||
73 | 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, | ||
74 | 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, | ||
75 | 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, | ||
76 | 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, | ||
77 | 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, | ||
78 | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, | ||
79 | 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, | ||
80 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | ||
81 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | ||
82 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
83 | 0, 0 | ||
84 | }; | ||
85 | |||
86 | #define WM_VOL_MAX (sizeof(wm_vol) - 1) | ||
87 | #define WM_VOL_MUTE 0x8000 | ||
88 | |||
48 | static akm4xxx_t akm_phase22 __devinitdata = { | 89 | static akm4xxx_t akm_phase22 __devinitdata = { |
49 | .type = SND_AK4524, | 90 | .type = SND_AK4524, |
50 | .num_dacs = 2, | 91 | .num_dacs = 2, |
@@ -124,6 +165,684 @@ static unsigned char phase22_eeprom[] __devinitdata = { | |||
124 | 0x00, /* GPIO_STATE2 */ | 165 | 0x00, /* GPIO_STATE2 */ |
125 | }; | 166 | }; |
126 | 167 | ||
168 | static unsigned char phase28_eeprom[] __devinitdata = { | ||
169 | 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */ | ||
170 | 0x80, /* ACLINK: I2S */ | ||
171 | 0xfc, /* I2S: vol, 96k, 24bit, 192k */ | ||
172 | 0xc3, /* SPDIF: out-en, out-int, spdif-in */ | ||
173 | 0xff, /* GPIO_DIR */ | ||
174 | 0xff, /* GPIO_DIR1 */ | ||
175 | 0x5f, /* GPIO_DIR2 */ | ||
176 | 0x00, /* GPIO_MASK */ | ||
177 | 0x00, /* GPIO_MASK1 */ | ||
178 | 0x00, /* GPIO_MASK2 */ | ||
179 | 0x00, /* GPIO_STATE */ | ||
180 | 0x00, /* GPIO_STATE1 */ | ||
181 | 0x00, /* GPIO_STATE2 */ | ||
182 | }; | ||
183 | |||
184 | /* | ||
185 | * write data in the SPI mode | ||
186 | */ | ||
187 | static void phase28_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits) | ||
188 | { | ||
189 | unsigned int tmp; | ||
190 | int i; | ||
191 | |||
192 | tmp = snd_ice1712_gpio_read(ice); | ||
193 | |||
194 | snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|PHASE28_SPI_CLK| | ||
195 | PHASE28_WM_CS)); | ||
196 | tmp |= PHASE28_WM_RW; | ||
197 | tmp &= ~cs; | ||
198 | snd_ice1712_gpio_write(ice, tmp); | ||
199 | udelay(1); | ||
200 | |||
201 | for (i = bits - 1; i >= 0; i--) { | ||
202 | tmp &= ~PHASE28_SPI_CLK; | ||
203 | snd_ice1712_gpio_write(ice, tmp); | ||
204 | udelay(1); | ||
205 | if (data & (1 << i)) | ||
206 | tmp |= PHASE28_SPI_MOSI; | ||
207 | else | ||
208 | tmp &= ~PHASE28_SPI_MOSI; | ||
209 | snd_ice1712_gpio_write(ice, tmp); | ||
210 | udelay(1); | ||
211 | tmp |= PHASE28_SPI_CLK; | ||
212 | snd_ice1712_gpio_write(ice, tmp); | ||
213 | udelay(1); | ||
214 | } | ||
215 | |||
216 | tmp &= ~PHASE28_SPI_CLK; | ||
217 | tmp |= cs; | ||
218 | snd_ice1712_gpio_write(ice, tmp); | ||
219 | udelay(1); | ||
220 | tmp |= PHASE28_SPI_CLK; | ||
221 | snd_ice1712_gpio_write(ice, tmp); | ||
222 | udelay(1); | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * get the current register value of WM codec | ||
227 | */ | ||
228 | static unsigned short wm_get(ice1712_t *ice, int reg) | ||
229 | { | ||
230 | reg <<= 1; | ||
231 | return ((unsigned short)ice->akm[0].images[reg] << 8) | | ||
232 | ice->akm[0].images[reg + 1]; | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | * set the register value of WM codec | ||
237 | */ | ||
238 | static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val) | ||
239 | { | ||
240 | phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16); | ||
241 | } | ||
242 | |||
243 | /* | ||
244 | * set the register value of WM codec and remember it | ||
245 | */ | ||
246 | static void wm_put(ice1712_t *ice, int reg, unsigned short val) | ||
247 | { | ||
248 | wm_put_nocache(ice, reg, val); | ||
249 | reg <<= 1; | ||
250 | ice->akm[0].images[reg] = val >> 8; | ||
251 | ice->akm[0].images[reg + 1] = val; | ||
252 | } | ||
253 | |||
254 | static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master) | ||
255 | { | ||
256 | unsigned char nvol; | ||
257 | |||
258 | if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE)) | ||
259 | nvol = 0; | ||
260 | else | ||
261 | nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX]; | ||
262 | |||
263 | wm_put(ice, index, nvol); | ||
264 | wm_put_nocache(ice, index, 0x180 | nvol); | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * DAC mute control | ||
269 | */ | ||
270 | #define wm_pcm_mute_info phase28_mono_bool_info | ||
271 | |||
272 | static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
273 | { | ||
274 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
275 | |||
276 | down(&ice->gpio_mutex); | ||
277 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1; | ||
278 | up(&ice->gpio_mutex); | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
283 | { | ||
284 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
285 | unsigned short nval, oval; | ||
286 | int change; | ||
287 | |||
288 | snd_ice1712_save_gpio_status(ice); | ||
289 | oval = wm_get(ice, WM_MUTE); | ||
290 | nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10); | ||
291 | if ((change = (nval != oval))) | ||
292 | wm_put(ice, WM_MUTE, nval); | ||
293 | snd_ice1712_restore_gpio_status(ice); | ||
294 | |||
295 | return change; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * Master volume attenuation mixer control | ||
300 | */ | ||
301 | static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
302 | { | ||
303 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
304 | uinfo->count = 2; | ||
305 | uinfo->value.integer.min = 0; | ||
306 | uinfo->value.integer.max = WM_VOL_MAX; | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
311 | { | ||
312 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
313 | int i; | ||
314 | for (i=0; i<2; i++) | ||
315 | ucontrol->value.integer.value[i] = ice->spec.phase28.master[i] & ~WM_VOL_MUTE; | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
320 | { | ||
321 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
322 | int ch, change = 0; | ||
323 | |||
324 | snd_ice1712_save_gpio_status(ice); | ||
325 | for (ch = 0; ch < 2; ch++) { | ||
326 | if (ucontrol->value.integer.value[ch] != ice->spec.phase28.master[ch]) { | ||
327 | int dac; | ||
328 | ice->spec.phase28.master[ch] &= WM_VOL_MUTE; | ||
329 | ice->spec.phase28.master[ch] |= ucontrol->value.integer.value[ch]; | ||
330 | for (dac = 0; dac < ice->num_total_dacs; dac += 2) | ||
331 | wm_set_vol(ice, WM_DAC_ATTEN + dac + ch, | ||
332 | ice->spec.phase28.vol[dac + ch], | ||
333 | ice->spec.phase28.master[ch]); | ||
334 | change = 1; | ||
335 | } | ||
336 | } | ||
337 | snd_ice1712_restore_gpio_status(ice); | ||
338 | return change; | ||
339 | } | ||
340 | |||
341 | static int __devinit phase28_init(ice1712_t *ice) | ||
342 | { | ||
343 | static unsigned short wm_inits_phase28[] = { | ||
344 | /* These come first to reduce init pop noise */ | ||
345 | 0x1b, 0x044, /* ADC Mux (AC'97 source) */ | ||
346 | 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */ | ||
347 | 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */ | ||
348 | |||
349 | 0x18, 0x000, /* All power-up */ | ||
350 | |||
351 | 0x16, 0x122, /* I2S, normal polarity, 24bit */ | ||
352 | 0x17, 0x022, /* 256fs, slave mode */ | ||
353 | 0x00, 0, /* DAC1 analog mute */ | ||
354 | 0x01, 0, /* DAC2 analog mute */ | ||
355 | 0x02, 0, /* DAC3 analog mute */ | ||
356 | 0x03, 0, /* DAC4 analog mute */ | ||
357 | 0x04, 0, /* DAC5 analog mute */ | ||
358 | 0x05, 0, /* DAC6 analog mute */ | ||
359 | 0x06, 0, /* DAC7 analog mute */ | ||
360 | 0x07, 0, /* DAC8 analog mute */ | ||
361 | 0x08, 0x100, /* master analog mute */ | ||
362 | 0x09, 0xff, /* DAC1 digital full */ | ||
363 | 0x0a, 0xff, /* DAC2 digital full */ | ||
364 | 0x0b, 0xff, /* DAC3 digital full */ | ||
365 | 0x0c, 0xff, /* DAC4 digital full */ | ||
366 | 0x0d, 0xff, /* DAC5 digital full */ | ||
367 | 0x0e, 0xff, /* DAC6 digital full */ | ||
368 | 0x0f, 0xff, /* DAC7 digital full */ | ||
369 | 0x10, 0xff, /* DAC8 digital full */ | ||
370 | 0x11, 0x1ff, /* master digital full */ | ||
371 | 0x12, 0x000, /* phase normal */ | ||
372 | 0x13, 0x090, /* unmute DAC L/R */ | ||
373 | 0x14, 0x000, /* all unmute */ | ||
374 | 0x15, 0x000, /* no deemphasis, no ZFLG */ | ||
375 | 0x19, 0x000, /* -12dB ADC/L */ | ||
376 | 0x1a, 0x000, /* -12dB ADC/R */ | ||
377 | (unsigned short)-1 | ||
378 | }; | ||
379 | |||
380 | unsigned int tmp; | ||
381 | akm4xxx_t *ak; | ||
382 | unsigned short *p; | ||
383 | int i; | ||
384 | |||
385 | ice->num_total_dacs = 8; | ||
386 | ice->num_total_adcs = 2; | ||
387 | |||
388 | // Initialize analog chips | ||
389 | ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL); | ||
390 | if (!ak) | ||
391 | return -ENOMEM; | ||
392 | ice->akm_codecs = 1; | ||
393 | |||
394 | snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */ | ||
395 | |||
396 | /* reset the wm codec as the SPI mode */ | ||
397 | snd_ice1712_save_gpio_status(ice); | ||
398 | snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|PHASE28_HP_SEL)); | ||
399 | |||
400 | tmp = snd_ice1712_gpio_read(ice); | ||
401 | tmp &= ~PHASE28_WM_RESET; | ||
402 | snd_ice1712_gpio_write(ice, tmp); | ||
403 | udelay(1); | ||
404 | tmp |= PHASE28_WM_CS; | ||
405 | snd_ice1712_gpio_write(ice, tmp); | ||
406 | udelay(1); | ||
407 | tmp |= PHASE28_WM_RESET; | ||
408 | snd_ice1712_gpio_write(ice, tmp); | ||
409 | udelay(1); | ||
410 | |||
411 | p = wm_inits_phase28; | ||
412 | for (; *p != (unsigned short)-1; p += 2) | ||
413 | wm_put(ice, p[0], p[1]); | ||
414 | |||
415 | snd_ice1712_restore_gpio_status(ice); | ||
416 | |||
417 | ice->spec.phase28.master[0] = WM_VOL_MUTE; | ||
418 | ice->spec.phase28.master[1] = WM_VOL_MUTE; | ||
419 | for (i = 0; i < ice->num_total_dacs; i++) { | ||
420 | ice->spec.phase28.vol[i] = WM_VOL_MUTE; | ||
421 | wm_set_vol(ice, i, ice->spec.phase28.vol[i], ice->spec.phase28.master[i % 2]); | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | * DAC volume attenuation mixer control | ||
429 | */ | ||
430 | static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
431 | { | ||
432 | int voices = kcontrol->private_value >> 8; | ||
433 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
434 | uinfo->count = voices; | ||
435 | uinfo->value.integer.min = 0; /* mute (-101dB) */ | ||
436 | uinfo->value.integer.max = 0x7F; /* 0dB */ | ||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
441 | { | ||
442 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
443 | int i, ofs, voices; | ||
444 | |||
445 | voices = kcontrol->private_value >> 8; | ||
446 | ofs = kcontrol->private_value & 0xff; | ||
447 | for (i = 0; i < voices; i++) | ||
448 | ucontrol->value.integer.value[i] = ice->spec.phase28.vol[ofs+i] & ~WM_VOL_MUTE; | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
453 | { | ||
454 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
455 | int i, idx, ofs, voices; | ||
456 | int change = 0; | ||
457 | |||
458 | voices = kcontrol->private_value >> 8; | ||
459 | ofs = kcontrol->private_value & 0xff; | ||
460 | snd_ice1712_save_gpio_status(ice); | ||
461 | for (i = 0; i < voices; i++) { | ||
462 | idx = WM_DAC_ATTEN + ofs + i; | ||
463 | if (ucontrol->value.integer.value[i] != ice->spec.phase28.vol[ofs+i]) { | ||
464 | ice->spec.phase28.vol[ofs+i] &= WM_VOL_MUTE; | ||
465 | ice->spec.phase28.vol[ofs+i] |= ucontrol->value.integer.value[i]; | ||
466 | wm_set_vol(ice, idx, ice->spec.phase28.vol[ofs+i], | ||
467 | ice->spec.phase28.master[i]); | ||
468 | change = 1; | ||
469 | } | ||
470 | } | ||
471 | snd_ice1712_restore_gpio_status(ice); | ||
472 | return change; | ||
473 | } | ||
474 | |||
475 | /* | ||
476 | * WM8770 mute control | ||
477 | */ | ||
478 | static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) { | ||
479 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
480 | uinfo->count = kcontrol->private_value >> 8; | ||
481 | uinfo->value.integer.min = 0; | ||
482 | uinfo->value.integer.max = 1; | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
487 | { | ||
488 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
489 | int voices, ofs, i; | ||
490 | |||
491 | voices = kcontrol->private_value >> 8; | ||
492 | ofs = kcontrol->private_value & 0xFF; | ||
493 | |||
494 | for (i = 0; i < voices; i++) | ||
495 | ucontrol->value.integer.value[i] = (ice->spec.phase28.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1; | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
500 | { | ||
501 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
502 | int change = 0, voices, ofs, i; | ||
503 | |||
504 | voices = kcontrol->private_value >> 8; | ||
505 | ofs = kcontrol->private_value & 0xFF; | ||
506 | |||
507 | snd_ice1712_save_gpio_status(ice); | ||
508 | for (i = 0; i < voices; i++) { | ||
509 | int val = (ice->spec.phase28.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1; | ||
510 | if (ucontrol->value.integer.value[i] != val) { | ||
511 | ice->spec.phase28.vol[ofs + i] &= ~WM_VOL_MUTE; | ||
512 | ice->spec.phase28.vol[ofs + i] |= | ||
513 | ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; | ||
514 | wm_set_vol(ice, ofs + i, ice->spec.phase28.vol[ofs + i], | ||
515 | ice->spec.phase28.master[i]); | ||
516 | change = 1; | ||
517 | } | ||
518 | } | ||
519 | snd_ice1712_restore_gpio_status(ice); | ||
520 | |||
521 | return change; | ||
522 | } | ||
523 | |||
524 | /* | ||
525 | * WM8770 master mute control | ||
526 | */ | ||
527 | static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) { | ||
528 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
529 | uinfo->count = 2; | ||
530 | uinfo->value.integer.min = 0; | ||
531 | uinfo->value.integer.max = 1; | ||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
536 | { | ||
537 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
538 | |||
539 | ucontrol->value.integer.value[0] = (ice->spec.phase28.master[0] & WM_VOL_MUTE) ? 0 : 1; | ||
540 | ucontrol->value.integer.value[1] = (ice->spec.phase28.master[1] & WM_VOL_MUTE) ? 0 : 1; | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
545 | { | ||
546 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
547 | int change = 0, i; | ||
548 | |||
549 | snd_ice1712_save_gpio_status(ice); | ||
550 | for (i = 0; i < 2; i++) { | ||
551 | int val = (ice->spec.phase28.master[i] & WM_VOL_MUTE) ? 0 : 1; | ||
552 | if (ucontrol->value.integer.value[i] != val) { | ||
553 | int dac; | ||
554 | ice->spec.phase28.master[i] &= ~WM_VOL_MUTE; | ||
555 | ice->spec.phase28.master[i] |= | ||
556 | ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE; | ||
557 | for (dac = 0; dac < ice->num_total_dacs; dac += 2) | ||
558 | wm_set_vol(ice, WM_DAC_ATTEN + dac + i, | ||
559 | ice->spec.phase28.vol[dac + i], | ||
560 | ice->spec.phase28.master[i]); | ||
561 | change = 1; | ||
562 | } | ||
563 | } | ||
564 | snd_ice1712_restore_gpio_status(ice); | ||
565 | |||
566 | return change; | ||
567 | } | ||
568 | |||
569 | /* digital master volume */ | ||
570 | #define PCM_0dB 0xff | ||
571 | #define PCM_RES 128 /* -64dB */ | ||
572 | #define PCM_MIN (PCM_0dB - PCM_RES) | ||
573 | static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
574 | { | ||
575 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
576 | uinfo->count = 1; | ||
577 | uinfo->value.integer.min = 0; /* mute (-64dB) */ | ||
578 | uinfo->value.integer.max = PCM_RES; /* 0dB */ | ||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
583 | { | ||
584 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
585 | unsigned short val; | ||
586 | |||
587 | down(&ice->gpio_mutex); | ||
588 | val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; | ||
589 | val = val > PCM_MIN ? (val - PCM_MIN) : 0; | ||
590 | ucontrol->value.integer.value[0] = val; | ||
591 | up(&ice->gpio_mutex); | ||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
596 | { | ||
597 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
598 | unsigned short ovol, nvol; | ||
599 | int change = 0; | ||
600 | |||
601 | snd_ice1712_save_gpio_status(ice); | ||
602 | nvol = ucontrol->value.integer.value[0]; | ||
603 | nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff; | ||
604 | ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff; | ||
605 | if (ovol != nvol) { | ||
606 | wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */ | ||
607 | wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */ | ||
608 | change = 1; | ||
609 | } | ||
610 | snd_ice1712_restore_gpio_status(ice); | ||
611 | return change; | ||
612 | } | ||
613 | |||
614 | /* | ||
615 | */ | ||
616 | static int phase28_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo) | ||
617 | { | ||
618 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
619 | uinfo->count = 1; | ||
620 | uinfo->value.integer.min = 0; | ||
621 | uinfo->value.integer.max = 1; | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | /* | ||
626 | * Deemphasis | ||
627 | */ | ||
628 | #define phase28_deemp_info phase28_mono_bool_info | ||
629 | |||
630 | static int phase28_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
631 | { | ||
632 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
633 | ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf; | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int phase28_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
638 | { | ||
639 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
640 | int temp, temp2; | ||
641 | temp2 = temp = wm_get(ice, WM_DAC_CTRL2); | ||
642 | if (ucontrol->value.integer.value[0]) | ||
643 | temp |= 0xf; | ||
644 | else | ||
645 | temp &= ~0xf; | ||
646 | if (temp != temp2) { | ||
647 | wm_put(ice, WM_DAC_CTRL2, temp); | ||
648 | return 1; | ||
649 | } | ||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | /* | ||
654 | * ADC Oversampling | ||
655 | */ | ||
656 | static int phase28_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo) | ||
657 | { | ||
658 | static char *texts[2] = { "128x", "64x" }; | ||
659 | |||
660 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
661 | uinfo->count = 1; | ||
662 | uinfo->value.enumerated.items = 2; | ||
663 | |||
664 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
665 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
666 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
667 | |||
668 | return 0; | ||
669 | } | ||
670 | |||
671 | static int phase28_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
672 | { | ||
673 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
674 | ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8; | ||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | static int phase28_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
679 | { | ||
680 | int temp, temp2; | ||
681 | ice1712_t *ice = snd_kcontrol_chip(kcontrol); | ||
682 | |||
683 | temp2 = temp = wm_get(ice, WM_MASTER); | ||
684 | |||
685 | if (ucontrol->value.enumerated.item[0]) | ||
686 | temp |= 0x8; | ||
687 | else | ||
688 | temp &= ~0x8; | ||
689 | |||
690 | if (temp != temp2) { | ||
691 | wm_put(ice, WM_MASTER, temp); | ||
692 | return 1; | ||
693 | } | ||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static snd_kcontrol_new_t phase28_dac_controls[] __devinitdata = { | ||
698 | { | ||
699 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
700 | .name = "Master Playback Switch", | ||
701 | .info = wm_master_mute_info, | ||
702 | .get = wm_master_mute_get, | ||
703 | .put = wm_master_mute_put | ||
704 | }, | ||
705 | { | ||
706 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
707 | .name = "Master Playback Volume", | ||
708 | .info = wm_master_vol_info, | ||
709 | .get = wm_master_vol_get, | ||
710 | .put = wm_master_vol_put | ||
711 | }, | ||
712 | { | ||
713 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
714 | .name = "Front Playback Switch", | ||
715 | .info = wm_mute_info, | ||
716 | .get = wm_mute_get, | ||
717 | .put = wm_mute_put, | ||
718 | .private_value = (2 << 8) | 0 | ||
719 | }, | ||
720 | { | ||
721 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
722 | .name = "Front Playback Volume", | ||
723 | .info = wm_vol_info, | ||
724 | .get = wm_vol_get, | ||
725 | .put = wm_vol_put, | ||
726 | .private_value = (2 << 8) | 0 | ||
727 | }, | ||
728 | { | ||
729 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
730 | .name = "Rear Playback Switch", | ||
731 | .info = wm_mute_info, | ||
732 | .get = wm_mute_get, | ||
733 | .put = wm_mute_put, | ||
734 | .private_value = (2 << 8) | 2 | ||
735 | }, | ||
736 | { | ||
737 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
738 | .name = "Rear Playback Volume", | ||
739 | .info = wm_vol_info, | ||
740 | .get = wm_vol_get, | ||
741 | .put = wm_vol_put, | ||
742 | .private_value = (2 << 8) | 2 | ||
743 | }, | ||
744 | { | ||
745 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
746 | .name = "Center Playback Switch", | ||
747 | .info = wm_mute_info, | ||
748 | .get = wm_mute_get, | ||
749 | .put = wm_mute_put, | ||
750 | .private_value = (1 << 8) | 4 | ||
751 | }, | ||
752 | { | ||
753 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
754 | .name = "Center Playback Volume", | ||
755 | .info = wm_vol_info, | ||
756 | .get = wm_vol_get, | ||
757 | .put = wm_vol_put, | ||
758 | .private_value = (1 << 8) | 4 | ||
759 | }, | ||
760 | { | ||
761 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
762 | .name = "LFE Playback Switch", | ||
763 | .info = wm_mute_info, | ||
764 | .get = wm_mute_get, | ||
765 | .put = wm_mute_put, | ||
766 | .private_value = (1 << 8) | 5 | ||
767 | }, | ||
768 | { | ||
769 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
770 | .name = "LFE Playback Volume", | ||
771 | .info = wm_vol_info, | ||
772 | .get = wm_vol_get, | ||
773 | .put = wm_vol_put, | ||
774 | .private_value = (1 << 8) | 5 | ||
775 | }, | ||
776 | { | ||
777 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
778 | .name = "Side Playback Switch", | ||
779 | .info = wm_mute_info, | ||
780 | .get = wm_mute_get, | ||
781 | .put = wm_mute_put, | ||
782 | .private_value = (2 << 8) | 6 | ||
783 | }, | ||
784 | { | ||
785 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
786 | .name = "Side Playback Volume", | ||
787 | .info = wm_vol_info, | ||
788 | .get = wm_vol_get, | ||
789 | .put = wm_vol_put, | ||
790 | .private_value = (2 << 8) | 6 | ||
791 | } | ||
792 | }; | ||
793 | |||
794 | static snd_kcontrol_new_t wm_controls[] __devinitdata = { | ||
795 | { | ||
796 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
797 | .name = "PCM Playback Switch", | ||
798 | .info = wm_pcm_mute_info, | ||
799 | .get = wm_pcm_mute_get, | ||
800 | .put = wm_pcm_mute_put | ||
801 | }, | ||
802 | { | ||
803 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
804 | .name = "PCM Playback Volume", | ||
805 | .info = wm_pcm_vol_info, | ||
806 | .get = wm_pcm_vol_get, | ||
807 | .put = wm_pcm_vol_put | ||
808 | }, | ||
809 | { | ||
810 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
811 | .name = "DAC Deemphasis Switch", | ||
812 | .info = phase28_deemp_info, | ||
813 | .get = phase28_deemp_get, | ||
814 | .put = phase28_deemp_put | ||
815 | }, | ||
816 | { | ||
817 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
818 | .name = "ADC Oversampling", | ||
819 | .info = phase28_oversampling_info, | ||
820 | .get = phase28_oversampling_get, | ||
821 | .put = phase28_oversampling_put | ||
822 | } | ||
823 | }; | ||
824 | |||
825 | static int __devinit phase28_add_controls(ice1712_t *ice) | ||
826 | { | ||
827 | unsigned int i, counts; | ||
828 | int err; | ||
829 | |||
830 | counts = ARRAY_SIZE(phase28_dac_controls); | ||
831 | for (i = 0; i < counts; i++) { | ||
832 | err = snd_ctl_add(ice->card, snd_ctl_new1(&phase28_dac_controls[i], ice)); | ||
833 | if (err < 0) | ||
834 | return err; | ||
835 | } | ||
836 | |||
837 | for (i = 0; i < ARRAY_SIZE(wm_controls); i++) { | ||
838 | err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice)); | ||
839 | if (err < 0) | ||
840 | return err; | ||
841 | } | ||
842 | |||
843 | return 0; | ||
844 | } | ||
845 | |||
127 | struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { | 846 | struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { |
128 | { | 847 | { |
129 | .subvendor = VT1724_SUBDEVICE_PHASE22, | 848 | .subvendor = VT1724_SUBDEVICE_PHASE22, |
@@ -134,5 +853,14 @@ struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { | |||
134 | .eeprom_size = sizeof(phase22_eeprom), | 853 | .eeprom_size = sizeof(phase22_eeprom), |
135 | .eeprom_data = phase22_eeprom, | 854 | .eeprom_data = phase22_eeprom, |
136 | }, | 855 | }, |
856 | { | ||
857 | .subvendor = VT1724_SUBDEVICE_PHASE28, | ||
858 | .name = "Terratec PHASE 28", | ||
859 | .model = "phase28", | ||
860 | .chip_init = phase28_init, | ||
861 | .build_controls = phase28_add_controls, | ||
862 | .eeprom_size = sizeof(phase28_eeprom), | ||
863 | .eeprom_data = phase28_eeprom, | ||
864 | }, | ||
137 | { } /* terminator */ | 865 | { } /* terminator */ |
138 | }; | 866 | }; |
diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h index 6230cf16989f..13e841b55488 100644 --- a/sound/pci/ice1712/phase.h +++ b/sound/pci/ice1712/phase.h | |||
@@ -24,11 +24,28 @@ | |||
24 | * | 24 | * |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define PHASE_DEVICE_DESC "{Terratec,Phase 22}," | 27 | #define PHASE_DEVICE_DESC "{Terratec,Phase 22},"\ |
28 | "{Terratec,Phase 28}," | ||
28 | 29 | ||
29 | #define VT1724_SUBDEVICE_PHASE22 0x3b155011 | 30 | #define VT1724_SUBDEVICE_PHASE22 0x3b155011 |
31 | #define VT1724_SUBDEVICE_PHASE28 0x3b154911 | ||
30 | 32 | ||
31 | /* entry point */ | 33 | /* entry point */ |
32 | extern struct snd_ice1712_card_info snd_vt1724_phase_cards[]; | 34 | extern struct snd_ice1712_card_info snd_vt1724_phase_cards[]; |
33 | 35 | ||
36 | /* PHASE28 GPIO bits */ | ||
37 | #define PHASE28_SPI_MISO (1 << 21) | ||
38 | #define PHASE28_WM_RESET (1 << 20) | ||
39 | #define PHASE28_SPI_CLK (1 << 19) | ||
40 | #define PHASE28_SPI_MOSI (1 << 18) | ||
41 | #define PHASE28_WM_RW (1 << 17) | ||
42 | #define PHASE28_AC97_RESET (1 << 16) | ||
43 | #define PHASE28_DIGITAL_SEL1 (1 << 15) | ||
44 | #define PHASE28_HP_SEL (1 << 14) | ||
45 | #define PHASE28_WM_CS (1 << 12) | ||
46 | #define PHASE28_AC97_COMMIT (1 << 11) | ||
47 | #define PHASE28_AC97_ADDR (1 << 10) | ||
48 | #define PHASE28_AC97_DATA_LOW (1 << 9) | ||
49 | #define PHASE28_AC97_DATA_HIGH (1 << 8) | ||
50 | #define PHASE28_AC97_DATA_MASK 0xFF | ||
34 | #endif /* __SOUND_PHASE */ | 51 | #endif /* __SOUND_PHASE */ |
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c index 3bd92627231c..ab61e383024f 100644 --- a/sound/pci/ice1712/vt1720_mobo.c +++ b/sound/pci/ice1712/vt1720_mobo.c | |||
@@ -110,6 +110,15 @@ struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = { | |||
110 | .eeprom_size = sizeof(k8x800_eeprom), | 110 | .eeprom_size = sizeof(k8x800_eeprom), |
111 | .eeprom_data = k8x800_eeprom, | 111 | .eeprom_data = k8x800_eeprom, |
112 | }, | 112 | }, |
113 | { | ||
114 | .subvendor = VT1720_SUBDEVICE_SN25P, | ||
115 | .name = "Shuttle SN25P", | ||
116 | /* identical with k8x800 */ | ||
117 | .chip_init = k8x800_init, | ||
118 | .build_controls = k8x800_add_controls, | ||
119 | .eeprom_size = sizeof(k8x800_eeprom), | ||
120 | .eeprom_data = k8x800_eeprom, | ||
121 | }, | ||
113 | { } /* terminator */ | 122 | { } /* terminator */ |
114 | }; | 123 | }; |
115 | 124 | ||
diff --git a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h index f949eb804cae..0b1b0ee1bea7 100644 --- a/sound/pci/ice1712/vt1720_mobo.h +++ b/sound/pci/ice1712/vt1720_mobo.h | |||
@@ -27,12 +27,14 @@ | |||
27 | #define VT1720_MOBO_DEVICE_DESC "{Albatron,K8X800 Pro II},"\ | 27 | #define VT1720_MOBO_DEVICE_DESC "{Albatron,K8X800 Pro II},"\ |
28 | "{Chaintech,ZNF3-150},"\ | 28 | "{Chaintech,ZNF3-150},"\ |
29 | "{Chaintech,ZNF3-250},"\ | 29 | "{Chaintech,ZNF3-250},"\ |
30 | "{Chaintech,9CJS}," | 30 | "{Chaintech,9CJS},"\ |
31 | "{Shuttle,SN25P}," | ||
31 | 32 | ||
32 | #define VT1720_SUBDEVICE_K8X800 0xf217052c | 33 | #define VT1720_SUBDEVICE_K8X800 0xf217052c |
33 | #define VT1720_SUBDEVICE_ZNF3_150 0x0f2741f6 | 34 | #define VT1720_SUBDEVICE_ZNF3_150 0x0f2741f6 |
34 | #define VT1720_SUBDEVICE_ZNF3_250 0x0f2745f6 | 35 | #define VT1720_SUBDEVICE_ZNF3_250 0x0f2745f6 |
35 | #define VT1720_SUBDEVICE_9CJS 0x0f272327 | 36 | #define VT1720_SUBDEVICE_9CJS 0x0f272327 |
37 | #define VT1720_SUBDEVICE_SN25P 0x97123650 | ||
36 | 38 | ||
37 | extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[]; | 39 | extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[]; |
38 | 40 | ||
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 8b33b12fa5dc..d7af3e474432 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -424,6 +424,7 @@ struct _snd_intel8x0 { | |||
424 | unsigned xbox: 1; /* workaround for Xbox AC'97 detection */ | 424 | unsigned xbox: 1; /* workaround for Xbox AC'97 detection */ |
425 | 425 | ||
426 | int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */ | 426 | int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */ |
427 | unsigned int sdm_saved; /* SDM reg value */ | ||
427 | 428 | ||
428 | ac97_bus_t *ac97_bus; | 429 | ac97_bus_t *ac97_bus; |
429 | ac97_t *ac97[3]; | 430 | ac97_t *ac97[3]; |
@@ -1725,229 +1726,235 @@ static struct ac97_pcm ac97_pcm_defs[] __devinitdata = { | |||
1725 | 1726 | ||
1726 | static struct ac97_quirk ac97_quirks[] __devinitdata = { | 1727 | static struct ac97_quirk ac97_quirks[] __devinitdata = { |
1727 | { | 1728 | { |
1728 | .vendor = 0x0e11, | 1729 | .subvendor = 0x0e11, |
1729 | .device = 0x008a, | 1730 | .subdevice = 0x008a, |
1730 | .name = "Compaq Evo W4000", /* AD1885 */ | 1731 | .name = "Compaq Evo W4000", /* AD1885 */ |
1731 | .type = AC97_TUNE_HP_ONLY | 1732 | .type = AC97_TUNE_HP_ONLY |
1732 | }, | 1733 | }, |
1733 | { | 1734 | { |
1734 | .vendor = 0x0e11, | 1735 | .subvendor = 0x0e11, |
1735 | .device = 0x00b8, | 1736 | .subdevice = 0x00b8, |
1736 | .name = "Compaq Evo D510C", | 1737 | .name = "Compaq Evo D510C", |
1737 | .type = AC97_TUNE_HP_ONLY | 1738 | .type = AC97_TUNE_HP_ONLY |
1738 | }, | 1739 | }, |
1739 | { | 1740 | { |
1740 | .vendor = 0x0e11, | 1741 | .subvendor = 0x0e11, |
1741 | .device = 0x0860, | 1742 | .subdevice = 0x0860, |
1742 | .name = "HP/Compaq nx7010", | 1743 | .name = "HP/Compaq nx7010", |
1743 | .type = AC97_TUNE_MUTE_LED | 1744 | .type = AC97_TUNE_MUTE_LED |
1744 | }, | 1745 | }, |
1745 | { | 1746 | { |
1746 | .vendor = 0x1014, | 1747 | .subvendor = 0x1014, |
1747 | .device = 0x1f00, | 1748 | .subdevice = 0x1f00, |
1748 | .name = "MS-9128", | 1749 | .name = "MS-9128", |
1749 | .type = AC97_TUNE_ALC_JACK | 1750 | .type = AC97_TUNE_ALC_JACK |
1750 | }, | 1751 | }, |
1751 | { | 1752 | { |
1752 | .vendor = 0x1028, | 1753 | .subvendor = 0x1028, |
1753 | .device = 0x00d8, | 1754 | .subdevice = 0x00d8, |
1754 | .name = "Dell Precision 530", /* AD1885 */ | 1755 | .name = "Dell Precision 530", /* AD1885 */ |
1755 | .type = AC97_TUNE_HP_ONLY | 1756 | .type = AC97_TUNE_HP_ONLY |
1756 | }, | 1757 | }, |
1757 | { | 1758 | { |
1758 | .vendor = 0x1028, | 1759 | .subvendor = 0x1028, |
1759 | .device = 0x010d, | 1760 | .subdevice = 0x010d, |
1760 | .name = "Dell", /* which model? AD1885 */ | 1761 | .name = "Dell", /* which model? AD1885 */ |
1761 | .type = AC97_TUNE_HP_ONLY | 1762 | .type = AC97_TUNE_HP_ONLY |
1762 | }, | 1763 | }, |
1763 | { | 1764 | { |
1764 | .vendor = 0x1028, | 1765 | .subvendor = 0x1028, |
1765 | .device = 0x0126, | 1766 | .subdevice = 0x0126, |
1766 | .name = "Dell Optiplex GX260", /* AD1981A */ | 1767 | .name = "Dell Optiplex GX260", /* AD1981A */ |
1767 | .type = AC97_TUNE_HP_ONLY | 1768 | .type = AC97_TUNE_HP_ONLY |
1768 | }, | 1769 | }, |
1769 | { | 1770 | { |
1770 | .vendor = 0x1028, | 1771 | .subvendor = 0x1028, |
1771 | .device = 0x012c, | 1772 | .subdevice = 0x012c, |
1772 | .name = "Dell Precision 650", /* AD1981A */ | 1773 | .name = "Dell Precision 650", /* AD1981A */ |
1773 | .type = AC97_TUNE_HP_ONLY | 1774 | .type = AC97_TUNE_HP_ONLY |
1774 | }, | 1775 | }, |
1775 | { | 1776 | { |
1776 | .vendor = 0x1028, | 1777 | .subvendor = 0x1028, |
1777 | .device = 0x012d, | 1778 | .subdevice = 0x012d, |
1778 | .name = "Dell Precision 450", /* AD1981B*/ | 1779 | .name = "Dell Precision 450", /* AD1981B*/ |
1779 | .type = AC97_TUNE_HP_ONLY | 1780 | .type = AC97_TUNE_HP_ONLY |
1780 | }, | 1781 | }, |
1781 | { | 1782 | { |
1782 | .vendor = 0x1028, | 1783 | .subvendor = 0x1028, |
1783 | .device = 0x0147, | 1784 | .subdevice = 0x0147, |
1784 | .name = "Dell", /* which model? AD1981B*/ | 1785 | .name = "Dell", /* which model? AD1981B*/ |
1785 | .type = AC97_TUNE_HP_ONLY | 1786 | .type = AC97_TUNE_HP_ONLY |
1786 | }, | 1787 | }, |
1787 | { | 1788 | { |
1788 | .vendor = 0x1028, | 1789 | .subvendor = 0x1028, |
1789 | .device = 0x0163, | 1790 | .subdevice = 0x0163, |
1790 | .name = "Dell Unknown", /* STAC9750/51 */ | 1791 | .name = "Dell Unknown", /* STAC9750/51 */ |
1791 | .type = AC97_TUNE_HP_ONLY | 1792 | .type = AC97_TUNE_HP_ONLY |
1792 | }, | 1793 | }, |
1793 | { | 1794 | { |
1794 | .vendor = 0x103c, | 1795 | .subvendor = 0x103c, |
1795 | .device = 0x006d, | 1796 | .subdevice = 0x006d, |
1796 | .name = "HP zv5000", | 1797 | .name = "HP zv5000", |
1797 | .type = AC97_TUNE_MUTE_LED /*AD1981B*/ | 1798 | .type = AC97_TUNE_MUTE_LED /*AD1981B*/ |
1798 | }, | 1799 | }, |
1799 | { /* FIXME: which codec? */ | 1800 | { /* FIXME: which codec? */ |
1800 | .vendor = 0x103c, | 1801 | .subvendor = 0x103c, |
1801 | .device = 0x00c3, | 1802 | .subdevice = 0x00c3, |
1802 | .name = "HP xw6000", | 1803 | .name = "HP xw6000", |
1803 | .type = AC97_TUNE_HP_ONLY | 1804 | .type = AC97_TUNE_HP_ONLY |
1804 | }, | 1805 | }, |
1805 | { | 1806 | { |
1806 | .vendor = 0x103c, | 1807 | .subvendor = 0x103c, |
1807 | .device = 0x088c, | 1808 | .subdevice = 0x088c, |
1808 | .name = "HP nc8000", | 1809 | .name = "HP nc8000", |
1809 | .type = AC97_TUNE_MUTE_LED | 1810 | .type = AC97_TUNE_MUTE_LED |
1810 | }, | 1811 | }, |
1811 | { | 1812 | { |
1812 | .vendor = 0x103c, | 1813 | .subvendor = 0x103c, |
1813 | .device = 0x0890, | 1814 | .subdevice = 0x0890, |
1814 | .name = "HP nc6000", | 1815 | .name = "HP nc6000", |
1815 | .type = AC97_TUNE_MUTE_LED | 1816 | .type = AC97_TUNE_MUTE_LED |
1816 | }, | 1817 | }, |
1817 | { | 1818 | { |
1818 | .vendor = 0x103c, | 1819 | .subvendor = 0x103c, |
1819 | .device = 0x129d, | 1820 | .subdevice = 0x129d, |
1820 | .name = "HP xw8000", | 1821 | .name = "HP xw8000", |
1821 | .type = AC97_TUNE_HP_ONLY | 1822 | .type = AC97_TUNE_HP_ONLY |
1822 | }, | 1823 | }, |
1823 | { | 1824 | { |
1824 | .vendor = 0x103c, | 1825 | .subvendor = 0x103c, |
1825 | .device = 0x12f1, | 1826 | .subdevice = 0x12f1, |
1826 | .name = "HP xw8200", /* AD1981B*/ | 1827 | .name = "HP xw8200", /* AD1981B*/ |
1827 | .type = AC97_TUNE_HP_ONLY | 1828 | .type = AC97_TUNE_HP_ONLY |
1828 | }, | 1829 | }, |
1829 | { | 1830 | { |
1830 | .vendor = 0x103c, | 1831 | .subvendor = 0x103c, |
1831 | .device = 0x12f2, | 1832 | .subdevice = 0x12f2, |
1832 | .name = "HP xw6200", | 1833 | .name = "HP xw6200", |
1833 | .type = AC97_TUNE_HP_ONLY | 1834 | .type = AC97_TUNE_HP_ONLY |
1834 | }, | 1835 | }, |
1835 | { | 1836 | { |
1836 | .vendor = 0x103c, | 1837 | .subvendor = 0x103c, |
1837 | .device = 0x3008, | 1838 | .subdevice = 0x3008, |
1838 | .name = "HP xw4200", /* AD1981B*/ | 1839 | .name = "HP xw4200", /* AD1981B*/ |
1839 | .type = AC97_TUNE_HP_ONLY | 1840 | .type = AC97_TUNE_HP_ONLY |
1840 | }, | 1841 | }, |
1841 | { | 1842 | { |
1842 | .vendor = 0x104d, | 1843 | .subvendor = 0x104d, |
1843 | .device = 0x8197, | 1844 | .subdevice = 0x8197, |
1844 | .name = "Sony S1XP", | 1845 | .name = "Sony S1XP", |
1845 | .type = AC97_TUNE_INV_EAPD | 1846 | .type = AC97_TUNE_INV_EAPD |
1846 | }, | 1847 | }, |
1847 | { | 1848 | { |
1848 | .vendor = 0x1043, | 1849 | .subvendor = 0x1043, |
1849 | .device = 0x80f3, | 1850 | .subdevice = 0x80f3, |
1850 | .name = "ASUS ICH5/AD1985", | 1851 | .name = "ASUS ICH5/AD1985", |
1851 | .type = AC97_TUNE_AD_SHARING | 1852 | .type = AC97_TUNE_AD_SHARING |
1852 | }, | 1853 | }, |
1853 | { | 1854 | { |
1854 | .vendor = 0x10cf, | 1855 | .subvendor = 0x10cf, |
1855 | .device = 0x11c3, | 1856 | .subdevice = 0x11c3, |
1856 | .name = "Fujitsu-Siemens E4010", | 1857 | .name = "Fujitsu-Siemens E4010", |
1857 | .type = AC97_TUNE_HP_ONLY | 1858 | .type = AC97_TUNE_HP_ONLY |
1858 | }, | 1859 | }, |
1859 | { | 1860 | { |
1860 | .vendor = 0x10cf, | 1861 | .subvendor = 0x10cf, |
1861 | .device = 0x1253, | 1862 | .subdevice = 0x1225, |
1863 | .name = "Fujitsu-Siemens T3010", | ||
1864 | .type = AC97_TUNE_HP_ONLY | ||
1865 | }, | ||
1866 | { | ||
1867 | .subvendor = 0x10cf, | ||
1868 | .subdevice = 0x1253, | ||
1862 | .name = "Fujitsu S6210", /* STAC9750/51 */ | 1869 | .name = "Fujitsu S6210", /* STAC9750/51 */ |
1863 | .type = AC97_TUNE_HP_ONLY | 1870 | .type = AC97_TUNE_HP_ONLY |
1864 | }, | 1871 | }, |
1865 | { | 1872 | { |
1866 | .vendor = 0x10f1, | 1873 | .subvendor = 0x10f1, |
1867 | .device = 0x2665, | 1874 | .subdevice = 0x2665, |
1868 | .name = "Fujitsu-Siemens Celsius", /* AD1981? */ | 1875 | .name = "Fujitsu-Siemens Celsius", /* AD1981? */ |
1869 | .type = AC97_TUNE_HP_ONLY | 1876 | .type = AC97_TUNE_HP_ONLY |
1870 | }, | 1877 | }, |
1871 | { | 1878 | { |
1872 | .vendor = 0x10f1, | 1879 | .subvendor = 0x10f1, |
1873 | .device = 0x2885, | 1880 | .subdevice = 0x2885, |
1874 | .name = "AMD64 Mobo", /* ALC650 */ | 1881 | .name = "AMD64 Mobo", /* ALC650 */ |
1875 | .type = AC97_TUNE_HP_ONLY | 1882 | .type = AC97_TUNE_HP_ONLY |
1876 | }, | 1883 | }, |
1877 | { | 1884 | { |
1878 | .vendor = 0x110a, | 1885 | .subvendor = 0x110a, |
1879 | .device = 0x0056, | 1886 | .subdevice = 0x0056, |
1880 | .name = "Fujitsu-Siemens Scenic", /* AD1981? */ | 1887 | .name = "Fujitsu-Siemens Scenic", /* AD1981? */ |
1881 | .type = AC97_TUNE_HP_ONLY | 1888 | .type = AC97_TUNE_HP_ONLY |
1882 | }, | 1889 | }, |
1883 | { | 1890 | { |
1884 | .vendor = 0x11d4, | 1891 | .subvendor = 0x11d4, |
1885 | .device = 0x5375, | 1892 | .subdevice = 0x5375, |
1886 | .name = "ADI AD1985 (discrete)", | 1893 | .name = "ADI AD1985 (discrete)", |
1887 | .type = AC97_TUNE_HP_ONLY | 1894 | .type = AC97_TUNE_HP_ONLY |
1888 | }, | 1895 | }, |
1889 | { | 1896 | { |
1890 | .vendor = 0x1462, | 1897 | .subvendor = 0x1462, |
1891 | .device = 0x5470, | 1898 | .subdevice = 0x5470, |
1892 | .name = "MSI P4 ATX 645 Ultra", | 1899 | .name = "MSI P4 ATX 645 Ultra", |
1893 | .type = AC97_TUNE_HP_ONLY | 1900 | .type = AC97_TUNE_HP_ONLY |
1894 | }, | 1901 | }, |
1895 | { | 1902 | { |
1896 | .vendor = 0x1734, | 1903 | .subvendor = 0x1734, |
1897 | .device = 0x0088, | 1904 | .subdevice = 0x0088, |
1898 | .name = "Fujitsu-Siemens D1522", /* AD1981 */ | 1905 | .name = "Fujitsu-Siemens D1522", /* AD1981 */ |
1899 | .type = AC97_TUNE_HP_ONLY | 1906 | .type = AC97_TUNE_HP_ONLY |
1900 | }, | 1907 | }, |
1901 | { | 1908 | { |
1902 | .vendor = 0x8086, | 1909 | .subvendor = 0x8086, |
1903 | .device = 0x2000, | 1910 | .subdevice = 0x2000, |
1904 | .mask = 0xfff0, | 1911 | .mask = 0xfff0, |
1905 | .name = "Intel ICH5/AD1985", | 1912 | .name = "Intel ICH5/AD1985", |
1906 | .type = AC97_TUNE_AD_SHARING | 1913 | .type = AC97_TUNE_AD_SHARING |
1907 | }, | 1914 | }, |
1908 | { | 1915 | { |
1909 | .vendor = 0x8086, | 1916 | .subvendor = 0x8086, |
1910 | .device = 0x4000, | 1917 | .subdevice = 0x4000, |
1911 | .mask = 0xfff0, | 1918 | .mask = 0xfff0, |
1912 | .name = "Intel ICH5/AD1985", | 1919 | .name = "Intel ICH5/AD1985", |
1913 | .type = AC97_TUNE_AD_SHARING | 1920 | .type = AC97_TUNE_AD_SHARING |
1914 | }, | 1921 | }, |
1915 | { | 1922 | { |
1916 | .vendor = 0x8086, | 1923 | .subvendor = 0x8086, |
1917 | .device = 0x4856, | 1924 | .subdevice = 0x4856, |
1918 | .name = "Intel D845WN (82801BA)", | 1925 | .name = "Intel D845WN (82801BA)", |
1919 | .type = AC97_TUNE_SWAP_HP | 1926 | .type = AC97_TUNE_SWAP_HP |
1920 | }, | 1927 | }, |
1921 | { | 1928 | { |
1922 | .vendor = 0x8086, | 1929 | .subvendor = 0x8086, |
1923 | .device = 0x4d44, | 1930 | .subdevice = 0x4d44, |
1924 | .name = "Intel D850EMV2", /* AD1885 */ | 1931 | .name = "Intel D850EMV2", /* AD1885 */ |
1925 | .type = AC97_TUNE_HP_ONLY | 1932 | .type = AC97_TUNE_HP_ONLY |
1926 | }, | 1933 | }, |
1927 | { | 1934 | { |
1928 | .vendor = 0x8086, | 1935 | .subvendor = 0x8086, |
1929 | .device = 0x4d56, | 1936 | .subdevice = 0x4d56, |
1930 | .name = "Intel ICH/AD1885", | 1937 | .name = "Intel ICH/AD1885", |
1931 | .type = AC97_TUNE_HP_ONLY | 1938 | .type = AC97_TUNE_HP_ONLY |
1932 | }, | 1939 | }, |
1933 | { | 1940 | { |
1934 | .vendor = 0x8086, | 1941 | .subvendor = 0x8086, |
1935 | .device = 0x6000, | 1942 | .subdevice = 0x6000, |
1936 | .mask = 0xfff0, | 1943 | .mask = 0xfff0, |
1937 | .name = "Intel ICH5/AD1985", | 1944 | .name = "Intel ICH5/AD1985", |
1938 | .type = AC97_TUNE_AD_SHARING | 1945 | .type = AC97_TUNE_AD_SHARING |
1939 | }, | 1946 | }, |
1940 | { | 1947 | { |
1941 | .vendor = 0x8086, | 1948 | .subvendor = 0x8086, |
1942 | .device = 0xe000, | 1949 | .subdevice = 0xe000, |
1943 | .mask = 0xfff0, | 1950 | .mask = 0xfff0, |
1944 | .name = "Intel ICH5/AD1985", | 1951 | .name = "Intel ICH5/AD1985", |
1945 | .type = AC97_TUNE_AD_SHARING | 1952 | .type = AC97_TUNE_AD_SHARING |
1946 | }, | 1953 | }, |
1947 | #if 0 /* FIXME: this seems wrong on most boards */ | 1954 | #if 0 /* FIXME: this seems wrong on most boards */ |
1948 | { | 1955 | { |
1949 | .vendor = 0x8086, | 1956 | .subvendor = 0x8086, |
1950 | .device = 0xa000, | 1957 | .subdevice = 0xa000, |
1951 | .mask = 0xfff0, | 1958 | .mask = 0xfff0, |
1952 | .name = "Intel ICH5/AD1985", | 1959 | .name = "Intel ICH5/AD1985", |
1953 | .type = AC97_TUNE_HP_ONLY | 1960 | .type = AC97_TUNE_HP_ONLY |
@@ -2367,6 +2374,11 @@ static int intel8x0_suspend(snd_card_t *card, pm_message_t state) | |||
2367 | for (i = 0; i < 3; i++) | 2374 | for (i = 0; i < 3; i++) |
2368 | if (chip->ac97[i]) | 2375 | if (chip->ac97[i]) |
2369 | snd_ac97_suspend(chip->ac97[i]); | 2376 | snd_ac97_suspend(chip->ac97[i]); |
2377 | if (chip->device_type == DEVICE_INTEL_ICH4) | ||
2378 | chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); | ||
2379 | |||
2380 | if (chip->irq >= 0) | ||
2381 | free_irq(chip->irq, (void *)chip); | ||
2370 | pci_disable_device(chip->pci); | 2382 | pci_disable_device(chip->pci); |
2371 | return 0; | 2383 | return 0; |
2372 | } | 2384 | } |
@@ -2378,7 +2390,19 @@ static int intel8x0_resume(snd_card_t *card) | |||
2378 | 2390 | ||
2379 | pci_enable_device(chip->pci); | 2391 | pci_enable_device(chip->pci); |
2380 | pci_set_master(chip->pci); | 2392 | pci_set_master(chip->pci); |
2381 | snd_intel8x0_chip_init(chip, 0); | 2393 | request_irq(chip->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip); |
2394 | synchronize_irq(chip->irq); | ||
2395 | snd_intel8x0_chip_init(chip, 1); | ||
2396 | |||
2397 | /* re-initialize mixer stuff */ | ||
2398 | if (chip->device_type == DEVICE_INTEL_ICH4) { | ||
2399 | /* enable separate SDINs for ICH4 */ | ||
2400 | iputbyte(chip, ICHREG(SDM), chip->sdm_saved); | ||
2401 | /* use slot 10/11 for SPDIF */ | ||
2402 | iputdword(chip, ICHREG(GLOB_CNT), | ||
2403 | (igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK) | | ||
2404 | ICH_PCM_SPDIF_1011); | ||
2405 | } | ||
2382 | 2406 | ||
2383 | /* refill nocache */ | 2407 | /* refill nocache */ |
2384 | if (chip->fix_nocache) | 2408 | if (chip->fix_nocache) |
@@ -2445,8 +2469,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip) | |||
2445 | } | 2469 | } |
2446 | do_gettimeofday(&start_time); | 2470 | do_gettimeofday(&start_time); |
2447 | spin_unlock_irq(&chip->reg_lock); | 2471 | spin_unlock_irq(&chip->reg_lock); |
2448 | set_current_state(TASK_UNINTERRUPTIBLE); | 2472 | msleep(50); |
2449 | schedule_timeout(HZ / 20); | ||
2450 | spin_lock_irq(&chip->reg_lock); | 2473 | spin_lock_irq(&chip->reg_lock); |
2451 | /* check the position */ | 2474 | /* check the position */ |
2452 | pos = ichdev->fragsize1; | 2475 | pos = ichdev->fragsize1; |
@@ -2849,7 +2872,7 @@ static struct pci_driver driver = { | |||
2849 | 2872 | ||
2850 | static int __init alsa_card_intel8x0_init(void) | 2873 | static int __init alsa_card_intel8x0_init(void) |
2851 | { | 2874 | { |
2852 | return pci_module_init(&driver); | 2875 | return pci_register_driver(&driver); |
2853 | } | 2876 | } |
2854 | 2877 | ||
2855 | static void __exit alsa_card_intel8x0_exit(void) | 2878 | static void __exit alsa_card_intel8x0_exit(void) |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 67da096d659b..bb758c77d211 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <sound/pcm.h> | 35 | #include <sound/pcm.h> |
36 | #include <sound/ac97_codec.h> | 36 | #include <sound/ac97_codec.h> |
37 | #include <sound/info.h> | 37 | #include <sound/info.h> |
38 | #include <sound/control.h> | ||
39 | #include <sound/initval.h> | 38 | #include <sound/initval.h> |
40 | 39 | ||
41 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); | 40 | MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); |
@@ -292,60 +291,9 @@ static struct pci_device_id snd_intel8x0m_ids[] = { | |||
292 | #endif | 291 | #endif |
293 | { 0, } | 292 | { 0, } |
294 | }; | 293 | }; |
295 | static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol, | ||
296 | snd_ctl_elem_value_t *ucontrol); | ||
297 | static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol, | ||
298 | snd_ctl_elem_value_t *ucontrol); | ||
299 | static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol, | ||
300 | snd_ctl_elem_info_t *uinfo); | ||
301 | |||
302 | #define PRIVATE_VALUE_INITIALIZER(r,m) (((r) & 0xffff) << 16 | ((m) & 0xffff)) | ||
303 | #define PRIVATE_VALUE_MASK(control) ((control)->private_value & 0xffff) | ||
304 | #define PRIVATE_VALUE_REG(control) (((control)->private_value >> 16) & 0xffff) | ||
305 | |||
306 | static snd_kcontrol_new_t snd_intel8x0m_mixer_switches[] __devinitdata = { | ||
307 | { .name = "Off-hook Switch", | ||
308 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
309 | .info = snd_intel8x0m_switch_default_info, | ||
310 | .get = snd_intel8x0m_switch_default_get, | ||
311 | .put = snd_intel8x0m_switch_default_put, | ||
312 | .private_value = PRIVATE_VALUE_INITIALIZER(AC97_GPIO_STATUS,AC97_GPIO_LINE1_OH) | ||
313 | } | ||
314 | }; | ||
315 | 294 | ||
316 | MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids); | 295 | MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids); |
317 | 296 | ||
318 | static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol, | ||
319 | snd_ctl_elem_info_t *uinfo) | ||
320 | { | ||
321 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
322 | uinfo->count = 1; | ||
323 | uinfo->value.integer.min = 0; | ||
324 | uinfo->value.integer.max = 1; | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol, | ||
329 | snd_ctl_elem_value_t *ucontrol) | ||
330 | { | ||
331 | unsigned short mask = PRIVATE_VALUE_MASK(kcontrol); | ||
332 | unsigned short reg = PRIVATE_VALUE_REG(kcontrol); | ||
333 | intel8x0_t *chip = snd_kcontrol_chip(kcontrol); | ||
334 | unsigned int status; | ||
335 | status = snd_ac97_read(chip->ac97, reg) & mask ? 1 : 0; | ||
336 | ucontrol->value.integer.value[0] = status; | ||
337 | return 0; | ||
338 | } | ||
339 | static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol, | ||
340 | snd_ctl_elem_value_t *ucontrol) | ||
341 | { | ||
342 | unsigned short mask = PRIVATE_VALUE_MASK(kcontrol); | ||
343 | unsigned short reg = PRIVATE_VALUE_REG(kcontrol); | ||
344 | intel8x0_t *chip = snd_kcontrol_chip(kcontrol); | ||
345 | unsigned short new_status = ucontrol->value.integer.value[0] ? mask : ~mask; | ||
346 | return snd_ac97_update_bits(chip->ac97, reg, | ||
347 | mask, new_status); | ||
348 | } | ||
349 | /* | 297 | /* |
350 | * Lowlevel I/O - busmaster | 298 | * Lowlevel I/O - busmaster |
351 | */ | 299 | */ |
@@ -500,6 +448,8 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, | |||
500 | res = 0xffff; | 448 | res = 0xffff; |
501 | } | 449 | } |
502 | } | 450 | } |
451 | if (reg == AC97_GPIO_STATUS) | ||
452 | iagetword(chip, 0); /* clear semaphore */ | ||
503 | return res; | 453 | return res; |
504 | } | 454 | } |
505 | 455 | ||
@@ -698,21 +648,6 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea | |||
698 | return bytes_to_frames(substream->runtime, ptr); | 648 | return bytes_to_frames(substream->runtime, ptr); |
699 | } | 649 | } |
700 | 650 | ||
701 | static int snd_intel8x0m_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | ||
702 | { | ||
703 | /* hook off/on on start/stop */ | ||
704 | /* Moved this to mixer control */ | ||
705 | switch (cmd) { | ||
706 | case SNDRV_PCM_TRIGGER_START: | ||
707 | break; | ||
708 | case SNDRV_PCM_TRIGGER_STOP: | ||
709 | break; | ||
710 | default: | ||
711 | return -EINVAL; | ||
712 | } | ||
713 | return snd_intel8x0_pcm_trigger(substream,cmd); | ||
714 | } | ||
715 | |||
716 | static int snd_intel8x0m_pcm_prepare(snd_pcm_substream_t * substream) | 651 | static int snd_intel8x0m_pcm_prepare(snd_pcm_substream_t * substream) |
717 | { | 652 | { |
718 | intel8x0_t *chip = snd_pcm_substream_chip(substream); | 653 | intel8x0_t *chip = snd_pcm_substream_chip(substream); |
@@ -808,7 +743,7 @@ static snd_pcm_ops_t snd_intel8x0m_playback_ops = { | |||
808 | .hw_params = snd_intel8x0_hw_params, | 743 | .hw_params = snd_intel8x0_hw_params, |
809 | .hw_free = snd_intel8x0_hw_free, | 744 | .hw_free = snd_intel8x0_hw_free, |
810 | .prepare = snd_intel8x0m_pcm_prepare, | 745 | .prepare = snd_intel8x0m_pcm_prepare, |
811 | .trigger = snd_intel8x0m_pcm_trigger, | 746 | .trigger = snd_intel8x0_pcm_trigger, |
812 | .pointer = snd_intel8x0_pcm_pointer, | 747 | .pointer = snd_intel8x0_pcm_pointer, |
813 | }; | 748 | }; |
814 | 749 | ||
@@ -819,7 +754,7 @@ static snd_pcm_ops_t snd_intel8x0m_capture_ops = { | |||
819 | .hw_params = snd_intel8x0_hw_params, | 754 | .hw_params = snd_intel8x0_hw_params, |
820 | .hw_free = snd_intel8x0_hw_free, | 755 | .hw_free = snd_intel8x0_hw_free, |
821 | .prepare = snd_intel8x0m_pcm_prepare, | 756 | .prepare = snd_intel8x0m_pcm_prepare, |
822 | .trigger = snd_intel8x0m_pcm_trigger, | 757 | .trigger = snd_intel8x0_pcm_trigger, |
823 | .pointer = snd_intel8x0_pcm_pointer, | 758 | .pointer = snd_intel8x0_pcm_pointer, |
824 | }; | 759 | }; |
825 | 760 | ||
@@ -947,7 +882,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock) | |||
947 | ac97_t *x97; | 882 | ac97_t *x97; |
948 | int err; | 883 | int err; |
949 | unsigned int glob_sta = 0; | 884 | unsigned int glob_sta = 0; |
950 | unsigned int idx; | ||
951 | static ac97_bus_ops_t ops = { | 885 | static ac97_bus_ops_t ops = { |
952 | .write = snd_intel8x0_codec_write, | 886 | .write = snd_intel8x0_codec_write, |
953 | .read = snd_intel8x0_codec_read, | 887 | .read = snd_intel8x0_codec_read, |
@@ -983,10 +917,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock) | |||
983 | chip->ichd[ICHD_MDMIN].ac97 = x97; | 917 | chip->ichd[ICHD_MDMIN].ac97 = x97; |
984 | chip->ichd[ICHD_MDMOUT].ac97 = x97; | 918 | chip->ichd[ICHD_MDMOUT].ac97 = x97; |
985 | } | 919 | } |
986 | for (idx = 0; idx < ARRAY_SIZE(snd_intel8x0m_mixer_switches); idx++) { | ||
987 | if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_intel8x0m_mixer_switches[idx], chip))) < 0) | ||
988 | goto __err; | ||
989 | } | ||
990 | 920 | ||
991 | chip->in_ac97_init = 0; | 921 | chip->in_ac97_init = 0; |
992 | return 0; | 922 | return 0; |
@@ -1450,7 +1380,7 @@ static struct pci_driver driver = { | |||
1450 | 1380 | ||
1451 | static int __init alsa_card_intel8x0m_init(void) | 1381 | static int __init alsa_card_intel8x0m_init(void) |
1452 | { | 1382 | { |
1453 | return pci_module_init(&driver); | 1383 | return pci_register_driver(&driver); |
1454 | } | 1384 | } |
1455 | 1385 | ||
1456 | static void __exit alsa_card_intel8x0m_exit(void) | 1386 | static void __exit alsa_card_intel8x0m_exit(void) |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index bb1de2008176..79d8eda54f0d 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -2541,7 +2541,7 @@ static struct pci_driver driver = { | |||
2541 | 2541 | ||
2542 | static int __init alsa_card_korg1212_init(void) | 2542 | static int __init alsa_card_korg1212_init(void) |
2543 | { | 2543 | { |
2544 | return pci_module_init(&driver); | 2544 | return pci_register_driver(&driver); |
2545 | } | 2545 | } |
2546 | 2546 | ||
2547 | static void __exit alsa_card_korg1212_exit(void) | 2547 | static void __exit alsa_card_korg1212_exit(void) |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 2cf33083d7cc..39b5e7db1543 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -779,6 +779,12 @@ struct m3_quirk { | |||
779 | (e.g. for IrDA on Dell Inspirons) */ | 779 | (e.g. for IrDA on Dell Inspirons) */ |
780 | }; | 780 | }; |
781 | 781 | ||
782 | struct m3_hv_quirk { | ||
783 | u16 vendor, device, subsystem_vendor, subsystem_device; | ||
784 | u32 config; /* ALLEGRO_CONFIG hardware volume bits */ | ||
785 | int is_omnibook; /* Do HP OmniBook GPIO magic? */ | ||
786 | }; | ||
787 | |||
782 | struct m3_list { | 788 | struct m3_list { |
783 | int curlen; | 789 | int curlen; |
784 | int mem_addr; | 790 | int mem_addr; |
@@ -828,6 +834,7 @@ struct snd_m3 { | |||
828 | 834 | ||
829 | struct pci_dev *pci; | 835 | struct pci_dev *pci; |
830 | struct m3_quirk *quirk; | 836 | struct m3_quirk *quirk; |
837 | struct m3_hv_quirk *hv_quirk; | ||
831 | 838 | ||
832 | int dacs_active; | 839 | int dacs_active; |
833 | int timer_users; | 840 | int timer_users; |
@@ -851,6 +858,11 @@ struct snd_m3 { | |||
851 | m3_dma_t *substreams; | 858 | m3_dma_t *substreams; |
852 | 859 | ||
853 | spinlock_t reg_lock; | 860 | spinlock_t reg_lock; |
861 | spinlock_t ac97_lock; | ||
862 | |||
863 | snd_kcontrol_t *master_switch; | ||
864 | snd_kcontrol_t *master_volume; | ||
865 | struct tasklet_struct hwvol_tq; | ||
854 | 866 | ||
855 | #ifdef CONFIG_PM | 867 | #ifdef CONFIG_PM |
856 | u16 *suspend_mem; | 868 | u16 *suspend_mem; |
@@ -968,32 +980,92 @@ static struct m3_quirk m3_quirk_list[] = { | |||
968 | { NULL } | 980 | { NULL } |
969 | }; | 981 | }; |
970 | 982 | ||
983 | /* These values came from the Windows driver. */ | ||
984 | static struct m3_hv_quirk m3_hv_quirk_list[] = { | ||
985 | /* Allegro chips */ | ||
986 | { 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
987 | { 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
988 | { 0x125D, 0x1988, 0x0E11, 0xB112, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
989 | { 0x125D, 0x1988, 0x0E11, 0xB114, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
990 | { 0x125D, 0x1988, 0x103C, 0x0012, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
991 | { 0x125D, 0x1988, 0x103C, 0x0018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
992 | { 0x125D, 0x1988, 0x103C, 0x001C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
993 | { 0x125D, 0x1988, 0x103C, 0x001D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
994 | { 0x125D, 0x1988, 0x103C, 0x001E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
995 | { 0x125D, 0x1988, 0x107B, 0x3350, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
996 | { 0x125D, 0x1988, 0x10F7, 0x8338, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
997 | { 0x125D, 0x1988, 0x10F7, 0x833C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
998 | { 0x125D, 0x1988, 0x10F7, 0x833D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
999 | { 0x125D, 0x1988, 0x10F7, 0x833E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1000 | { 0x125D, 0x1988, 0x10F7, 0x833F, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1001 | { 0x125D, 0x1988, 0x13BD, 0x1018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1002 | { 0x125D, 0x1988, 0x13BD, 0x1019, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1003 | { 0x125D, 0x1988, 0x13BD, 0x101A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1004 | { 0x125D, 0x1988, 0x14FF, 0x0F03, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1005 | { 0x125D, 0x1988, 0x14FF, 0x0F04, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1006 | { 0x125D, 0x1988, 0x14FF, 0x0F05, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1007 | { 0x125D, 0x1988, 0x156D, 0xB400, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1008 | { 0x125D, 0x1988, 0x156D, 0xB795, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1009 | { 0x125D, 0x1988, 0x156D, 0xB797, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1010 | { 0x125D, 0x1988, 0x156D, 0xC700, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, | ||
1011 | { 0x125D, 0x1988, 0x1033, 0x80F1, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1012 | { 0x125D, 0x1988, 0x103C, 0x001A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, /* HP OmniBook 6100 */ | ||
1013 | { 0x125D, 0x1988, 0x107B, 0x340A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1014 | { 0x125D, 0x1988, 0x107B, 0x3450, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1015 | { 0x125D, 0x1988, 0x109F, 0x3134, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1016 | { 0x125D, 0x1988, 0x109F, 0x3161, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1017 | { 0x125D, 0x1988, 0x144D, 0x3280, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1018 | { 0x125D, 0x1988, 0x144D, 0x3281, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1019 | { 0x125D, 0x1988, 0x144D, 0xC002, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1020 | { 0x125D, 0x1988, 0x144D, 0xC003, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1021 | { 0x125D, 0x1988, 0x1509, 0x1740, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1022 | { 0x125D, 0x1988, 0x1610, 0x0010, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, | ||
1023 | { 0x125D, 0x1988, 0x1042, 0x1042, HV_CTRL_ENABLE, 0 }, | ||
1024 | { 0x125D, 0x1988, 0x107B, 0x9500, HV_CTRL_ENABLE, 0 }, | ||
1025 | { 0x125D, 0x1988, 0x14FF, 0x0F06, HV_CTRL_ENABLE, 0 }, | ||
1026 | { 0x125D, 0x1988, 0x1558, 0x8586, HV_CTRL_ENABLE, 0 }, | ||
1027 | { 0x125D, 0x1988, 0x161F, 0x2011, HV_CTRL_ENABLE, 0 }, | ||
1028 | /* Maestro3 chips */ | ||
1029 | { 0x125D, 0x1998, 0x103C, 0x000E, HV_CTRL_ENABLE, 0 }, | ||
1030 | { 0x125D, 0x1998, 0x103C, 0x0010, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 6000 */ | ||
1031 | { 0x125D, 0x1998, 0x103C, 0x0011, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 500 */ | ||
1032 | { 0x125D, 0x1998, 0x103C, 0x001B, HV_CTRL_ENABLE, 0 }, | ||
1033 | { 0x125D, 0x1998, 0x104D, 0x80A6, HV_CTRL_ENABLE, 0 }, | ||
1034 | { 0x125D, 0x1998, 0x104D, 0x80AA, HV_CTRL_ENABLE, 0 }, | ||
1035 | { 0x125D, 0x1998, 0x107B, 0x5300, HV_CTRL_ENABLE, 0 }, | ||
1036 | { 0x125D, 0x1998, 0x110A, 0x1998, HV_CTRL_ENABLE, 0 }, | ||
1037 | { 0x125D, 0x1998, 0x13BD, 0x1015, HV_CTRL_ENABLE, 0 }, | ||
1038 | { 0x125D, 0x1998, 0x13BD, 0x101C, HV_CTRL_ENABLE, 0 }, | ||
1039 | { 0x125D, 0x1998, 0x13BD, 0x1802, HV_CTRL_ENABLE, 0 }, | ||
1040 | { 0x125D, 0x1998, 0x1599, 0x0715, HV_CTRL_ENABLE, 0 }, | ||
1041 | { 0x125D, 0x1998, 0x5643, 0x5643, HV_CTRL_ENABLE, 0 }, | ||
1042 | { 0x125D, 0x199A, 0x144D, 0x3260, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, | ||
1043 | { 0x125D, 0x199A, 0x144D, 0x3261, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, | ||
1044 | { 0x125D, 0x199A, 0x144D, 0xC000, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, | ||
1045 | { 0x125D, 0x199A, 0x144D, 0xC001, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, | ||
1046 | { 0 } | ||
1047 | }; | ||
971 | 1048 | ||
972 | /* | 1049 | /* |
973 | * lowlevel functions | 1050 | * lowlevel functions |
974 | */ | 1051 | */ |
975 | 1052 | ||
976 | #define big_mdelay(msec) do {\ | 1053 | static inline void snd_m3_outw(m3_t *chip, u16 value, unsigned long reg) |
977 | set_current_state(TASK_UNINTERRUPTIBLE);\ | ||
978 | schedule_timeout(((msec) * HZ) / 1000);\ | ||
979 | } while (0) | ||
980 | |||
981 | inline static void snd_m3_outw(m3_t *chip, u16 value, unsigned long reg) | ||
982 | { | 1054 | { |
983 | outw(value, chip->iobase + reg); | 1055 | outw(value, chip->iobase + reg); |
984 | } | 1056 | } |
985 | 1057 | ||
986 | inline static u16 snd_m3_inw(m3_t *chip, unsigned long reg) | 1058 | static inline u16 snd_m3_inw(m3_t *chip, unsigned long reg) |
987 | { | 1059 | { |
988 | return inw(chip->iobase + reg); | 1060 | return inw(chip->iobase + reg); |
989 | } | 1061 | } |
990 | 1062 | ||
991 | inline static void snd_m3_outb(m3_t *chip, u8 value, unsigned long reg) | 1063 | static inline void snd_m3_outb(m3_t *chip, u8 value, unsigned long reg) |
992 | { | 1064 | { |
993 | outb(value, chip->iobase + reg); | 1065 | outb(value, chip->iobase + reg); |
994 | } | 1066 | } |
995 | 1067 | ||
996 | inline static u8 snd_m3_inb(m3_t *chip, unsigned long reg) | 1068 | static inline u8 snd_m3_inb(m3_t *chip, unsigned long reg) |
997 | { | 1069 | { |
998 | return inb(chip->iobase + reg); | 1070 | return inb(chip->iobase + reg); |
999 | } | 1071 | } |
@@ -1019,7 +1091,7 @@ static void snd_m3_assp_write(m3_t *chip, u16 region, u16 index, u16 data) | |||
1019 | static void snd_m3_assp_halt(m3_t *chip) | 1091 | static void snd_m3_assp_halt(m3_t *chip) |
1020 | { | 1092 | { |
1021 | chip->reset_state = snd_m3_inb(chip, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK; | 1093 | chip->reset_state = snd_m3_inb(chip, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK; |
1022 | big_mdelay(10); | 1094 | msleep(10); |
1023 | snd_m3_outb(chip, chip->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B); | 1095 | snd_m3_outb(chip, chip->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B); |
1024 | } | 1096 | } |
1025 | 1097 | ||
@@ -1565,6 +1637,68 @@ static void snd_m3_update_ptr(m3_t *chip, m3_dma_t *s) | |||
1565 | } | 1637 | } |
1566 | } | 1638 | } |
1567 | 1639 | ||
1640 | static void snd_m3_update_hw_volume(unsigned long private_data) | ||
1641 | { | ||
1642 | m3_t *chip = (m3_t *) private_data; | ||
1643 | int x, val; | ||
1644 | unsigned long flags; | ||
1645 | |||
1646 | /* Figure out which volume control button was pushed, | ||
1647 | based on differences from the default register | ||
1648 | values. */ | ||
1649 | x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee; | ||
1650 | |||
1651 | /* Reset the volume control registers. */ | ||
1652 | outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE); | ||
1653 | outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE); | ||
1654 | outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER); | ||
1655 | outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER); | ||
1656 | |||
1657 | if (!chip->master_switch || !chip->master_volume) | ||
1658 | return; | ||
1659 | |||
1660 | /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ | ||
1661 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
1662 | |||
1663 | val = chip->ac97->regs[AC97_MASTER_VOL]; | ||
1664 | switch (x) { | ||
1665 | case 0x88: | ||
1666 | /* mute */ | ||
1667 | val ^= 0x8000; | ||
1668 | chip->ac97->regs[AC97_MASTER_VOL] = val; | ||
1669 | outw(val, chip->iobase + CODEC_DATA); | ||
1670 | outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | ||
1671 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1672 | &chip->master_switch->id); | ||
1673 | break; | ||
1674 | case 0xaa: | ||
1675 | /* volume up */ | ||
1676 | if ((val & 0x7f) > 0) | ||
1677 | val--; | ||
1678 | if ((val & 0x7f00) > 0) | ||
1679 | val -= 0x0100; | ||
1680 | chip->ac97->regs[AC97_MASTER_VOL] = val; | ||
1681 | outw(val, chip->iobase + CODEC_DATA); | ||
1682 | outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | ||
1683 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1684 | &chip->master_volume->id); | ||
1685 | break; | ||
1686 | case 0x66: | ||
1687 | /* volume down */ | ||
1688 | if ((val & 0x7f) < 0x1f) | ||
1689 | val++; | ||
1690 | if ((val & 0x7f00) < 0x1f00) | ||
1691 | val += 0x0100; | ||
1692 | chip->ac97->regs[AC97_MASTER_VOL] = val; | ||
1693 | outw(val, chip->iobase + CODEC_DATA); | ||
1694 | outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | ||
1695 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1696 | &chip->master_volume->id); | ||
1697 | break; | ||
1698 | } | ||
1699 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | ||
1700 | } | ||
1701 | |||
1568 | static irqreturn_t | 1702 | static irqreturn_t |
1569 | snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 1703 | snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
1570 | { | 1704 | { |
@@ -1576,7 +1710,10 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1576 | 1710 | ||
1577 | if (status == 0xff) | 1711 | if (status == 0xff) |
1578 | return IRQ_NONE; | 1712 | return IRQ_NONE; |
1579 | 1713 | ||
1714 | if (status & HV_INT_PENDING) | ||
1715 | tasklet_hi_schedule(&chip->hwvol_tq); | ||
1716 | |||
1580 | /* | 1717 | /* |
1581 | * ack an assp int if its running | 1718 | * ack an assp int if its running |
1582 | * and has an int pending | 1719 | * and has an int pending |
@@ -1605,7 +1742,7 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1605 | #endif | 1742 | #endif |
1606 | 1743 | ||
1607 | /* ack ints */ | 1744 | /* ack ints */ |
1608 | snd_m3_outw(chip, HOST_INT_STATUS, status); | 1745 | outb(status, chip->iobase + HOST_INT_STATUS); |
1609 | 1746 | ||
1610 | return IRQ_HANDLED; | 1747 | return IRQ_HANDLED; |
1611 | } | 1748 | } |
@@ -1842,24 +1979,32 @@ static unsigned short | |||
1842 | snd_m3_ac97_read(ac97_t *ac97, unsigned short reg) | 1979 | snd_m3_ac97_read(ac97_t *ac97, unsigned short reg) |
1843 | { | 1980 | { |
1844 | m3_t *chip = ac97->private_data; | 1981 | m3_t *chip = ac97->private_data; |
1982 | unsigned long flags; | ||
1983 | unsigned short data; | ||
1845 | 1984 | ||
1846 | if (snd_m3_ac97_wait(chip)) | 1985 | if (snd_m3_ac97_wait(chip)) |
1847 | return 0xffff; | 1986 | return 0xffff; |
1987 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
1848 | snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); | 1988 | snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); |
1849 | if (snd_m3_ac97_wait(chip)) | 1989 | if (snd_m3_ac97_wait(chip)) |
1850 | return 0xffff; | 1990 | return 0xffff; |
1851 | return snd_m3_inw(chip, CODEC_DATA); | 1991 | data = snd_m3_inw(chip, CODEC_DATA); |
1992 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | ||
1993 | return data; | ||
1852 | } | 1994 | } |
1853 | 1995 | ||
1854 | static void | 1996 | static void |
1855 | snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) | 1997 | snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) |
1856 | { | 1998 | { |
1857 | m3_t *chip = ac97->private_data; | 1999 | m3_t *chip = ac97->private_data; |
2000 | unsigned long flags; | ||
1858 | 2001 | ||
1859 | if (snd_m3_ac97_wait(chip)) | 2002 | if (snd_m3_ac97_wait(chip)) |
1860 | return; | 2003 | return; |
2004 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
1861 | snd_m3_outw(chip, val, CODEC_DATA); | 2005 | snd_m3_outw(chip, val, CODEC_DATA); |
1862 | snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); | 2006 | snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); |
2007 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | ||
1863 | } | 2008 | } |
1864 | 2009 | ||
1865 | 2010 | ||
@@ -1958,9 +2103,9 @@ static void snd_m3_ac97_reset(m3_t *chip) | |||
1958 | */ | 2103 | */ |
1959 | tmp = inw(io + RING_BUS_CTRL_A); | 2104 | tmp = inw(io + RING_BUS_CTRL_A); |
1960 | outw(RAC_SDFS_ENABLE|LAC_SDFS_ENABLE, io + RING_BUS_CTRL_A); | 2105 | outw(RAC_SDFS_ENABLE|LAC_SDFS_ENABLE, io + RING_BUS_CTRL_A); |
1961 | big_mdelay(20); | 2106 | msleep(20); |
1962 | outw(tmp, io + RING_BUS_CTRL_A); | 2107 | outw(tmp, io + RING_BUS_CTRL_A); |
1963 | big_mdelay(50); | 2108 | msleep(50); |
1964 | #endif | 2109 | #endif |
1965 | } | 2110 | } |
1966 | 2111 | ||
@@ -1968,6 +2113,7 @@ static int __devinit snd_m3_mixer(m3_t *chip) | |||
1968 | { | 2113 | { |
1969 | ac97_bus_t *pbus; | 2114 | ac97_bus_t *pbus; |
1970 | ac97_template_t ac97; | 2115 | ac97_template_t ac97; |
2116 | snd_ctl_elem_id_t id; | ||
1971 | int err; | 2117 | int err; |
1972 | static ac97_bus_ops_t ops = { | 2118 | static ac97_bus_ops_t ops = { |
1973 | .write = snd_m3_ac97_write, | 2119 | .write = snd_m3_ac97_write, |
@@ -1988,6 +2134,15 @@ static int __devinit snd_m3_mixer(m3_t *chip) | |||
1988 | schedule_timeout(HZ / 10); | 2134 | schedule_timeout(HZ / 10); |
1989 | snd_ac97_write(chip->ac97, AC97_PCM, 0); | 2135 | snd_ac97_write(chip->ac97, AC97_PCM, 0); |
1990 | 2136 | ||
2137 | memset(&id, 0, sizeof(id)); | ||
2138 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
2139 | strcpy(id.name, "Master Playback Switch"); | ||
2140 | chip->master_switch = snd_ctl_find_id(chip->card, &id); | ||
2141 | memset(&id, 0, sizeof(id)); | ||
2142 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
2143 | strcpy(id.name, "Master Playback Volume"); | ||
2144 | chip->master_volume = snd_ctl_find_id(chip->card, &id); | ||
2145 | |||
1991 | return 0; | 2146 | return 0; |
1992 | } | 2147 | } |
1993 | 2148 | ||
@@ -2293,6 +2448,7 @@ static int | |||
2293 | snd_m3_chip_init(m3_t *chip) | 2448 | snd_m3_chip_init(m3_t *chip) |
2294 | { | 2449 | { |
2295 | struct pci_dev *pcidev = chip->pci; | 2450 | struct pci_dev *pcidev = chip->pci; |
2451 | unsigned long io = chip->iobase; | ||
2296 | u32 n; | 2452 | u32 n; |
2297 | u16 w; | 2453 | u16 w; |
2298 | u8 t; /* makes as much sense as 'n', no? */ | 2454 | u8 t; /* makes as much sense as 'n', no? */ |
@@ -2303,8 +2459,27 @@ snd_m3_chip_init(m3_t *chip) | |||
2303 | DISABLE_LEGACY); | 2459 | DISABLE_LEGACY); |
2304 | pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); | 2460 | pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); |
2305 | 2461 | ||
2462 | if (chip->hv_quirk && chip->hv_quirk->is_omnibook) { | ||
2463 | /* | ||
2464 | * Volume buttons on some HP OmniBook laptops don't work | ||
2465 | * correctly. This makes them work for the most part. | ||
2466 | * | ||
2467 | * Volume up and down buttons on the laptop side work. | ||
2468 | * Fn+cursor_up (volme up) works. | ||
2469 | * Fn+cursor_down (volume down) doesn't work. | ||
2470 | * Fn+F7 (mute) works acts as volume up. | ||
2471 | */ | ||
2472 | outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK); | ||
2473 | outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION); | ||
2474 | outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA); | ||
2475 | outw(0xffff, io + GPIO_MASK); | ||
2476 | } | ||
2306 | pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); | 2477 | pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); |
2307 | n &= REDUCED_DEBOUNCE; | 2478 | n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD); |
2479 | if (chip->hv_quirk) | ||
2480 | n |= chip->hv_quirk->config; | ||
2481 | /* For some reason we must always use reduced debounce. */ | ||
2482 | n |= REDUCED_DEBOUNCE; | ||
2308 | n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; | 2483 | n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; |
2309 | pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n); | 2484 | pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n); |
2310 | 2485 | ||
@@ -2332,6 +2507,12 @@ snd_m3_chip_init(m3_t *chip) | |||
2332 | 2507 | ||
2333 | outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B); | 2508 | outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B); |
2334 | 2509 | ||
2510 | outb(0x00, io + HARDWARE_VOL_CTRL); | ||
2511 | outb(0x88, io + SHADOW_MIX_REG_VOICE); | ||
2512 | outb(0x88, io + HW_VOL_COUNTER_VOICE); | ||
2513 | outb(0x88, io + SHADOW_MIX_REG_MASTER); | ||
2514 | outb(0x88, io + HW_VOL_COUNTER_MASTER); | ||
2515 | |||
2335 | return 0; | 2516 | return 0; |
2336 | } | 2517 | } |
2337 | 2518 | ||
@@ -2339,9 +2520,13 @@ static void | |||
2339 | snd_m3_enable_ints(m3_t *chip) | 2520 | snd_m3_enable_ints(m3_t *chip) |
2340 | { | 2521 | { |
2341 | unsigned long io = chip->iobase; | 2522 | unsigned long io = chip->iobase; |
2523 | unsigned short val; | ||
2342 | 2524 | ||
2343 | /* TODO: MPU401 not supported yet */ | 2525 | /* TODO: MPU401 not supported yet */ |
2344 | outw(ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL); | 2526 | val = ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/; |
2527 | if (chip->hv_quirk && (chip->hv_quirk->config & HV_CTRL_ENABLE)) | ||
2528 | val |= HV_INT_ENABLE; | ||
2529 | outw(val, io + HOST_INT_CTRL); | ||
2345 | outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, | 2530 | outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, |
2346 | io + ASSP_CONTROL_C); | 2531 | io + ASSP_CONTROL_C); |
2347 | } | 2532 | } |
@@ -2367,7 +2552,7 @@ static int snd_m3_free(m3_t *chip) | |||
2367 | kfree(chip->substreams); | 2552 | kfree(chip->substreams); |
2368 | } | 2553 | } |
2369 | if (chip->iobase) { | 2554 | if (chip->iobase) { |
2370 | snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */ | 2555 | outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */ |
2371 | } | 2556 | } |
2372 | 2557 | ||
2373 | #ifdef CONFIG_PM | 2558 | #ifdef CONFIG_PM |
@@ -2403,7 +2588,7 @@ static int m3_suspend(snd_card_t *card, pm_message_t state) | |||
2403 | snd_pcm_suspend_all(chip->pcm); | 2588 | snd_pcm_suspend_all(chip->pcm); |
2404 | snd_ac97_suspend(chip->ac97); | 2589 | snd_ac97_suspend(chip->ac97); |
2405 | 2590 | ||
2406 | big_mdelay(10); /* give the assp a chance to idle.. */ | 2591 | msleep(10); /* give the assp a chance to idle.. */ |
2407 | 2592 | ||
2408 | snd_m3_assp_halt(chip); | 2593 | snd_m3_assp_halt(chip); |
2409 | 2594 | ||
@@ -2486,7 +2671,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, | |||
2486 | m3_t *chip; | 2671 | m3_t *chip; |
2487 | int i, err; | 2672 | int i, err; |
2488 | struct m3_quirk *quirk; | 2673 | struct m3_quirk *quirk; |
2489 | u16 subsystem_vendor, subsystem_device; | 2674 | struct m3_hv_quirk *hv_quirk; |
2490 | static snd_device_ops_t ops = { | 2675 | static snd_device_ops_t ops = { |
2491 | .dev_free = snd_m3_dev_free, | 2676 | .dev_free = snd_m3_dev_free, |
2492 | }; | 2677 | }; |
@@ -2511,6 +2696,8 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, | |||
2511 | } | 2696 | } |
2512 | 2697 | ||
2513 | spin_lock_init(&chip->reg_lock); | 2698 | spin_lock_init(&chip->reg_lock); |
2699 | spin_lock_init(&chip->ac97_lock); | ||
2700 | |||
2514 | switch (pci->device) { | 2701 | switch (pci->device) { |
2515 | case PCI_DEVICE_ID_ESS_ALLEGRO: | 2702 | case PCI_DEVICE_ID_ESS_ALLEGRO: |
2516 | case PCI_DEVICE_ID_ESS_ALLEGRO_1: | 2703 | case PCI_DEVICE_ID_ESS_ALLEGRO_1: |
@@ -2524,18 +2711,25 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, | |||
2524 | chip->pci = pci; | 2711 | chip->pci = pci; |
2525 | chip->irq = -1; | 2712 | chip->irq = -1; |
2526 | 2713 | ||
2527 | pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); | ||
2528 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device); | ||
2529 | |||
2530 | for (quirk = m3_quirk_list; quirk->vendor; quirk++) { | 2714 | for (quirk = m3_quirk_list; quirk->vendor; quirk++) { |
2531 | if (subsystem_vendor == quirk->vendor && | 2715 | if (pci->subsystem_vendor == quirk->vendor && |
2532 | subsystem_device == quirk->device) { | 2716 | pci->subsystem_device == quirk->device) { |
2533 | printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name); | 2717 | printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name); |
2534 | chip->quirk = quirk; | 2718 | chip->quirk = quirk; |
2535 | break; | 2719 | break; |
2536 | } | 2720 | } |
2537 | } | 2721 | } |
2538 | 2722 | ||
2723 | for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) { | ||
2724 | if (pci->vendor == hv_quirk->vendor && | ||
2725 | pci->device == hv_quirk->device && | ||
2726 | pci->subsystem_vendor == hv_quirk->subsystem_vendor && | ||
2727 | pci->subsystem_device == hv_quirk->subsystem_device) { | ||
2728 | chip->hv_quirk = hv_quirk; | ||
2729 | break; | ||
2730 | } | ||
2731 | } | ||
2732 | |||
2539 | chip->external_amp = enable_amp; | 2733 | chip->external_amp = enable_amp; |
2540 | if (amp_gpio >= 0 && amp_gpio <= 0x0f) | 2734 | if (amp_gpio >= 0 && amp_gpio <= 0x0f) |
2541 | chip->amp_gpio = amp_gpio; | 2735 | chip->amp_gpio = amp_gpio; |
@@ -2572,6 +2766,8 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, | |||
2572 | snd_m3_assp_init(chip); | 2766 | snd_m3_assp_init(chip); |
2573 | snd_m3_amp_enable(chip, 1); | 2767 | snd_m3_amp_enable(chip, 1); |
2574 | 2768 | ||
2769 | tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); | ||
2770 | |||
2575 | if (request_irq(pci->irq, snd_m3_interrupt, SA_INTERRUPT|SA_SHIRQ, | 2771 | if (request_irq(pci->irq, snd_m3_interrupt, SA_INTERRUPT|SA_SHIRQ, |
2576 | card->driver, (void *)chip)) { | 2772 | card->driver, (void *)chip)) { |
2577 | snd_printk("unable to grab IRQ %d\n", pci->irq); | 2773 | snd_printk("unable to grab IRQ %d\n", pci->irq); |
@@ -2702,7 +2898,7 @@ static struct pci_driver driver = { | |||
2702 | 2898 | ||
2703 | static int __init alsa_card_m3_init(void) | 2899 | static int __init alsa_card_m3_init(void) |
2704 | { | 2900 | { |
2705 | return pci_module_init(&driver); | 2901 | return pci_register_driver(&driver); |
2706 | } | 2902 | } |
2707 | 2903 | ||
2708 | static void __exit alsa_card_m3_exit(void) | 2904 | static void __exit alsa_card_m3_exit(void) |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 65bb0f47af2c..6c868d913634 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -445,9 +445,9 @@ static int snd_mixart_trigger(snd_pcm_substream_t *subs, int cmd) | |||
445 | 445 | ||
446 | static int mixart_sync_nonblock_events(mixart_mgr_t *mgr) | 446 | static int mixart_sync_nonblock_events(mixart_mgr_t *mgr) |
447 | { | 447 | { |
448 | int timeout = HZ; | 448 | unsigned long timeout = jiffies + HZ; |
449 | while (atomic_read(&mgr->msg_processed) > 0) { | 449 | while (atomic_read(&mgr->msg_processed) > 0) { |
450 | if (! timeout--) { | 450 | if (time_after(jiffies, timeout)) { |
451 | snd_printk(KERN_ERR "mixart: cannot process nonblock events!\n"); | 451 | snd_printk(KERN_ERR "mixart: cannot process nonblock events!\n"); |
452 | return -EBUSY; | 452 | return -EBUSY; |
453 | } | 453 | } |
@@ -1431,7 +1431,7 @@ static struct pci_driver driver = { | |||
1431 | 1431 | ||
1432 | static int __init alsa_card_mixart_init(void) | 1432 | static int __init alsa_card_mixart_init(void) |
1433 | { | 1433 | { |
1434 | return pci_module_init(&driver); | 1434 | return pci_register_driver(&driver); |
1435 | } | 1435 | } |
1436 | 1436 | ||
1437 | static void __exit alsa_card_mixart_exit(void) | 1437 | static void __exit alsa_card_mixart_exit(void) |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 356fbeac6f9e..7eb20b8f89f6 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -285,43 +285,43 @@ MODULE_DEVICE_TABLE(pci, snd_nm256_ids); | |||
285 | * lowlvel stuffs | 285 | * lowlvel stuffs |
286 | */ | 286 | */ |
287 | 287 | ||
288 | inline static u8 | 288 | static inline u8 |
289 | snd_nm256_readb(nm256_t *chip, int offset) | 289 | snd_nm256_readb(nm256_t *chip, int offset) |
290 | { | 290 | { |
291 | return readb(chip->cport + offset); | 291 | return readb(chip->cport + offset); |
292 | } | 292 | } |
293 | 293 | ||
294 | inline static u16 | 294 | static inline u16 |
295 | snd_nm256_readw(nm256_t *chip, int offset) | 295 | snd_nm256_readw(nm256_t *chip, int offset) |
296 | { | 296 | { |
297 | return readw(chip->cport + offset); | 297 | return readw(chip->cport + offset); |
298 | } | 298 | } |
299 | 299 | ||
300 | inline static u32 | 300 | static inline u32 |
301 | snd_nm256_readl(nm256_t *chip, int offset) | 301 | snd_nm256_readl(nm256_t *chip, int offset) |
302 | { | 302 | { |
303 | return readl(chip->cport + offset); | 303 | return readl(chip->cport + offset); |
304 | } | 304 | } |
305 | 305 | ||
306 | inline static void | 306 | static inline void |
307 | snd_nm256_writeb(nm256_t *chip, int offset, u8 val) | 307 | snd_nm256_writeb(nm256_t *chip, int offset, u8 val) |
308 | { | 308 | { |
309 | writeb(val, chip->cport + offset); | 309 | writeb(val, chip->cport + offset); |
310 | } | 310 | } |
311 | 311 | ||
312 | inline static void | 312 | static inline void |
313 | snd_nm256_writew(nm256_t *chip, int offset, u16 val) | 313 | snd_nm256_writew(nm256_t *chip, int offset, u16 val) |
314 | { | 314 | { |
315 | writew(val, chip->cport + offset); | 315 | writew(val, chip->cport + offset); |
316 | } | 316 | } |
317 | 317 | ||
318 | inline static void | 318 | static inline void |
319 | snd_nm256_writel(nm256_t *chip, int offset, u32 val) | 319 | snd_nm256_writel(nm256_t *chip, int offset, u32 val) |
320 | { | 320 | { |
321 | writel(val, chip->cport + offset); | 321 | writel(val, chip->cport + offset); |
322 | } | 322 | } |
323 | 323 | ||
324 | inline static void | 324 | static inline void |
325 | snd_nm256_write_buffer(nm256_t *chip, void *src, int offset, int size) | 325 | snd_nm256_write_buffer(nm256_t *chip, void *src, int offset, int size) |
326 | { | 326 | { |
327 | offset -= chip->buffer_start; | 327 | offset -= chip->buffer_start; |
@@ -926,7 +926,7 @@ snd_nm256_init_chip(nm256_t *chip) | |||
926 | } | 926 | } |
927 | 927 | ||
928 | 928 | ||
929 | inline static void | 929 | static inline void |
930 | snd_nm256_intr_check(nm256_t *chip) | 930 | snd_nm256_intr_check(nm256_t *chip) |
931 | { | 931 | { |
932 | if (chip->badintrcount++ > 1000) { | 932 | if (chip->badintrcount++ > 1000) { |
@@ -1645,7 +1645,7 @@ static struct pci_driver driver = { | |||
1645 | 1645 | ||
1646 | static int __init alsa_card_nm256_init(void) | 1646 | static int __init alsa_card_nm256_init(void) |
1647 | { | 1647 | { |
1648 | return pci_module_init(&driver); | 1648 | return pci_register_driver(&driver); |
1649 | } | 1649 | } |
1650 | 1650 | ||
1651 | static void __exit alsa_card_nm256_exit(void) | 1651 | static void __exit alsa_card_nm256_exit(void) |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index b96acd5a57db..b7b554df6705 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -2031,7 +2031,7 @@ static struct pci_driver driver = { | |||
2031 | 2031 | ||
2032 | static int __init alsa_card_rme32_init(void) | 2032 | static int __init alsa_card_rme32_init(void) |
2033 | { | 2033 | { |
2034 | return pci_module_init(&driver); | 2034 | return pci_register_driver(&driver); |
2035 | } | 2035 | } |
2036 | 2036 | ||
2037 | static void __exit alsa_card_rme32_exit(void) | 2037 | static void __exit alsa_card_rme32_exit(void) |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 8e2666841d21..10c4f45a913c 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -2437,7 +2437,7 @@ static struct pci_driver driver = { | |||
2437 | 2437 | ||
2438 | static int __init alsa_card_rme96_init(void) | 2438 | static int __init alsa_card_rme96_init(void) |
2439 | { | 2439 | { |
2440 | return pci_module_init(&driver); | 2440 | return pci_register_driver(&driver); |
2441 | } | 2441 | } |
2442 | 2442 | ||
2443 | static void __exit alsa_card_rme96_exit(void) | 2443 | static void __exit alsa_card_rme96_exit(void) |
diff --git a/sound/pci/rme9652/Makefile b/sound/pci/rme9652/Makefile index 917374c9cd40..d2c294e136f9 100644 --- a/sound/pci/rme9652/Makefile +++ b/sound/pci/rme9652/Makefile | |||
@@ -5,7 +5,9 @@ | |||
5 | 5 | ||
6 | snd-rme9652-objs := rme9652.o | 6 | snd-rme9652-objs := rme9652.o |
7 | snd-hdsp-objs := hdsp.o | 7 | snd-hdsp-objs := hdsp.o |
8 | snd-hdspm-objs := hdspm.o | ||
8 | 9 | ||
9 | # Toplevel Module Dependency | 10 | # Toplevel Module Dependency |
10 | obj-$(CONFIG_SND_RME9652) += snd-rme9652.o | 11 | obj-$(CONFIG_SND_RME9652) += snd-rme9652.o |
11 | obj-$(CONFIG_SND_HDSP) += snd-hdsp.o | 12 | obj-$(CONFIG_SND_HDSP) += snd-hdsp.o |
13 | obj-$(CONFIG_SND_HDSPM) +=snd-hdspm.o | ||
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 12efbf0fab54..796621de5009 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -445,6 +445,7 @@ struct _hdsp { | |||
445 | u32 control2_register; /* cached value */ | 445 | u32 control2_register; /* cached value */ |
446 | u32 creg_spdif; | 446 | u32 creg_spdif; |
447 | u32 creg_spdif_stream; | 447 | u32 creg_spdif_stream; |
448 | int clock_source_locked; | ||
448 | char *card_name; /* digiface/multiface */ | 449 | char *card_name; /* digiface/multiface */ |
449 | HDSP_IO_Type io_type; /* ditto, but for code use */ | 450 | HDSP_IO_Type io_type; /* ditto, but for code use */ |
450 | unsigned short firmware_rev; | 451 | unsigned short firmware_rev; |
@@ -559,18 +560,22 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer | |||
559 | { | 560 | { |
560 | dmab->dev.type = SNDRV_DMA_TYPE_DEV; | 561 | dmab->dev.type = SNDRV_DMA_TYPE_DEV; |
561 | dmab->dev.dev = snd_dma_pci_data(pci); | 562 | dmab->dev.dev = snd_dma_pci_data(pci); |
562 | if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { | 563 | if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { |
563 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | 564 | if (dmab->bytes >= size) |
564 | size, dmab) < 0) | 565 | return 0; |
565 | return -ENOMEM; | ||
566 | } | 566 | } |
567 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | ||
568 | size, dmab) < 0) | ||
569 | return -ENOMEM; | ||
567 | return 0; | 570 | return 0; |
568 | } | 571 | } |
569 | 572 | ||
570 | static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) | 573 | static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) |
571 | { | 574 | { |
572 | if (dmab->area) | 575 | if (dmab->area) { |
576 | dmab->dev.dev = NULL; /* make it anonymous */ | ||
573 | snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci)); | 577 | snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci)); |
578 | } | ||
574 | } | 579 | } |
575 | 580 | ||
576 | 581 | ||
@@ -674,8 +679,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) { | |||
674 | } | 679 | } |
675 | 680 | ||
676 | if ((1000 / HZ) < 3000) { | 681 | if ((1000 / HZ) < 3000) { |
677 | set_current_state(TASK_UNINTERRUPTIBLE); | 682 | ssleep(3); |
678 | schedule_timeout((3000 * HZ + 999) / 1000); | ||
679 | } else { | 683 | } else { |
680 | mdelay(3000); | 684 | mdelay(3000); |
681 | } | 685 | } |
@@ -2091,6 +2095,34 @@ static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_val | |||
2091 | return change; | 2095 | return change; |
2092 | } | 2096 | } |
2093 | 2097 | ||
2098 | static int snd_hdsp_info_clock_source_lock(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) | ||
2099 | { | ||
2100 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2101 | uinfo->count = 1; | ||
2102 | uinfo->value.integer.min = 0; | ||
2103 | uinfo->value.integer.max = 1; | ||
2104 | return 0; | ||
2105 | } | ||
2106 | |||
2107 | static int snd_hdsp_get_clock_source_lock(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
2108 | { | ||
2109 | hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); | ||
2110 | |||
2111 | ucontrol->value.integer.value[0] = hdsp->clock_source_locked; | ||
2112 | return 0; | ||
2113 | } | ||
2114 | |||
2115 | static int snd_hdsp_put_clock_source_lock(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
2116 | { | ||
2117 | hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); | ||
2118 | int change; | ||
2119 | |||
2120 | change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked; | ||
2121 | if (change) | ||
2122 | hdsp->clock_source_locked = ucontrol->value.integer.value[0]; | ||
2123 | return change; | ||
2124 | } | ||
2125 | |||
2094 | #define HDSP_DA_GAIN(xname, xindex) \ | 2126 | #define HDSP_DA_GAIN(xname, xindex) \ |
2095 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | 2127 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ |
2096 | .name = xname, \ | 2128 | .name = xname, \ |
@@ -3113,6 +3145,15 @@ HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0), | |||
3113 | HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0), | 3145 | HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0), |
3114 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ | 3146 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ |
3115 | HDSP_CLOCK_SOURCE("Sample Clock Source", 0), | 3147 | HDSP_CLOCK_SOURCE("Sample Clock Source", 0), |
3148 | { | ||
3149 | /* FIXME: should be PCM or MIXER? */ | ||
3150 | /* .iface = SNDRV_CTL_ELEM_IFACE_PCM, */ | ||
3151 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3152 | .name = "Sample Clock Source Locking", | ||
3153 | .info = snd_hdsp_info_clock_source_lock, | ||
3154 | .get = snd_hdsp_get_clock_source_lock, | ||
3155 | .put = snd_hdsp_put_clock_source_lock, | ||
3156 | }, | ||
3116 | HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | 3157 | HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
3117 | HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0), | 3158 | HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0), |
3118 | HDSP_AUTOSYNC_REF("AutoSync Reference", 0), | 3159 | HDSP_AUTOSYNC_REF("AutoSync Reference", 0), |
@@ -3345,6 +3386,7 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) | |||
3345 | snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode); | 3386 | snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode); |
3346 | 3387 | ||
3347 | snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate); | 3388 | snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate); |
3389 | snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No"); | ||
3348 | 3390 | ||
3349 | snd_iprintf(buffer, "\n"); | 3391 | snd_iprintf(buffer, "\n"); |
3350 | 3392 | ||
@@ -3849,13 +3891,14 @@ static int snd_hdsp_hw_params(snd_pcm_substream_t *substream, | |||
3849 | */ | 3891 | */ |
3850 | 3892 | ||
3851 | spin_lock_irq(&hdsp->lock); | 3893 | spin_lock_irq(&hdsp->lock); |
3852 | if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) { | 3894 | if (! hdsp->clock_source_locked) { |
3853 | spin_unlock_irq(&hdsp->lock); | 3895 | if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) { |
3854 | _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); | 3896 | spin_unlock_irq(&hdsp->lock); |
3855 | return err; | 3897 | _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); |
3856 | } else { | 3898 | return err; |
3857 | spin_unlock_irq(&hdsp->lock); | 3899 | } |
3858 | } | 3900 | } |
3901 | spin_unlock_irq(&hdsp->lock); | ||
3859 | 3902 | ||
3860 | if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) { | 3903 | if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) { |
3861 | _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | 3904 | _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); |
@@ -4280,13 +4323,17 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream) | |||
4280 | 4323 | ||
4281 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | 4324 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); |
4282 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes); | 4325 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes); |
4283 | if (hdsp->io_type == H9632) { | 4326 | if (hdsp->clock_source_locked) { |
4284 | runtime->hw.channels_min = hdsp->qs_out_channels; | 4327 | runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate; |
4285 | runtime->hw.channels_max = hdsp->ss_out_channels; | 4328 | } else if (hdsp->io_type == H9632) { |
4286 | runtime->hw.rate_max = 192000; | 4329 | runtime->hw.rate_max = 192000; |
4287 | runtime->hw.rates = SNDRV_PCM_RATE_KNOT; | 4330 | runtime->hw.rates = SNDRV_PCM_RATE_KNOT; |
4288 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates); | 4331 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates); |
4289 | } | 4332 | } |
4333 | if (hdsp->io_type == H9632) { | ||
4334 | runtime->hw.channels_min = hdsp->qs_out_channels; | ||
4335 | runtime->hw.channels_max = hdsp->ss_out_channels; | ||
4336 | } | ||
4290 | 4337 | ||
4291 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 4338 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
4292 | snd_hdsp_hw_rule_out_channels, hdsp, | 4339 | snd_hdsp_hw_rule_out_channels, hdsp, |
@@ -4912,19 +4959,9 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp) | |||
4912 | release_firmware(fw); | 4959 | release_firmware(fw); |
4913 | return -EINVAL; | 4960 | return -EINVAL; |
4914 | } | 4961 | } |
4915 | #ifdef SNDRV_BIG_ENDIAN | 4962 | |
4916 | { | ||
4917 | int i; | ||
4918 | u32 *src = (u32*)fw->data; | ||
4919 | for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++) | ||
4920 | hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) | | ||
4921 | ((*src & 0x0000ff00) << 8) | | ||
4922 | ((*src & 0x00ff0000) >> 8) | | ||
4923 | ((*src & 0xff000000) >> 16); | ||
4924 | } | ||
4925 | #else | ||
4926 | memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); | 4963 | memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); |
4927 | #endif | 4964 | |
4928 | release_firmware(fw); | 4965 | release_firmware(fw); |
4929 | 4966 | ||
4930 | hdsp->state |= HDSP_FirmwareCached; | 4967 | hdsp->state |= HDSP_FirmwareCached; |
@@ -5042,8 +5079,7 @@ static int __devinit snd_hdsp_create(snd_card_t *card, | |||
5042 | if (!is_9652 && !is_9632) { | 5079 | if (!is_9652 && !is_9632) { |
5043 | /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ | 5080 | /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ |
5044 | if ((1000 / HZ) < 2000) { | 5081 | if ((1000 / HZ) < 2000) { |
5045 | set_current_state(TASK_UNINTERRUPTIBLE); | 5082 | ssleep(2); |
5046 | schedule_timeout((2000 * HZ + 999) / 1000); | ||
5047 | } else { | 5083 | } else { |
5048 | mdelay(2000); | 5084 | mdelay(2000); |
5049 | } | 5085 | } |
@@ -5194,7 +5230,7 @@ static struct pci_driver driver = { | |||
5194 | 5230 | ||
5195 | static int __init alsa_card_hdsp_init(void) | 5231 | static int __init alsa_card_hdsp_init(void) |
5196 | { | 5232 | { |
5197 | return pci_module_init(&driver); | 5233 | return pci_register_driver(&driver); |
5198 | } | 5234 | } |
5199 | 5235 | ||
5200 | static void __exit alsa_card_hdsp_exit(void) | 5236 | static void __exit alsa_card_hdsp_exit(void) |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c new file mode 100644 index 000000000000..9e86d0eb41ce --- /dev/null +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -0,0 +1,3671 @@ | |||
1 | /* -*- linux-c -*- | ||
2 | * | ||
3 | * ALSA driver for RME Hammerfall DSP MADI audio interface(s) | ||
4 | * | ||
5 | * Copyright (c) 2003 Winfried Ritsch (IEM) | ||
6 | * code based on hdsp.c Paul Davis | ||
7 | * Marcus Andersson | ||
8 | * Thomas Charbonnel | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | */ | ||
25 | #include <sound/driver.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/moduleparam.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <asm/io.h> | ||
33 | |||
34 | #include <sound/core.h> | ||
35 | #include <sound/control.h> | ||
36 | #include <sound/pcm.h> | ||
37 | #include <sound/info.h> | ||
38 | #include <sound/asoundef.h> | ||
39 | #include <sound/rawmidi.h> | ||
40 | #include <sound/hwdep.h> | ||
41 | #include <sound/initval.h> | ||
42 | |||
43 | #include <sound/hdspm.h> | ||
44 | |||
45 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | ||
46 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | ||
47 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ | ||
48 | |||
49 | /* Disable precise pointer at start */ | ||
50 | static int precise_ptr[SNDRV_CARDS]; | ||
51 | |||
52 | /* Send all playback to line outs */ | ||
53 | static int line_outs_monitor[SNDRV_CARDS]; | ||
54 | |||
55 | /* Enable Analog Outs on Channel 63/64 by default */ | ||
56 | static int enable_monitor[SNDRV_CARDS]; | ||
57 | |||
58 | module_param_array(index, int, NULL, 0444); | ||
59 | MODULE_PARM_DESC(index, "Index value for RME HDSPM interface."); | ||
60 | |||
61 | module_param_array(id, charp, NULL, 0444); | ||
62 | MODULE_PARM_DESC(id, "ID string for RME HDSPM interface."); | ||
63 | |||
64 | module_param_array(enable, bool, NULL, 0444); | ||
65 | MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards."); | ||
66 | |||
67 | module_param_array(precise_ptr, bool, NULL, 0444); | ||
68 | MODULE_PARM_DESC(precise_ptr, "Enable precise pointer, or disable."); | ||
69 | |||
70 | module_param_array(line_outs_monitor, bool, NULL, 0444); | ||
71 | MODULE_PARM_DESC(line_outs_monitor, | ||
72 | "Send playback streams to analog outs by default."); | ||
73 | |||
74 | module_param_array(enable_monitor, bool, NULL, 0444); | ||
75 | MODULE_PARM_DESC(enable_monitor, | ||
76 | "Enable Analog Out on Channel 63/64 by default."); | ||
77 | |||
78 | MODULE_AUTHOR | ||
79 | ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, " | ||
80 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>"); | ||
81 | MODULE_DESCRIPTION("RME HDSPM"); | ||
82 | MODULE_LICENSE("GPL"); | ||
83 | MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | ||
84 | |||
85 | /* --- Write registers. --- | ||
86 | These are defined as byte-offsets from the iobase value. */ | ||
87 | |||
88 | #define HDSPM_controlRegister 64 | ||
89 | #define HDSPM_interruptConfirmation 96 | ||
90 | #define HDSPM_control2Reg 256 /* not in specs ???????? */ | ||
91 | #define HDSPM_midiDataOut0 352 /* just believe in old code */ | ||
92 | #define HDSPM_midiDataOut1 356 | ||
93 | |||
94 | /* DMA enable for 64 channels, only Bit 0 is relevant */ | ||
95 | #define HDSPM_outputEnableBase 512 /* 512-767 input DMA */ | ||
96 | #define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */ | ||
97 | |||
98 | /* 16 page addresses for each of the 64 channels DMA buffer in and out | ||
99 | (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */ | ||
100 | #define HDSPM_pageAddressBufferOut 8192 | ||
101 | #define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4) | ||
102 | |||
103 | #define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */ | ||
104 | |||
105 | #define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */ | ||
106 | |||
107 | /* --- Read registers. --- | ||
108 | These are defined as byte-offsets from the iobase value */ | ||
109 | #define HDSPM_statusRegister 0 | ||
110 | #define HDSPM_statusRegister2 96 | ||
111 | |||
112 | #define HDSPM_midiDataIn0 360 | ||
113 | #define HDSPM_midiDataIn1 364 | ||
114 | |||
115 | /* status is data bytes in MIDI-FIFO (0-128) */ | ||
116 | #define HDSPM_midiStatusOut0 384 | ||
117 | #define HDSPM_midiStatusOut1 388 | ||
118 | #define HDSPM_midiStatusIn0 392 | ||
119 | #define HDSPM_midiStatusIn1 396 | ||
120 | |||
121 | |||
122 | /* the meters are regular i/o-mapped registers, but offset | ||
123 | considerably from the rest. the peak registers are reset | ||
124 | when read; the least-significant 4 bits are full-scale counters; | ||
125 | the actual peak value is in the most-significant 24 bits. | ||
126 | */ | ||
127 | #define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters */ | ||
128 | |||
129 | /* --- Control Register bits --------- */ | ||
130 | #define HDSPM_Start (1<<0) /* start engine */ | ||
131 | |||
132 | #define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */ | ||
133 | #define HDSPM_Latency1 (1<<2) /* where n is defined */ | ||
134 | #define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */ | ||
135 | |||
136 | #define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */ | ||
137 | |||
138 | #define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */ | ||
139 | |||
140 | #define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */ | ||
141 | #define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */ | ||
142 | #define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */ | ||
143 | #define HDSPM_QuadSpeed (1<<31) /* quad speed bit, not implemented now */ | ||
144 | |||
145 | #define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1, | ||
146 | 56channelMODE=0 */ | ||
147 | |||
148 | #define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, | ||
149 | 0=off, 1=on */ | ||
150 | |||
151 | #define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ | ||
152 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ | ||
153 | |||
154 | #define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ | ||
155 | #define HDSPM_SyncRef1 (1<<17) /* should be 0 */ | ||
156 | |||
157 | #define HDSPM_clr_tms (1<<19) /* clear track marker, do not use | ||
158 | AES additional bits in | ||
159 | lower 5 Audiodatabits ??? */ | ||
160 | |||
161 | #define HDSPM_Midi0InterruptEnable (1<<22) | ||
162 | #define HDSPM_Midi1InterruptEnable (1<<23) | ||
163 | |||
164 | #define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */ | ||
165 | |||
166 | |||
167 | /* --- bit helper defines */ | ||
168 | #define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2) | ||
169 | #define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1) | ||
170 | #define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1) | ||
171 | #define HDSPM_InputOptical 0 | ||
172 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) | ||
173 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1) | ||
174 | #define HDSPM_SyncRef_Word 0 | ||
175 | #define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) | ||
176 | |||
177 | #define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */ | ||
178 | #define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */ | ||
179 | |||
180 | #define HDSPM_Frequency32KHz HDSPM_Frequency0 | ||
181 | #define HDSPM_Frequency44_1KHz HDSPM_Frequency1 | ||
182 | #define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0) | ||
183 | #define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0) | ||
184 | #define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1) | ||
185 | #define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0) | ||
186 | |||
187 | /* --- for internal discrimination */ | ||
188 | #define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ | ||
189 | #define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1 | ||
190 | #define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2 | ||
191 | #define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3 | ||
192 | #define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4 | ||
193 | #define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5 | ||
194 | #define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6 | ||
195 | #define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7 | ||
196 | #define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8 | ||
197 | #define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9 | ||
198 | |||
199 | /* Synccheck Status */ | ||
200 | #define HDSPM_SYNC_CHECK_NO_LOCK 0 | ||
201 | #define HDSPM_SYNC_CHECK_LOCK 1 | ||
202 | #define HDSPM_SYNC_CHECK_SYNC 2 | ||
203 | |||
204 | /* AutoSync References - used by "autosync_ref" control switch */ | ||
205 | #define HDSPM_AUTOSYNC_FROM_WORD 0 | ||
206 | #define HDSPM_AUTOSYNC_FROM_MADI 1 | ||
207 | #define HDSPM_AUTOSYNC_FROM_NONE 2 | ||
208 | |||
209 | /* Possible sources of MADI input */ | ||
210 | #define HDSPM_OPTICAL 0 /* optical */ | ||
211 | #define HDSPM_COAXIAL 1 /* BNC */ | ||
212 | |||
213 | #define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask) | ||
214 | #define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1) | ||
215 | |||
216 | #define hdspm_encode_in(x) (((x)&0x3)<<14) | ||
217 | #define hdspm_decode_in(x) (((x)>>14)&0x3) | ||
218 | |||
219 | /* --- control2 register bits --- */ | ||
220 | #define HDSPM_TMS (1<<0) | ||
221 | #define HDSPM_TCK (1<<1) | ||
222 | #define HDSPM_TDI (1<<2) | ||
223 | #define HDSPM_JTAG (1<<3) | ||
224 | #define HDSPM_PWDN (1<<4) | ||
225 | #define HDSPM_PROGRAM (1<<5) | ||
226 | #define HDSPM_CONFIG_MODE_0 (1<<6) | ||
227 | #define HDSPM_CONFIG_MODE_1 (1<<7) | ||
228 | /*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/ | ||
229 | #define HDSPM_BIGENDIAN_MODE (1<<9) | ||
230 | #define HDSPM_RD_MULTIPLE (1<<10) | ||
231 | |||
232 | /* --- Status Register bits --- */ | ||
233 | #define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */ | ||
234 | #define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */ | ||
235 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */ | ||
236 | #define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ | ||
237 | |||
238 | #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ | ||
239 | /* since 64byte accurate last 6 bits | ||
240 | are not used */ | ||
241 | |||
242 | #define HDSPM_madiSync (1<<18) /* MADI is in sync */ | ||
243 | #define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */ | ||
244 | |||
245 | #define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */ | ||
246 | #define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */ | ||
247 | #define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */ | ||
248 | #define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */ | ||
249 | |||
250 | #define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with Interrupt */ | ||
251 | #define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */ | ||
252 | #define HDSPM_midi1IRQPending (1<<31) /* and aktiv */ | ||
253 | |||
254 | /* --- status bit helpers */ | ||
255 | #define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3) | ||
256 | #define HDSPM_madiFreq32 (HDSPM_madiFreq0) | ||
257 | #define HDSPM_madiFreq44_1 (HDSPM_madiFreq1) | ||
258 | #define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1) | ||
259 | #define HDSPM_madiFreq64 (HDSPM_madiFreq2) | ||
260 | #define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2) | ||
261 | #define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2) | ||
262 | #define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2) | ||
263 | #define HDSPM_madiFreq176_4 (HDSPM_madiFreq3) | ||
264 | #define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0) | ||
265 | |||
266 | /* Status2 Register bits */ | ||
267 | |||
268 | #define HDSPM_version0 (1<<0) /* not realy defined but I guess */ | ||
269 | #define HDSPM_version1 (1<<1) /* in former cards it was ??? */ | ||
270 | #define HDSPM_version2 (1<<2) | ||
271 | |||
272 | #define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */ | ||
273 | #define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */ | ||
274 | |||
275 | #define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */ | ||
276 | #define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */ | ||
277 | #define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */ | ||
278 | /* missing Bit for 111=128, 1000=176.4, 1001=192 */ | ||
279 | |||
280 | #define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */ | ||
281 | #define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */ | ||
282 | #define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */ | ||
283 | |||
284 | #define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync) | ||
285 | |||
286 | #define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2) | ||
287 | #define HDSPM_wcFreq32 (HDSPM_wc_freq0) | ||
288 | #define HDSPM_wcFreq44_1 (HDSPM_wc_freq1) | ||
289 | #define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1) | ||
290 | #define HDSPM_wcFreq64 (HDSPM_wc_freq2) | ||
291 | #define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2) | ||
292 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) | ||
293 | |||
294 | |||
295 | #define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) | ||
296 | #define HDSPM_SelSyncRef_WORD 0 | ||
297 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) | ||
298 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) | ||
299 | |||
300 | /* Mixer Values */ | ||
301 | #define UNITY_GAIN 32768 /* = 65536/2 */ | ||
302 | #define MINUS_INFINITY_GAIN 0 | ||
303 | |||
304 | /* PCI info */ | ||
305 | #ifndef PCI_VENDOR_ID_XILINX | ||
306 | #define PCI_VENDOR_ID_XILINX 0x10ee | ||
307 | #endif | ||
308 | #ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP | ||
309 | #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5 | ||
310 | #endif | ||
311 | #ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI | ||
312 | #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6 | ||
313 | #endif | ||
314 | |||
315 | |||
316 | /* Number of channels for different Speed Modes */ | ||
317 | #define MADI_SS_CHANNELS 64 | ||
318 | #define MADI_DS_CHANNELS 32 | ||
319 | #define MADI_QS_CHANNELS 16 | ||
320 | |||
321 | /* the size of a substream (1 mono data stream) */ | ||
322 | #define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024) | ||
323 | #define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES) | ||
324 | |||
325 | /* the size of the area we need to allocate for DMA transfers. the | ||
326 | size is the same regardless of the number of channels, and | ||
327 | also the latency to use. | ||
328 | for one direction !!! | ||
329 | */ | ||
330 | #define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) | ||
331 | #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) | ||
332 | |||
333 | typedef struct _hdspm hdspm_t; | ||
334 | typedef struct _hdspm_midi hdspm_midi_t; | ||
335 | |||
336 | struct _hdspm_midi { | ||
337 | hdspm_t *hdspm; | ||
338 | int id; | ||
339 | snd_rawmidi_t *rmidi; | ||
340 | snd_rawmidi_substream_t *input; | ||
341 | snd_rawmidi_substream_t *output; | ||
342 | char istimer; /* timer in use */ | ||
343 | struct timer_list timer; | ||
344 | spinlock_t lock; | ||
345 | int pending; | ||
346 | }; | ||
347 | |||
348 | struct _hdspm { | ||
349 | spinlock_t lock; | ||
350 | snd_pcm_substream_t *capture_substream; /* only one playback */ | ||
351 | snd_pcm_substream_t *playback_substream; /* and/or capture stream */ | ||
352 | |||
353 | char *card_name; /* for procinfo */ | ||
354 | unsigned short firmware_rev; /* dont know if relevant */ | ||
355 | |||
356 | int precise_ptr; /* use precise pointers, to be tested */ | ||
357 | int monitor_outs; /* set up monitoring outs init flag */ | ||
358 | |||
359 | u32 control_register; /* cached value */ | ||
360 | u32 control2_register; /* cached value */ | ||
361 | |||
362 | hdspm_midi_t midi[2]; | ||
363 | struct tasklet_struct midi_tasklet; | ||
364 | |||
365 | size_t period_bytes; | ||
366 | unsigned char ss_channels; /* channels of card in single speed */ | ||
367 | unsigned char ds_channels; /* Double Speed */ | ||
368 | unsigned char qs_channels; /* Quad Speed */ | ||
369 | |||
370 | unsigned char *playback_buffer; /* suitably aligned address */ | ||
371 | unsigned char *capture_buffer; /* suitably aligned address */ | ||
372 | |||
373 | pid_t capture_pid; /* process id which uses capture */ | ||
374 | pid_t playback_pid; /* process id which uses capture */ | ||
375 | int running; /* running status */ | ||
376 | |||
377 | int last_external_sample_rate; /* samplerate mystic ... */ | ||
378 | int last_internal_sample_rate; | ||
379 | int system_sample_rate; | ||
380 | |||
381 | char *channel_map; /* channel map for DS and Quadspeed */ | ||
382 | |||
383 | int dev; /* Hardware vars... */ | ||
384 | int irq; | ||
385 | unsigned long port; | ||
386 | void __iomem *iobase; | ||
387 | |||
388 | int irq_count; /* for debug */ | ||
389 | |||
390 | snd_card_t *card; /* one card */ | ||
391 | snd_pcm_t *pcm; /* has one pcm */ | ||
392 | snd_hwdep_t *hwdep; /* and a hwdep for additional ioctl */ | ||
393 | struct pci_dev *pci; /* and an pci info */ | ||
394 | |||
395 | /* Mixer vars */ | ||
396 | snd_kcontrol_t *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */ | ||
397 | snd_kcontrol_t *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */ | ||
398 | hdspm_mixer_t *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */ | ||
399 | |||
400 | }; | ||
401 | |||
402 | /* These tables map the ALSA channels 1..N to the channels that we | ||
403 | need to use in order to find the relevant channel buffer. RME | ||
404 | refer to this kind of mapping as between "the ADAT channel and | ||
405 | the DMA channel." We index it using the logical audio channel, | ||
406 | and the value is the DMA channel (i.e. channel buffer number) | ||
407 | where the data for that channel can be read/written from/to. | ||
408 | */ | ||
409 | |||
410 | static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = { | ||
411 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
412 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
413 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
414 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
415 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
416 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
417 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
418 | 56, 57, 58, 59, 60, 61, 62, 63 | ||
419 | }; | ||
420 | |||
421 | static char channel_map_madi_ds[HDSPM_MAX_CHANNELS] = { | ||
422 | 0, 2, 4, 6, 8, 10, 12, 14, | ||
423 | 16, 18, 20, 22, 24, 26, 28, 30, | ||
424 | 32, 34, 36, 38, 40, 42, 44, 46, | ||
425 | 48, 50, 52, 54, 56, 58, 60, 62, | ||
426 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
427 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
428 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
429 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
430 | }; | ||
431 | |||
432 | static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = { | ||
433 | 0, 4, 8, 12, 16, 20, 24, 28, | ||
434 | 32, 36, 40, 44, 48, 52, 56, 60 | ||
435 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
436 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
437 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
438 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
439 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
440 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
441 | }; | ||
442 | |||
443 | |||
444 | static struct pci_device_id snd_hdspm_ids[] = { | ||
445 | { | ||
446 | .vendor = PCI_VENDOR_ID_XILINX, | ||
447 | .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI, | ||
448 | .subvendor = PCI_ANY_ID, | ||
449 | .subdevice = PCI_ANY_ID, | ||
450 | .class = 0, | ||
451 | .class_mask = 0, | ||
452 | .driver_data = 0}, | ||
453 | {0,} | ||
454 | }; | ||
455 | |||
456 | MODULE_DEVICE_TABLE(pci, snd_hdspm_ids); | ||
457 | |||
458 | /* prototypes */ | ||
459 | static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card, | ||
460 | hdspm_t * hdspm); | ||
461 | static int __devinit snd_hdspm_create_pcm(snd_card_t * card, | ||
462 | hdspm_t * hdspm); | ||
463 | |||
464 | static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm); | ||
465 | static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm); | ||
466 | static int hdspm_autosync_ref(hdspm_t * hdspm); | ||
467 | static int snd_hdspm_set_defaults(hdspm_t * hdspm); | ||
468 | static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf, | ||
469 | unsigned int reg, int channels); | ||
470 | |||
471 | /* Write/read to/from HDSPM with Adresses in Bytes | ||
472 | not words but only 32Bit writes are allowed */ | ||
473 | |||
474 | static inline void hdspm_write(hdspm_t * hdspm, unsigned int reg, | ||
475 | unsigned int val) | ||
476 | { | ||
477 | writel(val, hdspm->iobase + reg); | ||
478 | } | ||
479 | |||
480 | static inline unsigned int hdspm_read(hdspm_t * hdspm, unsigned int reg) | ||
481 | { | ||
482 | return readl(hdspm->iobase + reg); | ||
483 | } | ||
484 | |||
485 | /* for each output channel (chan) I have an Input (in) and Playback (pb) Fader | ||
486 | mixer is write only on hardware so we have to cache him for read | ||
487 | each fader is a u32, but uses only the first 16 bit */ | ||
488 | |||
489 | static inline int hdspm_read_in_gain(hdspm_t * hdspm, unsigned int chan, | ||
490 | unsigned int in) | ||
491 | { | ||
492 | if (chan > HDSPM_MIXER_CHANNELS || in > HDSPM_MIXER_CHANNELS) | ||
493 | return 0; | ||
494 | |||
495 | return hdspm->mixer->ch[chan].in[in]; | ||
496 | } | ||
497 | |||
498 | static inline int hdspm_read_pb_gain(hdspm_t * hdspm, unsigned int chan, | ||
499 | unsigned int pb) | ||
500 | { | ||
501 | if (chan > HDSPM_MIXER_CHANNELS || pb > HDSPM_MIXER_CHANNELS) | ||
502 | return 0; | ||
503 | return hdspm->mixer->ch[chan].pb[pb]; | ||
504 | } | ||
505 | |||
506 | static inline int hdspm_write_in_gain(hdspm_t * hdspm, unsigned int chan, | ||
507 | unsigned int in, unsigned short data) | ||
508 | { | ||
509 | if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS) | ||
510 | return -1; | ||
511 | |||
512 | hdspm_write(hdspm, | ||
513 | HDSPM_MADI_mixerBase + | ||
514 | ((in + 128 * chan) * sizeof(u32)), | ||
515 | (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF)); | ||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | static inline int hdspm_write_pb_gain(hdspm_t * hdspm, unsigned int chan, | ||
520 | unsigned int pb, unsigned short data) | ||
521 | { | ||
522 | if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS) | ||
523 | return -1; | ||
524 | |||
525 | hdspm_write(hdspm, | ||
526 | HDSPM_MADI_mixerBase + | ||
527 | ((64 + pb + 128 * chan) * sizeof(u32)), | ||
528 | (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF)); | ||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | |||
533 | /* enable DMA for specific channels, now available for DSP-MADI */ | ||
534 | static inline void snd_hdspm_enable_in(hdspm_t * hdspm, int i, int v) | ||
535 | { | ||
536 | hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v); | ||
537 | } | ||
538 | |||
539 | static inline void snd_hdspm_enable_out(hdspm_t * hdspm, int i, int v) | ||
540 | { | ||
541 | hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v); | ||
542 | } | ||
543 | |||
544 | /* check if same process is writing and reading */ | ||
545 | static inline int snd_hdspm_use_is_exclusive(hdspm_t * hdspm) | ||
546 | { | ||
547 | unsigned long flags; | ||
548 | int ret = 1; | ||
549 | |||
550 | spin_lock_irqsave(&hdspm->lock, flags); | ||
551 | if ((hdspm->playback_pid != hdspm->capture_pid) && | ||
552 | (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) { | ||
553 | ret = 0; | ||
554 | } | ||
555 | spin_unlock_irqrestore(&hdspm->lock, flags); | ||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | /* check for external sample rate */ | ||
560 | static inline int hdspm_external_sample_rate(hdspm_t * hdspm) | ||
561 | { | ||
562 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
563 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
564 | unsigned int rate_bits; | ||
565 | int rate = 0; | ||
566 | |||
567 | /* if wordclock has synced freq and wordclock is valid */ | ||
568 | if ((status2 & HDSPM_wcLock) != 0 && | ||
569 | (status & HDSPM_SelSyncRef0) == 0) { | ||
570 | |||
571 | rate_bits = status2 & HDSPM_wcFreqMask; | ||
572 | |||
573 | switch (rate_bits) { | ||
574 | case HDSPM_wcFreq32: | ||
575 | rate = 32000; | ||
576 | break; | ||
577 | case HDSPM_wcFreq44_1: | ||
578 | rate = 44100; | ||
579 | break; | ||
580 | case HDSPM_wcFreq48: | ||
581 | rate = 48000; | ||
582 | break; | ||
583 | case HDSPM_wcFreq64: | ||
584 | rate = 64000; | ||
585 | break; | ||
586 | case HDSPM_wcFreq88_2: | ||
587 | rate = 88200; | ||
588 | break; | ||
589 | case HDSPM_wcFreq96: | ||
590 | rate = 96000; | ||
591 | break; | ||
592 | /* Quadspeed Bit missing ???? */ | ||
593 | default: | ||
594 | rate = 0; | ||
595 | break; | ||
596 | } | ||
597 | } | ||
598 | |||
599 | /* if rate detected and Syncref is Word than have it, word has priority to MADI */ | ||
600 | if (rate != 0 | ||
601 | && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) | ||
602 | return rate; | ||
603 | |||
604 | /* maby a madi input (which is taken if sel sync is madi) */ | ||
605 | if (status & HDSPM_madiLock) { | ||
606 | rate_bits = status & HDSPM_madiFreqMask; | ||
607 | |||
608 | switch (rate_bits) { | ||
609 | case HDSPM_madiFreq32: | ||
610 | rate = 32000; | ||
611 | break; | ||
612 | case HDSPM_madiFreq44_1: | ||
613 | rate = 44100; | ||
614 | break; | ||
615 | case HDSPM_madiFreq48: | ||
616 | rate = 48000; | ||
617 | break; | ||
618 | case HDSPM_madiFreq64: | ||
619 | rate = 64000; | ||
620 | break; | ||
621 | case HDSPM_madiFreq88_2: | ||
622 | rate = 88200; | ||
623 | break; | ||
624 | case HDSPM_madiFreq96: | ||
625 | rate = 96000; | ||
626 | break; | ||
627 | case HDSPM_madiFreq128: | ||
628 | rate = 128000; | ||
629 | break; | ||
630 | case HDSPM_madiFreq176_4: | ||
631 | rate = 176400; | ||
632 | break; | ||
633 | case HDSPM_madiFreq192: | ||
634 | rate = 192000; | ||
635 | break; | ||
636 | default: | ||
637 | rate = 0; | ||
638 | break; | ||
639 | } | ||
640 | } | ||
641 | return rate; | ||
642 | } | ||
643 | |||
644 | /* Latency function */ | ||
645 | static inline void hdspm_compute_period_size(hdspm_t * hdspm) | ||
646 | { | ||
647 | hdspm->period_bytes = | ||
648 | 1 << ((hdspm_decode_latency(hdspm->control_register) + 8)); | ||
649 | } | ||
650 | |||
651 | static snd_pcm_uframes_t hdspm_hw_pointer(hdspm_t * hdspm) | ||
652 | { | ||
653 | int position; | ||
654 | |||
655 | position = hdspm_read(hdspm, HDSPM_statusRegister); | ||
656 | |||
657 | if (!hdspm->precise_ptr) { | ||
658 | return (position & HDSPM_BufferID) ? (hdspm->period_bytes / | ||
659 | 4) : 0; | ||
660 | } | ||
661 | |||
662 | /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst) | ||
663 | i have experimented that it is at most 64 Byte to much for playing | ||
664 | so substraction of 64 byte should be ok for ALSA, but use it only | ||
665 | for application where you know what you do since if you come to | ||
666 | near with record pointer it can be a disaster */ | ||
667 | |||
668 | position &= HDSPM_BufferPositionMask; | ||
669 | position = ((position - 64) % (2 * hdspm->period_bytes)) / 4; | ||
670 | |||
671 | return position; | ||
672 | } | ||
673 | |||
674 | |||
675 | static inline void hdspm_start_audio(hdspm_t * s) | ||
676 | { | ||
677 | s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start); | ||
678 | hdspm_write(s, HDSPM_controlRegister, s->control_register); | ||
679 | } | ||
680 | |||
681 | static inline void hdspm_stop_audio(hdspm_t * s) | ||
682 | { | ||
683 | s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable); | ||
684 | hdspm_write(s, HDSPM_controlRegister, s->control_register); | ||
685 | } | ||
686 | |||
687 | /* should I silence all or only opened ones ? doit all for first even is 4MB*/ | ||
688 | static inline void hdspm_silence_playback(hdspm_t * hdspm) | ||
689 | { | ||
690 | int i; | ||
691 | int n = hdspm->period_bytes; | ||
692 | void *buf = hdspm->playback_buffer; | ||
693 | |||
694 | snd_assert(buf != NULL, return); | ||
695 | |||
696 | for (i = 0; i < HDSPM_MAX_CHANNELS; i++) { | ||
697 | memset(buf, 0, n); | ||
698 | buf += HDSPM_CHANNEL_BUFFER_BYTES; | ||
699 | } | ||
700 | } | ||
701 | |||
702 | static int hdspm_set_interrupt_interval(hdspm_t * s, unsigned int frames) | ||
703 | { | ||
704 | int n; | ||
705 | |||
706 | spin_lock_irq(&s->lock); | ||
707 | |||
708 | frames >>= 7; | ||
709 | n = 0; | ||
710 | while (frames) { | ||
711 | n++; | ||
712 | frames >>= 1; | ||
713 | } | ||
714 | s->control_register &= ~HDSPM_LatencyMask; | ||
715 | s->control_register |= hdspm_encode_latency(n); | ||
716 | |||
717 | hdspm_write(s, HDSPM_controlRegister, s->control_register); | ||
718 | |||
719 | hdspm_compute_period_size(s); | ||
720 | |||
721 | spin_unlock_irq(&s->lock); | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | |||
727 | /* dummy set rate lets see what happens */ | ||
728 | static int hdspm_set_rate(hdspm_t * hdspm, int rate, int called_internally) | ||
729 | { | ||
730 | int reject_if_open = 0; | ||
731 | int current_rate; | ||
732 | int rate_bits; | ||
733 | int not_set = 0; | ||
734 | |||
735 | /* ASSUMPTION: hdspm->lock is either set, or there is no need for | ||
736 | it (e.g. during module initialization). | ||
737 | */ | ||
738 | |||
739 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { | ||
740 | |||
741 | /* SLAVE --- */ | ||
742 | if (called_internally) { | ||
743 | |||
744 | /* request from ctl or card initialization | ||
745 | just make a warning an remember setting | ||
746 | for future master mode switching */ | ||
747 | |||
748 | snd_printk | ||
749 | (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n"); | ||
750 | not_set = 1; | ||
751 | } else { | ||
752 | |||
753 | /* hw_param request while in AutoSync mode */ | ||
754 | int external_freq = | ||
755 | hdspm_external_sample_rate(hdspm); | ||
756 | |||
757 | if ((hdspm_autosync_ref(hdspm) == | ||
758 | HDSPM_AUTOSYNC_FROM_NONE)) { | ||
759 | |||
760 | snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n"); | ||
761 | not_set = 1; | ||
762 | |||
763 | } else if (rate != external_freq) { | ||
764 | |||
765 | snd_printk | ||
766 | (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n"); | ||
767 | not_set = 1; | ||
768 | } | ||
769 | } | ||
770 | } | ||
771 | |||
772 | current_rate = hdspm->system_sample_rate; | ||
773 | |||
774 | /* Changing between Singe, Double and Quad speed is not | ||
775 | allowed if any substreams are open. This is because such a change | ||
776 | causes a shift in the location of the DMA buffers and a reduction | ||
777 | in the number of available buffers. | ||
778 | |||
779 | Note that a similar but essentially insoluble problem exists for | ||
780 | externally-driven rate changes. All we can do is to flag rate | ||
781 | changes in the read/write routines. | ||
782 | */ | ||
783 | |||
784 | switch (rate) { | ||
785 | case 32000: | ||
786 | if (current_rate > 48000) { | ||
787 | reject_if_open = 1; | ||
788 | } | ||
789 | rate_bits = HDSPM_Frequency32KHz; | ||
790 | break; | ||
791 | case 44100: | ||
792 | if (current_rate > 48000) { | ||
793 | reject_if_open = 1; | ||
794 | } | ||
795 | rate_bits = HDSPM_Frequency44_1KHz; | ||
796 | break; | ||
797 | case 48000: | ||
798 | if (current_rate > 48000) { | ||
799 | reject_if_open = 1; | ||
800 | } | ||
801 | rate_bits = HDSPM_Frequency48KHz; | ||
802 | break; | ||
803 | case 64000: | ||
804 | if (current_rate <= 48000) { | ||
805 | reject_if_open = 1; | ||
806 | } | ||
807 | rate_bits = HDSPM_Frequency64KHz; | ||
808 | break; | ||
809 | case 88200: | ||
810 | if (current_rate <= 48000) { | ||
811 | reject_if_open = 1; | ||
812 | } | ||
813 | rate_bits = HDSPM_Frequency88_2KHz; | ||
814 | break; | ||
815 | case 96000: | ||
816 | if (current_rate <= 48000) { | ||
817 | reject_if_open = 1; | ||
818 | } | ||
819 | rate_bits = HDSPM_Frequency96KHz; | ||
820 | break; | ||
821 | default: | ||
822 | return -EINVAL; | ||
823 | } | ||
824 | |||
825 | if (reject_if_open | ||
826 | && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) { | ||
827 | snd_printk | ||
828 | (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n", | ||
829 | hdspm->capture_pid, hdspm->playback_pid); | ||
830 | return -EBUSY; | ||
831 | } | ||
832 | |||
833 | hdspm->control_register &= ~HDSPM_FrequencyMask; | ||
834 | hdspm->control_register |= rate_bits; | ||
835 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
836 | |||
837 | if (rate > 64000) | ||
838 | hdspm->channel_map = channel_map_madi_qs; | ||
839 | else if (rate > 48000) | ||
840 | hdspm->channel_map = channel_map_madi_ds; | ||
841 | else | ||
842 | hdspm->channel_map = channel_map_madi_ss; | ||
843 | |||
844 | hdspm->system_sample_rate = rate; | ||
845 | |||
846 | if (not_set != 0) | ||
847 | return -1; | ||
848 | |||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | /* mainly for init to 0 on load */ | ||
853 | static void all_in_all_mixer(hdspm_t * hdspm, int sgain) | ||
854 | { | ||
855 | int i, j; | ||
856 | unsigned int gain = | ||
857 | (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain; | ||
858 | |||
859 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) | ||
860 | for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) { | ||
861 | hdspm_write_in_gain(hdspm, i, j, gain); | ||
862 | hdspm_write_pb_gain(hdspm, i, j, gain); | ||
863 | } | ||
864 | } | ||
865 | |||
866 | /*---------------------------------------------------------------------------- | ||
867 | MIDI | ||
868 | ----------------------------------------------------------------------------*/ | ||
869 | |||
870 | static inline unsigned char snd_hdspm_midi_read_byte (hdspm_t *hdspm, int id) | ||
871 | { | ||
872 | /* the hardware already does the relevant bit-mask with 0xff */ | ||
873 | if (id) | ||
874 | return hdspm_read(hdspm, HDSPM_midiDataIn1); | ||
875 | else | ||
876 | return hdspm_read(hdspm, HDSPM_midiDataIn0); | ||
877 | } | ||
878 | |||
879 | static inline void snd_hdspm_midi_write_byte (hdspm_t *hdspm, int id, int val) | ||
880 | { | ||
881 | /* the hardware already does the relevant bit-mask with 0xff */ | ||
882 | if (id) | ||
883 | return hdspm_write(hdspm, HDSPM_midiDataOut1, val); | ||
884 | else | ||
885 | return hdspm_write(hdspm, HDSPM_midiDataOut0, val); | ||
886 | } | ||
887 | |||
888 | static inline int snd_hdspm_midi_input_available (hdspm_t *hdspm, int id) | ||
889 | { | ||
890 | if (id) | ||
891 | return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff); | ||
892 | else | ||
893 | return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff); | ||
894 | } | ||
895 | |||
896 | static inline int snd_hdspm_midi_output_possible (hdspm_t *hdspm, int id) | ||
897 | { | ||
898 | int fifo_bytes_used; | ||
899 | |||
900 | if (id) | ||
901 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff; | ||
902 | else | ||
903 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff; | ||
904 | |||
905 | if (fifo_bytes_used < 128) | ||
906 | return 128 - fifo_bytes_used; | ||
907 | else | ||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | static inline void snd_hdspm_flush_midi_input (hdspm_t *hdspm, int id) | ||
912 | { | ||
913 | while (snd_hdspm_midi_input_available (hdspm, id)) | ||
914 | snd_hdspm_midi_read_byte (hdspm, id); | ||
915 | } | ||
916 | |||
917 | static int snd_hdspm_midi_output_write (hdspm_midi_t *hmidi) | ||
918 | { | ||
919 | unsigned long flags; | ||
920 | int n_pending; | ||
921 | int to_write; | ||
922 | int i; | ||
923 | unsigned char buf[128]; | ||
924 | |||
925 | /* Output is not interrupt driven */ | ||
926 | |||
927 | spin_lock_irqsave (&hmidi->lock, flags); | ||
928 | if (hmidi->output) { | ||
929 | if (!snd_rawmidi_transmit_empty (hmidi->output)) { | ||
930 | if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) { | ||
931 | if (n_pending > (int)sizeof (buf)) | ||
932 | n_pending = sizeof (buf); | ||
933 | |||
934 | if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) { | ||
935 | for (i = 0; i < to_write; ++i) | ||
936 | snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]); | ||
937 | } | ||
938 | } | ||
939 | } | ||
940 | } | ||
941 | spin_unlock_irqrestore (&hmidi->lock, flags); | ||
942 | return 0; | ||
943 | } | ||
944 | |||
945 | static int snd_hdspm_midi_input_read (hdspm_midi_t *hmidi) | ||
946 | { | ||
947 | unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */ | ||
948 | unsigned long flags; | ||
949 | int n_pending; | ||
950 | int i; | ||
951 | |||
952 | spin_lock_irqsave (&hmidi->lock, flags); | ||
953 | if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) { | ||
954 | if (hmidi->input) { | ||
955 | if (n_pending > (int)sizeof (buf)) { | ||
956 | n_pending = sizeof (buf); | ||
957 | } | ||
958 | for (i = 0; i < n_pending; ++i) { | ||
959 | buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id); | ||
960 | } | ||
961 | if (n_pending) { | ||
962 | snd_rawmidi_receive (hmidi->input, buf, n_pending); | ||
963 | } | ||
964 | } else { | ||
965 | /* flush the MIDI input FIFO */ | ||
966 | while (n_pending--) { | ||
967 | snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id); | ||
968 | } | ||
969 | } | ||
970 | } | ||
971 | hmidi->pending = 0; | ||
972 | if (hmidi->id) { | ||
973 | hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable; | ||
974 | } else { | ||
975 | hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable; | ||
976 | } | ||
977 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register); | ||
978 | spin_unlock_irqrestore (&hmidi->lock, flags); | ||
979 | return snd_hdspm_midi_output_write (hmidi); | ||
980 | } | ||
981 | |||
982 | static void snd_hdspm_midi_input_trigger(snd_rawmidi_substream_t * substream, int up) | ||
983 | { | ||
984 | hdspm_t *hdspm; | ||
985 | hdspm_midi_t *hmidi; | ||
986 | unsigned long flags; | ||
987 | u32 ie; | ||
988 | |||
989 | hmidi = (hdspm_midi_t *) substream->rmidi->private_data; | ||
990 | hdspm = hmidi->hdspm; | ||
991 | ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable; | ||
992 | spin_lock_irqsave (&hdspm->lock, flags); | ||
993 | if (up) { | ||
994 | if (!(hdspm->control_register & ie)) { | ||
995 | snd_hdspm_flush_midi_input (hdspm, hmidi->id); | ||
996 | hdspm->control_register |= ie; | ||
997 | } | ||
998 | } else { | ||
999 | hdspm->control_register &= ~ie; | ||
1000 | } | ||
1001 | |||
1002 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
1003 | spin_unlock_irqrestore (&hdspm->lock, flags); | ||
1004 | } | ||
1005 | |||
1006 | static void snd_hdspm_midi_output_timer(unsigned long data) | ||
1007 | { | ||
1008 | hdspm_midi_t *hmidi = (hdspm_midi_t *) data; | ||
1009 | unsigned long flags; | ||
1010 | |||
1011 | snd_hdspm_midi_output_write(hmidi); | ||
1012 | spin_lock_irqsave (&hmidi->lock, flags); | ||
1013 | |||
1014 | /* this does not bump hmidi->istimer, because the | ||
1015 | kernel automatically removed the timer when it | ||
1016 | expired, and we are now adding it back, thus | ||
1017 | leaving istimer wherever it was set before. | ||
1018 | */ | ||
1019 | |||
1020 | if (hmidi->istimer) { | ||
1021 | hmidi->timer.expires = 1 + jiffies; | ||
1022 | add_timer(&hmidi->timer); | ||
1023 | } | ||
1024 | |||
1025 | spin_unlock_irqrestore (&hmidi->lock, flags); | ||
1026 | } | ||
1027 | |||
1028 | static void snd_hdspm_midi_output_trigger(snd_rawmidi_substream_t * substream, int up) | ||
1029 | { | ||
1030 | hdspm_midi_t *hmidi; | ||
1031 | unsigned long flags; | ||
1032 | |||
1033 | hmidi = (hdspm_midi_t *) substream->rmidi->private_data; | ||
1034 | spin_lock_irqsave (&hmidi->lock, flags); | ||
1035 | if (up) { | ||
1036 | if (!hmidi->istimer) { | ||
1037 | init_timer(&hmidi->timer); | ||
1038 | hmidi->timer.function = snd_hdspm_midi_output_timer; | ||
1039 | hmidi->timer.data = (unsigned long) hmidi; | ||
1040 | hmidi->timer.expires = 1 + jiffies; | ||
1041 | add_timer(&hmidi->timer); | ||
1042 | hmidi->istimer++; | ||
1043 | } | ||
1044 | } else { | ||
1045 | if (hmidi->istimer && --hmidi->istimer <= 0) { | ||
1046 | del_timer (&hmidi->timer); | ||
1047 | } | ||
1048 | } | ||
1049 | spin_unlock_irqrestore (&hmidi->lock, flags); | ||
1050 | if (up) | ||
1051 | snd_hdspm_midi_output_write(hmidi); | ||
1052 | } | ||
1053 | |||
1054 | static int snd_hdspm_midi_input_open(snd_rawmidi_substream_t * substream) | ||
1055 | { | ||
1056 | hdspm_midi_t *hmidi; | ||
1057 | |||
1058 | hmidi = (hdspm_midi_t *) substream->rmidi->private_data; | ||
1059 | spin_lock_irq (&hmidi->lock); | ||
1060 | snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id); | ||
1061 | hmidi->input = substream; | ||
1062 | spin_unlock_irq (&hmidi->lock); | ||
1063 | |||
1064 | return 0; | ||
1065 | } | ||
1066 | |||
1067 | static int snd_hdspm_midi_output_open(snd_rawmidi_substream_t * substream) | ||
1068 | { | ||
1069 | hdspm_midi_t *hmidi; | ||
1070 | |||
1071 | hmidi = (hdspm_midi_t *) substream->rmidi->private_data; | ||
1072 | spin_lock_irq (&hmidi->lock); | ||
1073 | hmidi->output = substream; | ||
1074 | spin_unlock_irq (&hmidi->lock); | ||
1075 | |||
1076 | return 0; | ||
1077 | } | ||
1078 | |||
1079 | static int snd_hdspm_midi_input_close(snd_rawmidi_substream_t * substream) | ||
1080 | { | ||
1081 | hdspm_midi_t *hmidi; | ||
1082 | |||
1083 | snd_hdspm_midi_input_trigger (substream, 0); | ||
1084 | |||
1085 | hmidi = (hdspm_midi_t *) substream->rmidi->private_data; | ||
1086 | spin_lock_irq (&hmidi->lock); | ||
1087 | hmidi->input = NULL; | ||
1088 | spin_unlock_irq (&hmidi->lock); | ||
1089 | |||
1090 | return 0; | ||
1091 | } | ||
1092 | |||
1093 | static int snd_hdspm_midi_output_close(snd_rawmidi_substream_t * substream) | ||
1094 | { | ||
1095 | hdspm_midi_t *hmidi; | ||
1096 | |||
1097 | snd_hdspm_midi_output_trigger (substream, 0); | ||
1098 | |||
1099 | hmidi = (hdspm_midi_t *) substream->rmidi->private_data; | ||
1100 | spin_lock_irq (&hmidi->lock); | ||
1101 | hmidi->output = NULL; | ||
1102 | spin_unlock_irq (&hmidi->lock); | ||
1103 | |||
1104 | return 0; | ||
1105 | } | ||
1106 | |||
1107 | snd_rawmidi_ops_t snd_hdspm_midi_output = | ||
1108 | { | ||
1109 | .open = snd_hdspm_midi_output_open, | ||
1110 | .close = snd_hdspm_midi_output_close, | ||
1111 | .trigger = snd_hdspm_midi_output_trigger, | ||
1112 | }; | ||
1113 | |||
1114 | snd_rawmidi_ops_t snd_hdspm_midi_input = | ||
1115 | { | ||
1116 | .open = snd_hdspm_midi_input_open, | ||
1117 | .close = snd_hdspm_midi_input_close, | ||
1118 | .trigger = snd_hdspm_midi_input_trigger, | ||
1119 | }; | ||
1120 | |||
1121 | static int __devinit snd_hdspm_create_midi (snd_card_t *card, hdspm_t *hdspm, int id) | ||
1122 | { | ||
1123 | int err; | ||
1124 | char buf[32]; | ||
1125 | |||
1126 | hdspm->midi[id].id = id; | ||
1127 | hdspm->midi[id].rmidi = NULL; | ||
1128 | hdspm->midi[id].input = NULL; | ||
1129 | hdspm->midi[id].output = NULL; | ||
1130 | hdspm->midi[id].hdspm = hdspm; | ||
1131 | hdspm->midi[id].istimer = 0; | ||
1132 | hdspm->midi[id].pending = 0; | ||
1133 | spin_lock_init (&hdspm->midi[id].lock); | ||
1134 | |||
1135 | sprintf (buf, "%s MIDI %d", card->shortname, id+1); | ||
1136 | if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0) | ||
1137 | return err; | ||
1138 | |||
1139 | sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1); | ||
1140 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; | ||
1141 | |||
1142 | snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output); | ||
1143 | snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input); | ||
1144 | |||
1145 | hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | | ||
1146 | SNDRV_RAWMIDI_INFO_INPUT | | ||
1147 | SNDRV_RAWMIDI_INFO_DUPLEX; | ||
1148 | |||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1152 | |||
1153 | static void hdspm_midi_tasklet(unsigned long arg) | ||
1154 | { | ||
1155 | hdspm_t *hdspm = (hdspm_t *)arg; | ||
1156 | |||
1157 | if (hdspm->midi[0].pending) | ||
1158 | snd_hdspm_midi_input_read (&hdspm->midi[0]); | ||
1159 | if (hdspm->midi[1].pending) | ||
1160 | snd_hdspm_midi_input_read (&hdspm->midi[1]); | ||
1161 | } | ||
1162 | |||
1163 | |||
1164 | /*----------------------------------------------------------------------------- | ||
1165 | Status Interface | ||
1166 | ----------------------------------------------------------------------------*/ | ||
1167 | |||
1168 | /* get the system sample rate which is set */ | ||
1169 | |||
1170 | #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ | ||
1171 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
1172 | .name = xname, \ | ||
1173 | .index = xindex, \ | ||
1174 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ | ||
1175 | .info = snd_hdspm_info_system_sample_rate, \ | ||
1176 | .get = snd_hdspm_get_system_sample_rate \ | ||
1177 | } | ||
1178 | |||
1179 | static int snd_hdspm_info_system_sample_rate(snd_kcontrol_t * kcontrol, | ||
1180 | snd_ctl_elem_info_t * uinfo) | ||
1181 | { | ||
1182 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1183 | uinfo->count = 1; | ||
1184 | return 0; | ||
1185 | } | ||
1186 | |||
1187 | static int snd_hdspm_get_system_sample_rate(snd_kcontrol_t * kcontrol, | ||
1188 | snd_ctl_elem_value_t * | ||
1189 | ucontrol) | ||
1190 | { | ||
1191 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1192 | |||
1193 | ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate; | ||
1194 | return 0; | ||
1195 | } | ||
1196 | |||
1197 | #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ | ||
1198 | { .iface = SNDRV_CTL_ELEM_IFACE_PCM, \ | ||
1199 | .name = xname, \ | ||
1200 | .index = xindex, \ | ||
1201 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ | ||
1202 | .info = snd_hdspm_info_autosync_sample_rate, \ | ||
1203 | .get = snd_hdspm_get_autosync_sample_rate \ | ||
1204 | } | ||
1205 | |||
1206 | static int snd_hdspm_info_autosync_sample_rate(snd_kcontrol_t * kcontrol, | ||
1207 | snd_ctl_elem_info_t * uinfo) | ||
1208 | { | ||
1209 | static char *texts[] = { "32000", "44100", "48000", | ||
1210 | "64000", "88200", "96000", | ||
1211 | "128000", "176400", "192000", | ||
1212 | "None" | ||
1213 | }; | ||
1214 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1215 | uinfo->count = 1; | ||
1216 | uinfo->value.enumerated.items = 10; | ||
1217 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
1218 | uinfo->value.enumerated.item = | ||
1219 | uinfo->value.enumerated.items - 1; | ||
1220 | strcpy(uinfo->value.enumerated.name, | ||
1221 | texts[uinfo->value.enumerated.item]); | ||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1225 | static int snd_hdspm_get_autosync_sample_rate(snd_kcontrol_t * kcontrol, | ||
1226 | snd_ctl_elem_value_t * | ||
1227 | ucontrol) | ||
1228 | { | ||
1229 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1230 | |||
1231 | switch (hdspm_external_sample_rate(hdspm)) { | ||
1232 | case 32000: | ||
1233 | ucontrol->value.enumerated.item[0] = 0; | ||
1234 | break; | ||
1235 | case 44100: | ||
1236 | ucontrol->value.enumerated.item[0] = 1; | ||
1237 | break; | ||
1238 | case 48000: | ||
1239 | ucontrol->value.enumerated.item[0] = 2; | ||
1240 | break; | ||
1241 | case 64000: | ||
1242 | ucontrol->value.enumerated.item[0] = 3; | ||
1243 | break; | ||
1244 | case 88200: | ||
1245 | ucontrol->value.enumerated.item[0] = 4; | ||
1246 | break; | ||
1247 | case 96000: | ||
1248 | ucontrol->value.enumerated.item[0] = 5; | ||
1249 | break; | ||
1250 | case 128000: | ||
1251 | ucontrol->value.enumerated.item[0] = 6; | ||
1252 | break; | ||
1253 | case 176400: | ||
1254 | ucontrol->value.enumerated.item[0] = 7; | ||
1255 | break; | ||
1256 | case 192000: | ||
1257 | ucontrol->value.enumerated.item[0] = 8; | ||
1258 | break; | ||
1259 | |||
1260 | default: | ||
1261 | ucontrol->value.enumerated.item[0] = 9; | ||
1262 | } | ||
1263 | return 0; | ||
1264 | } | ||
1265 | |||
1266 | #define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \ | ||
1267 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
1268 | .name = xname, \ | ||
1269 | .index = xindex, \ | ||
1270 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ | ||
1271 | .info = snd_hdspm_info_system_clock_mode, \ | ||
1272 | .get = snd_hdspm_get_system_clock_mode, \ | ||
1273 | } | ||
1274 | |||
1275 | |||
1276 | |||
1277 | static int hdspm_system_clock_mode(hdspm_t * hdspm) | ||
1278 | { | ||
1279 | /* Always reflect the hardware info, rme is never wrong !!!! */ | ||
1280 | |||
1281 | if (hdspm->control_register & HDSPM_ClockModeMaster) | ||
1282 | return 0; | ||
1283 | return 1; | ||
1284 | } | ||
1285 | |||
1286 | static int snd_hdspm_info_system_clock_mode(snd_kcontrol_t * kcontrol, | ||
1287 | snd_ctl_elem_info_t * uinfo) | ||
1288 | { | ||
1289 | static char *texts[] = { "Master", "Slave" }; | ||
1290 | |||
1291 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1292 | uinfo->count = 1; | ||
1293 | uinfo->value.enumerated.items = 2; | ||
1294 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
1295 | uinfo->value.enumerated.item = | ||
1296 | uinfo->value.enumerated.items - 1; | ||
1297 | strcpy(uinfo->value.enumerated.name, | ||
1298 | texts[uinfo->value.enumerated.item]); | ||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1302 | static int snd_hdspm_get_system_clock_mode(snd_kcontrol_t * kcontrol, | ||
1303 | snd_ctl_elem_value_t * ucontrol) | ||
1304 | { | ||
1305 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1306 | |||
1307 | ucontrol->value.enumerated.item[0] = | ||
1308 | hdspm_system_clock_mode(hdspm); | ||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | #define HDSPM_CLOCK_SOURCE(xname, xindex) \ | ||
1313 | { .iface = SNDRV_CTL_ELEM_IFACE_PCM, \ | ||
1314 | .name = xname, \ | ||
1315 | .index = xindex, \ | ||
1316 | .info = snd_hdspm_info_clock_source, \ | ||
1317 | .get = snd_hdspm_get_clock_source, \ | ||
1318 | .put = snd_hdspm_put_clock_source \ | ||
1319 | } | ||
1320 | |||
1321 | static int hdspm_clock_source(hdspm_t * hdspm) | ||
1322 | { | ||
1323 | if (hdspm->control_register & HDSPM_ClockModeMaster) { | ||
1324 | switch (hdspm->system_sample_rate) { | ||
1325 | case 32000: | ||
1326 | return 1; | ||
1327 | case 44100: | ||
1328 | return 2; | ||
1329 | case 48000: | ||
1330 | return 3; | ||
1331 | case 64000: | ||
1332 | return 4; | ||
1333 | case 88200: | ||
1334 | return 5; | ||
1335 | case 96000: | ||
1336 | return 6; | ||
1337 | case 128000: | ||
1338 | return 7; | ||
1339 | case 176400: | ||
1340 | return 8; | ||
1341 | case 192000: | ||
1342 | return 9; | ||
1343 | default: | ||
1344 | return 3; | ||
1345 | } | ||
1346 | } else { | ||
1347 | return 0; | ||
1348 | } | ||
1349 | } | ||
1350 | |||
1351 | static int hdspm_set_clock_source(hdspm_t * hdspm, int mode) | ||
1352 | { | ||
1353 | int rate; | ||
1354 | switch (mode) { | ||
1355 | |||
1356 | case HDSPM_CLOCK_SOURCE_AUTOSYNC: | ||
1357 | if (hdspm_external_sample_rate(hdspm) != 0) { | ||
1358 | hdspm->control_register &= ~HDSPM_ClockModeMaster; | ||
1359 | hdspm_write(hdspm, HDSPM_controlRegister, | ||
1360 | hdspm->control_register); | ||
1361 | return 0; | ||
1362 | } | ||
1363 | return -1; | ||
1364 | case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: | ||
1365 | rate = 32000; | ||
1366 | break; | ||
1367 | case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: | ||
1368 | rate = 44100; | ||
1369 | break; | ||
1370 | case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: | ||
1371 | rate = 48000; | ||
1372 | break; | ||
1373 | case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: | ||
1374 | rate = 64000; | ||
1375 | break; | ||
1376 | case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: | ||
1377 | rate = 88200; | ||
1378 | break; | ||
1379 | case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: | ||
1380 | rate = 96000; | ||
1381 | break; | ||
1382 | case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ: | ||
1383 | rate = 128000; | ||
1384 | break; | ||
1385 | case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ: | ||
1386 | rate = 176400; | ||
1387 | break; | ||
1388 | case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ: | ||
1389 | rate = 192000; | ||
1390 | break; | ||
1391 | |||
1392 | default: | ||
1393 | rate = 44100; | ||
1394 | } | ||
1395 | hdspm->control_register |= HDSPM_ClockModeMaster; | ||
1396 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
1397 | hdspm_set_rate(hdspm, rate, 1); | ||
1398 | return 0; | ||
1399 | } | ||
1400 | |||
1401 | static int snd_hdspm_info_clock_source(snd_kcontrol_t * kcontrol, | ||
1402 | snd_ctl_elem_info_t * uinfo) | ||
1403 | { | ||
1404 | static char *texts[] = { "AutoSync", | ||
1405 | "Internal 32.0 kHz", "Internal 44.1 kHz", | ||
1406 | "Internal 48.0 kHz", | ||
1407 | "Internal 64.0 kHz", "Internal 88.2 kHz", | ||
1408 | "Internal 96.0 kHz", | ||
1409 | "Internal 128.0 kHz", "Internal 176.4 kHz", | ||
1410 | "Internal 192.0 kHz" | ||
1411 | }; | ||
1412 | |||
1413 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1414 | uinfo->count = 1; | ||
1415 | uinfo->value.enumerated.items = 10; | ||
1416 | |||
1417 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
1418 | uinfo->value.enumerated.item = | ||
1419 | uinfo->value.enumerated.items - 1; | ||
1420 | |||
1421 | strcpy(uinfo->value.enumerated.name, | ||
1422 | texts[uinfo->value.enumerated.item]); | ||
1423 | |||
1424 | return 0; | ||
1425 | } | ||
1426 | |||
1427 | static int snd_hdspm_get_clock_source(snd_kcontrol_t * kcontrol, | ||
1428 | snd_ctl_elem_value_t * ucontrol) | ||
1429 | { | ||
1430 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1431 | |||
1432 | ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm); | ||
1433 | return 0; | ||
1434 | } | ||
1435 | |||
1436 | static int snd_hdspm_put_clock_source(snd_kcontrol_t * kcontrol, | ||
1437 | snd_ctl_elem_value_t * ucontrol) | ||
1438 | { | ||
1439 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1440 | int change; | ||
1441 | int val; | ||
1442 | |||
1443 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
1444 | return -EBUSY; | ||
1445 | val = ucontrol->value.enumerated.item[0]; | ||
1446 | if (val < 0) | ||
1447 | val = 0; | ||
1448 | if (val > 6) | ||
1449 | val = 6; | ||
1450 | spin_lock_irq(&hdspm->lock); | ||
1451 | if (val != hdspm_clock_source(hdspm)) | ||
1452 | change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0; | ||
1453 | else | ||
1454 | change = 0; | ||
1455 | spin_unlock_irq(&hdspm->lock); | ||
1456 | return change; | ||
1457 | } | ||
1458 | |||
1459 | #define HDSPM_PREF_SYNC_REF(xname, xindex) \ | ||
1460 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
1461 | .name = xname, \ | ||
1462 | .index = xindex, \ | ||
1463 | .info = snd_hdspm_info_pref_sync_ref, \ | ||
1464 | .get = snd_hdspm_get_pref_sync_ref, \ | ||
1465 | .put = snd_hdspm_put_pref_sync_ref \ | ||
1466 | } | ||
1467 | |||
1468 | static int hdspm_pref_sync_ref(hdspm_t * hdspm) | ||
1469 | { | ||
1470 | /* Notice that this looks at the requested sync source, | ||
1471 | not the one actually in use. | ||
1472 | */ | ||
1473 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | ||
1474 | case HDSPM_SyncRef_Word: | ||
1475 | return HDSPM_SYNC_FROM_WORD; | ||
1476 | case HDSPM_SyncRef_MADI: | ||
1477 | return HDSPM_SYNC_FROM_MADI; | ||
1478 | } | ||
1479 | |||
1480 | return HDSPM_SYNC_FROM_WORD; | ||
1481 | } | ||
1482 | |||
1483 | static int hdspm_set_pref_sync_ref(hdspm_t * hdspm, int pref) | ||
1484 | { | ||
1485 | hdspm->control_register &= ~HDSPM_SyncRefMask; | ||
1486 | |||
1487 | switch (pref) { | ||
1488 | case HDSPM_SYNC_FROM_MADI: | ||
1489 | hdspm->control_register |= HDSPM_SyncRef_MADI; | ||
1490 | break; | ||
1491 | case HDSPM_SYNC_FROM_WORD: | ||
1492 | hdspm->control_register |= HDSPM_SyncRef_Word; | ||
1493 | break; | ||
1494 | default: | ||
1495 | return -1; | ||
1496 | } | ||
1497 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
1498 | return 0; | ||
1499 | } | ||
1500 | |||
1501 | static int snd_hdspm_info_pref_sync_ref(snd_kcontrol_t * kcontrol, | ||
1502 | snd_ctl_elem_info_t * uinfo) | ||
1503 | { | ||
1504 | static char *texts[] = { "Word", "MADI" }; | ||
1505 | |||
1506 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1507 | uinfo->count = 1; | ||
1508 | |||
1509 | uinfo->value.enumerated.items = 2; | ||
1510 | |||
1511 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
1512 | uinfo->value.enumerated.item = | ||
1513 | uinfo->value.enumerated.items - 1; | ||
1514 | strcpy(uinfo->value.enumerated.name, | ||
1515 | texts[uinfo->value.enumerated.item]); | ||
1516 | return 0; | ||
1517 | } | ||
1518 | |||
1519 | static int snd_hdspm_get_pref_sync_ref(snd_kcontrol_t * kcontrol, | ||
1520 | snd_ctl_elem_value_t * ucontrol) | ||
1521 | { | ||
1522 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1523 | |||
1524 | ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm); | ||
1525 | return 0; | ||
1526 | } | ||
1527 | |||
1528 | static int snd_hdspm_put_pref_sync_ref(snd_kcontrol_t * kcontrol, | ||
1529 | snd_ctl_elem_value_t * ucontrol) | ||
1530 | { | ||
1531 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1532 | int change, max; | ||
1533 | unsigned int val; | ||
1534 | |||
1535 | max = 2; | ||
1536 | |||
1537 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
1538 | return -EBUSY; | ||
1539 | |||
1540 | val = ucontrol->value.enumerated.item[0] % max; | ||
1541 | |||
1542 | spin_lock_irq(&hdspm->lock); | ||
1543 | change = (int) val != hdspm_pref_sync_ref(hdspm); | ||
1544 | hdspm_set_pref_sync_ref(hdspm, val); | ||
1545 | spin_unlock_irq(&hdspm->lock); | ||
1546 | return change; | ||
1547 | } | ||
1548 | |||
1549 | #define HDSPM_AUTOSYNC_REF(xname, xindex) \ | ||
1550 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
1551 | .name = xname, \ | ||
1552 | .index = xindex, \ | ||
1553 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ | ||
1554 | .info = snd_hdspm_info_autosync_ref, \ | ||
1555 | .get = snd_hdspm_get_autosync_ref, \ | ||
1556 | } | ||
1557 | |||
1558 | static int hdspm_autosync_ref(hdspm_t * hdspm) | ||
1559 | { | ||
1560 | /* This looks at the autosync selected sync reference */ | ||
1561 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
1562 | |||
1563 | switch (status2 & HDSPM_SelSyncRefMask) { | ||
1564 | |||
1565 | case HDSPM_SelSyncRef_WORD: | ||
1566 | return HDSPM_AUTOSYNC_FROM_WORD; | ||
1567 | |||
1568 | case HDSPM_SelSyncRef_MADI: | ||
1569 | return HDSPM_AUTOSYNC_FROM_MADI; | ||
1570 | |||
1571 | case HDSPM_SelSyncRef_NVALID: | ||
1572 | return HDSPM_AUTOSYNC_FROM_NONE; | ||
1573 | |||
1574 | default: | ||
1575 | return 0; | ||
1576 | } | ||
1577 | |||
1578 | return 0; | ||
1579 | } | ||
1580 | |||
1581 | static int snd_hdspm_info_autosync_ref(snd_kcontrol_t * kcontrol, | ||
1582 | snd_ctl_elem_info_t * uinfo) | ||
1583 | { | ||
1584 | static char *texts[] = { "WordClock", "MADI", "None" }; | ||
1585 | |||
1586 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1587 | uinfo->count = 1; | ||
1588 | uinfo->value.enumerated.items = 3; | ||
1589 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
1590 | uinfo->value.enumerated.item = | ||
1591 | uinfo->value.enumerated.items - 1; | ||
1592 | strcpy(uinfo->value.enumerated.name, | ||
1593 | texts[uinfo->value.enumerated.item]); | ||
1594 | return 0; | ||
1595 | } | ||
1596 | |||
1597 | static int snd_hdspm_get_autosync_ref(snd_kcontrol_t * kcontrol, | ||
1598 | snd_ctl_elem_value_t * ucontrol) | ||
1599 | { | ||
1600 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1601 | |||
1602 | ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm); | ||
1603 | return 0; | ||
1604 | } | ||
1605 | |||
1606 | #define HDSPM_LINE_OUT(xname, xindex) \ | ||
1607 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
1608 | .name = xname, \ | ||
1609 | .index = xindex, \ | ||
1610 | .info = snd_hdspm_info_line_out, \ | ||
1611 | .get = snd_hdspm_get_line_out, \ | ||
1612 | .put = snd_hdspm_put_line_out \ | ||
1613 | } | ||
1614 | |||
1615 | static int hdspm_line_out(hdspm_t * hdspm) | ||
1616 | { | ||
1617 | return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0; | ||
1618 | } | ||
1619 | |||
1620 | |||
1621 | static int hdspm_set_line_output(hdspm_t * hdspm, int out) | ||
1622 | { | ||
1623 | if (out) | ||
1624 | hdspm->control_register |= HDSPM_LineOut; | ||
1625 | else | ||
1626 | hdspm->control_register &= ~HDSPM_LineOut; | ||
1627 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
1628 | |||
1629 | return 0; | ||
1630 | } | ||
1631 | |||
1632 | static int snd_hdspm_info_line_out(snd_kcontrol_t * kcontrol, | ||
1633 | snd_ctl_elem_info_t * uinfo) | ||
1634 | { | ||
1635 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1636 | uinfo->count = 1; | ||
1637 | uinfo->value.integer.min = 0; | ||
1638 | uinfo->value.integer.max = 1; | ||
1639 | return 0; | ||
1640 | } | ||
1641 | |||
1642 | static int snd_hdspm_get_line_out(snd_kcontrol_t * kcontrol, | ||
1643 | snd_ctl_elem_value_t * ucontrol) | ||
1644 | { | ||
1645 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1646 | |||
1647 | spin_lock_irq(&hdspm->lock); | ||
1648 | ucontrol->value.integer.value[0] = hdspm_line_out(hdspm); | ||
1649 | spin_unlock_irq(&hdspm->lock); | ||
1650 | return 0; | ||
1651 | } | ||
1652 | |||
1653 | static int snd_hdspm_put_line_out(snd_kcontrol_t * kcontrol, | ||
1654 | snd_ctl_elem_value_t * ucontrol) | ||
1655 | { | ||
1656 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1657 | int change; | ||
1658 | unsigned int val; | ||
1659 | |||
1660 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
1661 | return -EBUSY; | ||
1662 | val = ucontrol->value.integer.value[0] & 1; | ||
1663 | spin_lock_irq(&hdspm->lock); | ||
1664 | change = (int) val != hdspm_line_out(hdspm); | ||
1665 | hdspm_set_line_output(hdspm, val); | ||
1666 | spin_unlock_irq(&hdspm->lock); | ||
1667 | return change; | ||
1668 | } | ||
1669 | |||
1670 | #define HDSPM_TX_64(xname, xindex) \ | ||
1671 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
1672 | .name = xname, \ | ||
1673 | .index = xindex, \ | ||
1674 | .info = snd_hdspm_info_tx_64, \ | ||
1675 | .get = snd_hdspm_get_tx_64, \ | ||
1676 | .put = snd_hdspm_put_tx_64 \ | ||
1677 | } | ||
1678 | |||
1679 | static int hdspm_tx_64(hdspm_t * hdspm) | ||
1680 | { | ||
1681 | return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0; | ||
1682 | } | ||
1683 | |||
1684 | static int hdspm_set_tx_64(hdspm_t * hdspm, int out) | ||
1685 | { | ||
1686 | if (out) | ||
1687 | hdspm->control_register |= HDSPM_TX_64ch; | ||
1688 | else | ||
1689 | hdspm->control_register &= ~HDSPM_TX_64ch; | ||
1690 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
1691 | |||
1692 | return 0; | ||
1693 | } | ||
1694 | |||
1695 | static int snd_hdspm_info_tx_64(snd_kcontrol_t * kcontrol, | ||
1696 | snd_ctl_elem_info_t * uinfo) | ||
1697 | { | ||
1698 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1699 | uinfo->count = 1; | ||
1700 | uinfo->value.integer.min = 0; | ||
1701 | uinfo->value.integer.max = 1; | ||
1702 | return 0; | ||
1703 | } | ||
1704 | |||
1705 | static int snd_hdspm_get_tx_64(snd_kcontrol_t * kcontrol, | ||
1706 | snd_ctl_elem_value_t * ucontrol) | ||
1707 | { | ||
1708 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1709 | |||
1710 | spin_lock_irq(&hdspm->lock); | ||
1711 | ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm); | ||
1712 | spin_unlock_irq(&hdspm->lock); | ||
1713 | return 0; | ||
1714 | } | ||
1715 | |||
1716 | static int snd_hdspm_put_tx_64(snd_kcontrol_t * kcontrol, | ||
1717 | snd_ctl_elem_value_t * ucontrol) | ||
1718 | { | ||
1719 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1720 | int change; | ||
1721 | unsigned int val; | ||
1722 | |||
1723 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
1724 | return -EBUSY; | ||
1725 | val = ucontrol->value.integer.value[0] & 1; | ||
1726 | spin_lock_irq(&hdspm->lock); | ||
1727 | change = (int) val != hdspm_tx_64(hdspm); | ||
1728 | hdspm_set_tx_64(hdspm, val); | ||
1729 | spin_unlock_irq(&hdspm->lock); | ||
1730 | return change; | ||
1731 | } | ||
1732 | |||
1733 | #define HDSPM_C_TMS(xname, xindex) \ | ||
1734 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
1735 | .name = xname, \ | ||
1736 | .index = xindex, \ | ||
1737 | .info = snd_hdspm_info_c_tms, \ | ||
1738 | .get = snd_hdspm_get_c_tms, \ | ||
1739 | .put = snd_hdspm_put_c_tms \ | ||
1740 | } | ||
1741 | |||
1742 | static int hdspm_c_tms(hdspm_t * hdspm) | ||
1743 | { | ||
1744 | return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0; | ||
1745 | } | ||
1746 | |||
1747 | static int hdspm_set_c_tms(hdspm_t * hdspm, int out) | ||
1748 | { | ||
1749 | if (out) | ||
1750 | hdspm->control_register |= HDSPM_clr_tms; | ||
1751 | else | ||
1752 | hdspm->control_register &= ~HDSPM_clr_tms; | ||
1753 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
1754 | |||
1755 | return 0; | ||
1756 | } | ||
1757 | |||
1758 | static int snd_hdspm_info_c_tms(snd_kcontrol_t * kcontrol, | ||
1759 | snd_ctl_elem_info_t * uinfo) | ||
1760 | { | ||
1761 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1762 | uinfo->count = 1; | ||
1763 | uinfo->value.integer.min = 0; | ||
1764 | uinfo->value.integer.max = 1; | ||
1765 | return 0; | ||
1766 | } | ||
1767 | |||
1768 | static int snd_hdspm_get_c_tms(snd_kcontrol_t * kcontrol, | ||
1769 | snd_ctl_elem_value_t * ucontrol) | ||
1770 | { | ||
1771 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1772 | |||
1773 | spin_lock_irq(&hdspm->lock); | ||
1774 | ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm); | ||
1775 | spin_unlock_irq(&hdspm->lock); | ||
1776 | return 0; | ||
1777 | } | ||
1778 | |||
1779 | static int snd_hdspm_put_c_tms(snd_kcontrol_t * kcontrol, | ||
1780 | snd_ctl_elem_value_t * ucontrol) | ||
1781 | { | ||
1782 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1783 | int change; | ||
1784 | unsigned int val; | ||
1785 | |||
1786 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
1787 | return -EBUSY; | ||
1788 | val = ucontrol->value.integer.value[0] & 1; | ||
1789 | spin_lock_irq(&hdspm->lock); | ||
1790 | change = (int) val != hdspm_c_tms(hdspm); | ||
1791 | hdspm_set_c_tms(hdspm, val); | ||
1792 | spin_unlock_irq(&hdspm->lock); | ||
1793 | return change; | ||
1794 | } | ||
1795 | |||
1796 | #define HDSPM_SAFE_MODE(xname, xindex) \ | ||
1797 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
1798 | .name = xname, \ | ||
1799 | .index = xindex, \ | ||
1800 | .info = snd_hdspm_info_safe_mode, \ | ||
1801 | .get = snd_hdspm_get_safe_mode, \ | ||
1802 | .put = snd_hdspm_put_safe_mode \ | ||
1803 | } | ||
1804 | |||
1805 | static int hdspm_safe_mode(hdspm_t * hdspm) | ||
1806 | { | ||
1807 | return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0; | ||
1808 | } | ||
1809 | |||
1810 | static int hdspm_set_safe_mode(hdspm_t * hdspm, int out) | ||
1811 | { | ||
1812 | if (out) | ||
1813 | hdspm->control_register |= HDSPM_AutoInp; | ||
1814 | else | ||
1815 | hdspm->control_register &= ~HDSPM_AutoInp; | ||
1816 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
1817 | |||
1818 | return 0; | ||
1819 | } | ||
1820 | |||
1821 | static int snd_hdspm_info_safe_mode(snd_kcontrol_t * kcontrol, | ||
1822 | snd_ctl_elem_info_t * uinfo) | ||
1823 | { | ||
1824 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1825 | uinfo->count = 1; | ||
1826 | uinfo->value.integer.min = 0; | ||
1827 | uinfo->value.integer.max = 1; | ||
1828 | return 0; | ||
1829 | } | ||
1830 | |||
1831 | static int snd_hdspm_get_safe_mode(snd_kcontrol_t * kcontrol, | ||
1832 | snd_ctl_elem_value_t * ucontrol) | ||
1833 | { | ||
1834 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1835 | |||
1836 | spin_lock_irq(&hdspm->lock); | ||
1837 | ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm); | ||
1838 | spin_unlock_irq(&hdspm->lock); | ||
1839 | return 0; | ||
1840 | } | ||
1841 | |||
1842 | static int snd_hdspm_put_safe_mode(snd_kcontrol_t * kcontrol, | ||
1843 | snd_ctl_elem_value_t * ucontrol) | ||
1844 | { | ||
1845 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1846 | int change; | ||
1847 | unsigned int val; | ||
1848 | |||
1849 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
1850 | return -EBUSY; | ||
1851 | val = ucontrol->value.integer.value[0] & 1; | ||
1852 | spin_lock_irq(&hdspm->lock); | ||
1853 | change = (int) val != hdspm_safe_mode(hdspm); | ||
1854 | hdspm_set_safe_mode(hdspm, val); | ||
1855 | spin_unlock_irq(&hdspm->lock); | ||
1856 | return change; | ||
1857 | } | ||
1858 | |||
1859 | #define HDSPM_INPUT_SELECT(xname, xindex) \ | ||
1860 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
1861 | .name = xname, \ | ||
1862 | .index = xindex, \ | ||
1863 | .info = snd_hdspm_info_input_select, \ | ||
1864 | .get = snd_hdspm_get_input_select, \ | ||
1865 | .put = snd_hdspm_put_input_select \ | ||
1866 | } | ||
1867 | |||
1868 | static int hdspm_input_select(hdspm_t * hdspm) | ||
1869 | { | ||
1870 | return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0; | ||
1871 | } | ||
1872 | |||
1873 | static int hdspm_set_input_select(hdspm_t * hdspm, int out) | ||
1874 | { | ||
1875 | if (out) | ||
1876 | hdspm->control_register |= HDSPM_InputSelect0; | ||
1877 | else | ||
1878 | hdspm->control_register &= ~HDSPM_InputSelect0; | ||
1879 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
1880 | |||
1881 | return 0; | ||
1882 | } | ||
1883 | |||
1884 | static int snd_hdspm_info_input_select(snd_kcontrol_t * kcontrol, | ||
1885 | snd_ctl_elem_info_t * uinfo) | ||
1886 | { | ||
1887 | static char *texts[] = { "optical", "coaxial" }; | ||
1888 | |||
1889 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1890 | uinfo->count = 1; | ||
1891 | uinfo->value.enumerated.items = 2; | ||
1892 | |||
1893 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
1894 | uinfo->value.enumerated.item = | ||
1895 | uinfo->value.enumerated.items - 1; | ||
1896 | strcpy(uinfo->value.enumerated.name, | ||
1897 | texts[uinfo->value.enumerated.item]); | ||
1898 | |||
1899 | return 0; | ||
1900 | } | ||
1901 | |||
1902 | static int snd_hdspm_get_input_select(snd_kcontrol_t * kcontrol, | ||
1903 | snd_ctl_elem_value_t * ucontrol) | ||
1904 | { | ||
1905 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1906 | |||
1907 | spin_lock_irq(&hdspm->lock); | ||
1908 | ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm); | ||
1909 | spin_unlock_irq(&hdspm->lock); | ||
1910 | return 0; | ||
1911 | } | ||
1912 | |||
1913 | static int snd_hdspm_put_input_select(snd_kcontrol_t * kcontrol, | ||
1914 | snd_ctl_elem_value_t * ucontrol) | ||
1915 | { | ||
1916 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1917 | int change; | ||
1918 | unsigned int val; | ||
1919 | |||
1920 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
1921 | return -EBUSY; | ||
1922 | val = ucontrol->value.integer.value[0] & 1; | ||
1923 | spin_lock_irq(&hdspm->lock); | ||
1924 | change = (int) val != hdspm_input_select(hdspm); | ||
1925 | hdspm_set_input_select(hdspm, val); | ||
1926 | spin_unlock_irq(&hdspm->lock); | ||
1927 | return change; | ||
1928 | } | ||
1929 | |||
1930 | /* Simple Mixer | ||
1931 | deprecated since to much faders ??? | ||
1932 | MIXER interface says output (source, destination, value) | ||
1933 | where source > MAX_channels are playback channels | ||
1934 | on MADICARD | ||
1935 | - playback mixer matrix: [channelout+64] [output] [value] | ||
1936 | - input(thru) mixer matrix: [channelin] [output] [value] | ||
1937 | (better do 2 kontrols for seperation ?) | ||
1938 | */ | ||
1939 | |||
1940 | #define HDSPM_MIXER(xname, xindex) \ | ||
1941 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
1942 | .name = xname, \ | ||
1943 | .index = xindex, \ | ||
1944 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
1945 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
1946 | .info = snd_hdspm_info_mixer, \ | ||
1947 | .get = snd_hdspm_get_mixer, \ | ||
1948 | .put = snd_hdspm_put_mixer \ | ||
1949 | } | ||
1950 | |||
1951 | static int snd_hdspm_info_mixer(snd_kcontrol_t * kcontrol, | ||
1952 | snd_ctl_elem_info_t * uinfo) | ||
1953 | { | ||
1954 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1955 | uinfo->count = 3; | ||
1956 | uinfo->value.integer.min = 0; | ||
1957 | uinfo->value.integer.max = 65535; | ||
1958 | uinfo->value.integer.step = 1; | ||
1959 | return 0; | ||
1960 | } | ||
1961 | |||
1962 | static int snd_hdspm_get_mixer(snd_kcontrol_t * kcontrol, | ||
1963 | snd_ctl_elem_value_t * ucontrol) | ||
1964 | { | ||
1965 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1966 | int source; | ||
1967 | int destination; | ||
1968 | |||
1969 | source = ucontrol->value.integer.value[0]; | ||
1970 | if (source < 0) | ||
1971 | source = 0; | ||
1972 | else if (source >= 2 * HDSPM_MAX_CHANNELS) | ||
1973 | source = 2 * HDSPM_MAX_CHANNELS - 1; | ||
1974 | |||
1975 | destination = ucontrol->value.integer.value[1]; | ||
1976 | if (destination < 0) | ||
1977 | destination = 0; | ||
1978 | else if (destination >= HDSPM_MAX_CHANNELS) | ||
1979 | destination = HDSPM_MAX_CHANNELS - 1; | ||
1980 | |||
1981 | spin_lock_irq(&hdspm->lock); | ||
1982 | if (source >= HDSPM_MAX_CHANNELS) | ||
1983 | ucontrol->value.integer.value[2] = | ||
1984 | hdspm_read_pb_gain(hdspm, destination, | ||
1985 | source - HDSPM_MAX_CHANNELS); | ||
1986 | else | ||
1987 | ucontrol->value.integer.value[2] = | ||
1988 | hdspm_read_in_gain(hdspm, destination, source); | ||
1989 | |||
1990 | spin_unlock_irq(&hdspm->lock); | ||
1991 | |||
1992 | return 0; | ||
1993 | } | ||
1994 | |||
1995 | static int snd_hdspm_put_mixer(snd_kcontrol_t * kcontrol, | ||
1996 | snd_ctl_elem_value_t * ucontrol) | ||
1997 | { | ||
1998 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
1999 | int change; | ||
2000 | int source; | ||
2001 | int destination; | ||
2002 | int gain; | ||
2003 | |||
2004 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
2005 | return -EBUSY; | ||
2006 | |||
2007 | source = ucontrol->value.integer.value[0]; | ||
2008 | destination = ucontrol->value.integer.value[1]; | ||
2009 | |||
2010 | if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS) | ||
2011 | return -1; | ||
2012 | if (destination < 0 || destination >= HDSPM_MAX_CHANNELS) | ||
2013 | return -1; | ||
2014 | |||
2015 | gain = ucontrol->value.integer.value[2]; | ||
2016 | |||
2017 | spin_lock_irq(&hdspm->lock); | ||
2018 | |||
2019 | if (source >= HDSPM_MAX_CHANNELS) | ||
2020 | change = gain != hdspm_read_pb_gain(hdspm, destination, | ||
2021 | source - | ||
2022 | HDSPM_MAX_CHANNELS); | ||
2023 | else | ||
2024 | change = | ||
2025 | gain != hdspm_read_in_gain(hdspm, destination, source); | ||
2026 | |||
2027 | if (change) { | ||
2028 | if (source >= HDSPM_MAX_CHANNELS) | ||
2029 | hdspm_write_pb_gain(hdspm, destination, | ||
2030 | source - HDSPM_MAX_CHANNELS, | ||
2031 | gain); | ||
2032 | else | ||
2033 | hdspm_write_in_gain(hdspm, destination, source, | ||
2034 | gain); | ||
2035 | } | ||
2036 | spin_unlock_irq(&hdspm->lock); | ||
2037 | |||
2038 | return change; | ||
2039 | } | ||
2040 | |||
2041 | /* The simple mixer control(s) provide gain control for the | ||
2042 | basic 1:1 mappings of playback streams to output | ||
2043 | streams. | ||
2044 | */ | ||
2045 | |||
2046 | #define HDSPM_PLAYBACK_MIXER \ | ||
2047 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2048 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \ | ||
2049 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2050 | .info = snd_hdspm_info_playback_mixer, \ | ||
2051 | .get = snd_hdspm_get_playback_mixer, \ | ||
2052 | .put = snd_hdspm_put_playback_mixer \ | ||
2053 | } | ||
2054 | |||
2055 | static int snd_hdspm_info_playback_mixer(snd_kcontrol_t * kcontrol, | ||
2056 | snd_ctl_elem_info_t * uinfo) | ||
2057 | { | ||
2058 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2059 | uinfo->count = 1; | ||
2060 | uinfo->value.integer.min = 0; | ||
2061 | uinfo->value.integer.max = 65536; | ||
2062 | uinfo->value.integer.step = 1; | ||
2063 | return 0; | ||
2064 | } | ||
2065 | |||
2066 | static int snd_hdspm_get_playback_mixer(snd_kcontrol_t * kcontrol, | ||
2067 | snd_ctl_elem_value_t * ucontrol) | ||
2068 | { | ||
2069 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
2070 | int channel; | ||
2071 | int mapped_channel; | ||
2072 | |||
2073 | channel = ucontrol->id.index - 1; | ||
2074 | |||
2075 | snd_assert(channel >= 0 | ||
2076 | || channel < HDSPM_MAX_CHANNELS, return -EINVAL); | ||
2077 | |||
2078 | if ((mapped_channel = hdspm->channel_map[channel]) < 0) | ||
2079 | return -EINVAL; | ||
2080 | |||
2081 | spin_lock_irq(&hdspm->lock); | ||
2082 | ucontrol->value.integer.value[0] = | ||
2083 | hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel); | ||
2084 | spin_unlock_irq(&hdspm->lock); | ||
2085 | |||
2086 | /* snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n", | ||
2087 | ucontrol->id.index, channel, mapped_channel, ucontrol->value.integer.value[0]); | ||
2088 | */ | ||
2089 | |||
2090 | return 0; | ||
2091 | } | ||
2092 | |||
2093 | static int snd_hdspm_put_playback_mixer(snd_kcontrol_t * kcontrol, | ||
2094 | snd_ctl_elem_value_t * ucontrol) | ||
2095 | { | ||
2096 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
2097 | int change; | ||
2098 | int channel; | ||
2099 | int mapped_channel; | ||
2100 | int gain; | ||
2101 | |||
2102 | if (!snd_hdspm_use_is_exclusive(hdspm)) | ||
2103 | return -EBUSY; | ||
2104 | |||
2105 | channel = ucontrol->id.index - 1; | ||
2106 | |||
2107 | snd_assert(channel >= 0 | ||
2108 | || channel < HDSPM_MAX_CHANNELS, return -EINVAL); | ||
2109 | |||
2110 | if ((mapped_channel = hdspm->channel_map[channel]) < 0) | ||
2111 | return -EINVAL; | ||
2112 | |||
2113 | gain = ucontrol->value.integer.value[0]; | ||
2114 | |||
2115 | spin_lock_irq(&hdspm->lock); | ||
2116 | change = | ||
2117 | gain != hdspm_read_pb_gain(hdspm, mapped_channel, | ||
2118 | mapped_channel); | ||
2119 | if (change) | ||
2120 | hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel, | ||
2121 | gain); | ||
2122 | spin_unlock_irq(&hdspm->lock); | ||
2123 | return change; | ||
2124 | } | ||
2125 | |||
2126 | #define HDSPM_WC_SYNC_CHECK(xname, xindex) \ | ||
2127 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
2128 | .name = xname, \ | ||
2129 | .index = xindex, \ | ||
2130 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2131 | .info = snd_hdspm_info_sync_check, \ | ||
2132 | .get = snd_hdspm_get_wc_sync_check \ | ||
2133 | } | ||
2134 | |||
2135 | static int snd_hdspm_info_sync_check(snd_kcontrol_t * kcontrol, | ||
2136 | snd_ctl_elem_info_t * uinfo) | ||
2137 | { | ||
2138 | static char *texts[] = { "No Lock", "Lock", "Sync" }; | ||
2139 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2140 | uinfo->count = 1; | ||
2141 | uinfo->value.enumerated.items = 3; | ||
2142 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2143 | uinfo->value.enumerated.item = | ||
2144 | uinfo->value.enumerated.items - 1; | ||
2145 | strcpy(uinfo->value.enumerated.name, | ||
2146 | texts[uinfo->value.enumerated.item]); | ||
2147 | return 0; | ||
2148 | } | ||
2149 | |||
2150 | static int hdspm_wc_sync_check(hdspm_t * hdspm) | ||
2151 | { | ||
2152 | int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
2153 | if (status2 & HDSPM_wcLock) { | ||
2154 | if (status2 & HDSPM_wcSync) | ||
2155 | return 2; | ||
2156 | else | ||
2157 | return 1; | ||
2158 | } | ||
2159 | return 0; | ||
2160 | } | ||
2161 | |||
2162 | static int snd_hdspm_get_wc_sync_check(snd_kcontrol_t * kcontrol, | ||
2163 | snd_ctl_elem_value_t * ucontrol) | ||
2164 | { | ||
2165 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
2166 | |||
2167 | ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm); | ||
2168 | return 0; | ||
2169 | } | ||
2170 | |||
2171 | |||
2172 | #define HDSPM_MADI_SYNC_CHECK(xname, xindex) \ | ||
2173 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | ||
2174 | .name = xname, \ | ||
2175 | .index = xindex, \ | ||
2176 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2177 | .info = snd_hdspm_info_sync_check, \ | ||
2178 | .get = snd_hdspm_get_madisync_sync_check \ | ||
2179 | } | ||
2180 | |||
2181 | static int hdspm_madisync_sync_check(hdspm_t * hdspm) | ||
2182 | { | ||
2183 | int status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
2184 | if (status & HDSPM_madiLock) { | ||
2185 | if (status & HDSPM_madiSync) | ||
2186 | return 2; | ||
2187 | else | ||
2188 | return 1; | ||
2189 | } | ||
2190 | return 0; | ||
2191 | } | ||
2192 | |||
2193 | static int snd_hdspm_get_madisync_sync_check(snd_kcontrol_t * kcontrol, | ||
2194 | snd_ctl_elem_value_t * | ||
2195 | ucontrol) | ||
2196 | { | ||
2197 | hdspm_t *hdspm = snd_kcontrol_chip(kcontrol); | ||
2198 | |||
2199 | ucontrol->value.enumerated.item[0] = | ||
2200 | hdspm_madisync_sync_check(hdspm); | ||
2201 | return 0; | ||
2202 | } | ||
2203 | |||
2204 | |||
2205 | |||
2206 | |||
2207 | static snd_kcontrol_new_t snd_hdspm_controls[] = { | ||
2208 | |||
2209 | HDSPM_MIXER("Mixer", 0), | ||
2210 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ | ||
2211 | HDSPM_CLOCK_SOURCE("Sample Clock Source", 0), | ||
2212 | |||
2213 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | ||
2214 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), | ||
2215 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), | ||
2216 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | ||
2217 | /* 'External Rate' complies with the alsa control naming scheme */ | ||
2218 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | ||
2219 | HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0), | ||
2220 | HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0), | ||
2221 | HDSPM_LINE_OUT("Line Out", 0), | ||
2222 | HDSPM_TX_64("TX 64 channels mode", 0), | ||
2223 | HDSPM_C_TMS("Clear Track Marker", 0), | ||
2224 | HDSPM_SAFE_MODE("Safe Mode", 0), | ||
2225 | HDSPM_INPUT_SELECT("Input Select", 0), | ||
2226 | }; | ||
2227 | |||
2228 | static snd_kcontrol_new_t snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER; | ||
2229 | |||
2230 | |||
2231 | static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm) | ||
2232 | { | ||
2233 | int i; | ||
2234 | |||
2235 | for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) { | ||
2236 | if (hdspm->system_sample_rate > 48000) { | ||
2237 | hdspm->playback_mixer_ctls[i]->vd[0].access = | ||
2238 | SNDRV_CTL_ELEM_ACCESS_INACTIVE | | ||
2239 | SNDRV_CTL_ELEM_ACCESS_READ | | ||
2240 | SNDRV_CTL_ELEM_ACCESS_VOLATILE; | ||
2241 | } else { | ||
2242 | hdspm->playback_mixer_ctls[i]->vd[0].access = | ||
2243 | SNDRV_CTL_ELEM_ACCESS_READWRITE | | ||
2244 | SNDRV_CTL_ELEM_ACCESS_VOLATILE; | ||
2245 | } | ||
2246 | snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE | | ||
2247 | SNDRV_CTL_EVENT_MASK_INFO, | ||
2248 | &hdspm->playback_mixer_ctls[i]->id); | ||
2249 | } | ||
2250 | |||
2251 | return 0; | ||
2252 | } | ||
2253 | |||
2254 | |||
2255 | static int snd_hdspm_create_controls(snd_card_t * card, hdspm_t * hdspm) | ||
2256 | { | ||
2257 | unsigned int idx, limit; | ||
2258 | int err; | ||
2259 | snd_kcontrol_t *kctl; | ||
2260 | |||
2261 | /* add control list first */ | ||
2262 | |||
2263 | for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) { | ||
2264 | if ((err = | ||
2265 | snd_ctl_add(card, kctl = | ||
2266 | snd_ctl_new1(&snd_hdspm_controls[idx], | ||
2267 | hdspm))) < 0) { | ||
2268 | return err; | ||
2269 | } | ||
2270 | } | ||
2271 | |||
2272 | /* Channel playback mixer as default control | ||
2273 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer | ||
2274 | they are accesible via special IOCTL on hwdep | ||
2275 | and the mixer 2dimensional mixer control */ | ||
2276 | |||
2277 | snd_hdspm_playback_mixer.name = "Chn"; | ||
2278 | limit = HDSPM_MAX_CHANNELS; | ||
2279 | |||
2280 | /* The index values are one greater than the channel ID so that alsamixer | ||
2281 | will display them correctly. We want to use the index for fast lookup | ||
2282 | of the relevant channel, but if we use it at all, most ALSA software | ||
2283 | does the wrong thing with it ... | ||
2284 | */ | ||
2285 | |||
2286 | for (idx = 0; idx < limit; ++idx) { | ||
2287 | snd_hdspm_playback_mixer.index = idx + 1; | ||
2288 | if ((err = snd_ctl_add(card, | ||
2289 | kctl = | ||
2290 | snd_ctl_new1 | ||
2291 | (&snd_hdspm_playback_mixer, | ||
2292 | hdspm)))) { | ||
2293 | return err; | ||
2294 | } | ||
2295 | hdspm->playback_mixer_ctls[idx] = kctl; | ||
2296 | } | ||
2297 | |||
2298 | return 0; | ||
2299 | } | ||
2300 | |||
2301 | /*------------------------------------------------------------ | ||
2302 | /proc interface | ||
2303 | ------------------------------------------------------------*/ | ||
2304 | |||
2305 | static void | ||
2306 | snd_hdspm_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer) | ||
2307 | { | ||
2308 | hdspm_t *hdspm = (hdspm_t *) entry->private_data; | ||
2309 | unsigned int status; | ||
2310 | unsigned int status2; | ||
2311 | char *pref_sync_ref; | ||
2312 | char *autosync_ref; | ||
2313 | char *system_clock_mode; | ||
2314 | char *clock_source; | ||
2315 | char *insel; | ||
2316 | char *syncref; | ||
2317 | int x, x2; | ||
2318 | |||
2319 | status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
2320 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
2321 | |||
2322 | snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n", | ||
2323 | hdspm->card_name, hdspm->card->number + 1, | ||
2324 | hdspm->firmware_rev, | ||
2325 | (status2 & HDSPM_version0) | | ||
2326 | (status2 & HDSPM_version1) | (status2 & | ||
2327 | HDSPM_version2)); | ||
2328 | |||
2329 | snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", | ||
2330 | hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase); | ||
2331 | |||
2332 | snd_iprintf(buffer, "--- System ---\n"); | ||
2333 | |||
2334 | snd_iprintf(buffer, | ||
2335 | "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n", | ||
2336 | status & HDSPM_audioIRQPending, | ||
2337 | (status & HDSPM_midi0IRQPending) ? 1 : 0, | ||
2338 | (status & HDSPM_midi1IRQPending) ? 1 : 0, | ||
2339 | hdspm->irq_count); | ||
2340 | snd_iprintf(buffer, | ||
2341 | "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n", | ||
2342 | ((status & HDSPM_BufferID) ? 1 : 0), | ||
2343 | (status & HDSPM_BufferPositionMask), | ||
2344 | (status & HDSPM_BufferPositionMask) % (2 * | ||
2345 | (int)hdspm-> | ||
2346 | period_bytes), | ||
2347 | ((status & HDSPM_BufferPositionMask) - | ||
2348 | 64) % (2 * (int)hdspm->period_bytes), | ||
2349 | (long) hdspm_hw_pointer(hdspm) * 4); | ||
2350 | |||
2351 | snd_iprintf(buffer, | ||
2352 | "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n", | ||
2353 | hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF, | ||
2354 | hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF, | ||
2355 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, | ||
2356 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); | ||
2357 | snd_iprintf(buffer, | ||
2358 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n", | ||
2359 | hdspm->control_register, hdspm->control2_register, | ||
2360 | status, status2); | ||
2361 | |||
2362 | snd_iprintf(buffer, "--- Settings ---\n"); | ||
2363 | |||
2364 | x = 1 << (6 + | ||
2365 | hdspm_decode_latency(hdspm-> | ||
2366 | control_register & | ||
2367 | HDSPM_LatencyMask)); | ||
2368 | |||
2369 | snd_iprintf(buffer, | ||
2370 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", | ||
2371 | x, (unsigned long) hdspm->period_bytes); | ||
2372 | |||
2373 | snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", | ||
2374 | (hdspm-> | ||
2375 | control_register & HDSPM_LineOut) ? "on " : "off", | ||
2376 | (hdspm->precise_ptr) ? "on" : "off"); | ||
2377 | |||
2378 | switch (hdspm->control_register & HDSPM_InputMask) { | ||
2379 | case HDSPM_InputOptical: | ||
2380 | insel = "Optical"; | ||
2381 | break; | ||
2382 | case HDSPM_InputCoaxial: | ||
2383 | insel = "Coaxial"; | ||
2384 | break; | ||
2385 | default: | ||
2386 | insel = "Unkown"; | ||
2387 | } | ||
2388 | |||
2389 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | ||
2390 | case HDSPM_SyncRef_Word: | ||
2391 | syncref = "WordClock"; | ||
2392 | break; | ||
2393 | case HDSPM_SyncRef_MADI: | ||
2394 | syncref = "MADI"; | ||
2395 | break; | ||
2396 | default: | ||
2397 | syncref = "Unkown"; | ||
2398 | } | ||
2399 | snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel, | ||
2400 | syncref); | ||
2401 | |||
2402 | snd_iprintf(buffer, | ||
2403 | "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n", | ||
2404 | (hdspm-> | ||
2405 | control_register & HDSPM_clr_tms) ? "on" : "off", | ||
2406 | (hdspm-> | ||
2407 | control_register & HDSPM_TX_64ch) ? "64" : "56", | ||
2408 | (hdspm-> | ||
2409 | control_register & HDSPM_AutoInp) ? "on" : "off"); | ||
2410 | |||
2411 | switch (hdspm_clock_source(hdspm)) { | ||
2412 | case HDSPM_CLOCK_SOURCE_AUTOSYNC: | ||
2413 | clock_source = "AutoSync"; | ||
2414 | break; | ||
2415 | case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: | ||
2416 | clock_source = "Internal 32 kHz"; | ||
2417 | break; | ||
2418 | case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: | ||
2419 | clock_source = "Internal 44.1 kHz"; | ||
2420 | break; | ||
2421 | case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: | ||
2422 | clock_source = "Internal 48 kHz"; | ||
2423 | break; | ||
2424 | case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: | ||
2425 | clock_source = "Internal 64 kHz"; | ||
2426 | break; | ||
2427 | case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: | ||
2428 | clock_source = "Internal 88.2 kHz"; | ||
2429 | break; | ||
2430 | case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: | ||
2431 | clock_source = "Internal 96 kHz"; | ||
2432 | break; | ||
2433 | default: | ||
2434 | clock_source = "Error"; | ||
2435 | } | ||
2436 | snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source); | ||
2437 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { | ||
2438 | system_clock_mode = "Slave"; | ||
2439 | } else { | ||
2440 | system_clock_mode = "Master"; | ||
2441 | } | ||
2442 | snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode); | ||
2443 | |||
2444 | switch (hdspm_pref_sync_ref(hdspm)) { | ||
2445 | case HDSPM_SYNC_FROM_WORD: | ||
2446 | pref_sync_ref = "Word Clock"; | ||
2447 | break; | ||
2448 | case HDSPM_SYNC_FROM_MADI: | ||
2449 | pref_sync_ref = "MADI Sync"; | ||
2450 | break; | ||
2451 | default: | ||
2452 | pref_sync_ref = "XXXX Clock"; | ||
2453 | break; | ||
2454 | } | ||
2455 | snd_iprintf(buffer, "Preferred Sync Reference: %s\n", | ||
2456 | pref_sync_ref); | ||
2457 | |||
2458 | snd_iprintf(buffer, "System Clock Frequency: %d\n", | ||
2459 | hdspm->system_sample_rate); | ||
2460 | |||
2461 | |||
2462 | snd_iprintf(buffer, "--- Status:\n"); | ||
2463 | |||
2464 | x = status & HDSPM_madiSync; | ||
2465 | x2 = status2 & HDSPM_wcSync; | ||
2466 | |||
2467 | snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n", | ||
2468 | (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") : | ||
2469 | "NoLock", | ||
2470 | (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") : | ||
2471 | "NoLock"); | ||
2472 | |||
2473 | switch (hdspm_autosync_ref(hdspm)) { | ||
2474 | case HDSPM_AUTOSYNC_FROM_WORD: | ||
2475 | autosync_ref = "Word Clock"; | ||
2476 | break; | ||
2477 | case HDSPM_AUTOSYNC_FROM_MADI: | ||
2478 | autosync_ref = "MADI Sync"; | ||
2479 | break; | ||
2480 | case HDSPM_AUTOSYNC_FROM_NONE: | ||
2481 | autosync_ref = "Input not valid"; | ||
2482 | break; | ||
2483 | default: | ||
2484 | autosync_ref = "---"; | ||
2485 | break; | ||
2486 | } | ||
2487 | snd_iprintf(buffer, | ||
2488 | "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n", | ||
2489 | autosync_ref, hdspm_external_sample_rate(hdspm), | ||
2490 | (status & HDSPM_madiFreqMask) >> 22, | ||
2491 | (status2 & HDSPM_wcFreqMask) >> 5); | ||
2492 | |||
2493 | snd_iprintf(buffer, "Input: %s, Mode=%s\n", | ||
2494 | (status & HDSPM_AB_int) ? "Coax" : "Optical", | ||
2495 | (status & HDSPM_RX_64ch) ? "64 channels" : | ||
2496 | "56 channels"); | ||
2497 | |||
2498 | snd_iprintf(buffer, "\n"); | ||
2499 | } | ||
2500 | |||
2501 | static void __devinit snd_hdspm_proc_init(hdspm_t * hdspm) | ||
2502 | { | ||
2503 | snd_info_entry_t *entry; | ||
2504 | |||
2505 | if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) | ||
2506 | snd_info_set_text_ops(entry, hdspm, 1024, | ||
2507 | snd_hdspm_proc_read); | ||
2508 | } | ||
2509 | |||
2510 | /*------------------------------------------------------------ | ||
2511 | hdspm intitialize | ||
2512 | ------------------------------------------------------------*/ | ||
2513 | |||
2514 | static int snd_hdspm_set_defaults(hdspm_t * hdspm) | ||
2515 | { | ||
2516 | unsigned int i; | ||
2517 | |||
2518 | /* ASSUMPTION: hdspm->lock is either held, or there is no need to | ||
2519 | hold it (e.g. during module initalization). | ||
2520 | */ | ||
2521 | |||
2522 | /* set defaults: */ | ||
2523 | |||
2524 | hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | ||
2525 | hdspm_encode_latency(7) | /* latency maximum = 8192 samples */ | ||
2526 | HDSPM_InputCoaxial | /* Input Coax not Optical */ | ||
2527 | HDSPM_SyncRef_MADI | /* Madi is syncclock */ | ||
2528 | HDSPM_LineOut | /* Analog output in */ | ||
2529 | HDSPM_TX_64ch | /* transmit in 64ch mode */ | ||
2530 | HDSPM_AutoInp; /* AutoInput chossing (takeover) */ | ||
2531 | |||
2532 | /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */ | ||
2533 | /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */ | ||
2534 | /* ! HDSPM_clr_tms = do not clear bits in track marks */ | ||
2535 | |||
2536 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
2537 | |||
2538 | #ifdef SNDRV_BIG_ENDIAN | ||
2539 | hdspm->control2_register = HDSPM_BIGENDIAN_MODE; | ||
2540 | #else | ||
2541 | hdspm->control2_register = 0; | ||
2542 | #endif | ||
2543 | |||
2544 | hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register); | ||
2545 | hdspm_compute_period_size(hdspm); | ||
2546 | |||
2547 | /* silence everything */ | ||
2548 | |||
2549 | all_in_all_mixer(hdspm, 0 * UNITY_GAIN); | ||
2550 | |||
2551 | if (line_outs_monitor[hdspm->dev]) { | ||
2552 | |||
2553 | snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n"); | ||
2554 | |||
2555 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) { | ||
2556 | if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN)) | ||
2557 | return -EIO; | ||
2558 | } | ||
2559 | } | ||
2560 | |||
2561 | /* set a default rate so that the channel map is set up. */ | ||
2562 | hdspm->channel_map = channel_map_madi_ss; | ||
2563 | hdspm_set_rate(hdspm, 44100, 1); | ||
2564 | |||
2565 | return 0; | ||
2566 | } | ||
2567 | |||
2568 | |||
2569 | /*------------------------------------------------------------ | ||
2570 | interupt | ||
2571 | ------------------------------------------------------------*/ | ||
2572 | |||
2573 | static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id, | ||
2574 | struct pt_regs *regs) | ||
2575 | { | ||
2576 | hdspm_t *hdspm = (hdspm_t *) dev_id; | ||
2577 | unsigned int status; | ||
2578 | int audio; | ||
2579 | int midi0; | ||
2580 | int midi1; | ||
2581 | unsigned int midi0status; | ||
2582 | unsigned int midi1status; | ||
2583 | int schedule = 0; | ||
2584 | |||
2585 | status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
2586 | |||
2587 | audio = status & HDSPM_audioIRQPending; | ||
2588 | midi0 = status & HDSPM_midi0IRQPending; | ||
2589 | midi1 = status & HDSPM_midi1IRQPending; | ||
2590 | |||
2591 | if (!audio && !midi0 && !midi1) | ||
2592 | return IRQ_NONE; | ||
2593 | |||
2594 | hdspm_write(hdspm, HDSPM_interruptConfirmation, 0); | ||
2595 | hdspm->irq_count++; | ||
2596 | |||
2597 | midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff; | ||
2598 | midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff; | ||
2599 | |||
2600 | if (audio) { | ||
2601 | |||
2602 | if (hdspm->capture_substream) | ||
2603 | snd_pcm_period_elapsed(hdspm->pcm-> | ||
2604 | streams | ||
2605 | [SNDRV_PCM_STREAM_CAPTURE]. | ||
2606 | substream); | ||
2607 | |||
2608 | if (hdspm->playback_substream) | ||
2609 | snd_pcm_period_elapsed(hdspm->pcm-> | ||
2610 | streams | ||
2611 | [SNDRV_PCM_STREAM_PLAYBACK]. | ||
2612 | substream); | ||
2613 | } | ||
2614 | |||
2615 | if (midi0 && midi0status) { | ||
2616 | /* we disable interrupts for this input until processing is done */ | ||
2617 | hdspm->control_register &= ~HDSPM_Midi0InterruptEnable; | ||
2618 | hdspm_write(hdspm, HDSPM_controlRegister, | ||
2619 | hdspm->control_register); | ||
2620 | hdspm->midi[0].pending = 1; | ||
2621 | schedule = 1; | ||
2622 | } | ||
2623 | if (midi1 && midi1status) { | ||
2624 | /* we disable interrupts for this input until processing is done */ | ||
2625 | hdspm->control_register &= ~HDSPM_Midi1InterruptEnable; | ||
2626 | hdspm_write(hdspm, HDSPM_controlRegister, | ||
2627 | hdspm->control_register); | ||
2628 | hdspm->midi[1].pending = 1; | ||
2629 | schedule = 1; | ||
2630 | } | ||
2631 | if (schedule) | ||
2632 | tasklet_hi_schedule(&hdspm->midi_tasklet); | ||
2633 | return IRQ_HANDLED; | ||
2634 | } | ||
2635 | |||
2636 | /*------------------------------------------------------------ | ||
2637 | pcm interface | ||
2638 | ------------------------------------------------------------*/ | ||
2639 | |||
2640 | |||
2641 | static snd_pcm_uframes_t snd_hdspm_hw_pointer(snd_pcm_substream_t * | ||
2642 | substream) | ||
2643 | { | ||
2644 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
2645 | return hdspm_hw_pointer(hdspm); | ||
2646 | } | ||
2647 | |||
2648 | static char *hdspm_channel_buffer_location(hdspm_t * hdspm, | ||
2649 | int stream, int channel) | ||
2650 | { | ||
2651 | int mapped_channel; | ||
2652 | |||
2653 | snd_assert(channel >= 0 | ||
2654 | || channel < HDSPM_MAX_CHANNELS, return NULL); | ||
2655 | |||
2656 | if ((mapped_channel = hdspm->channel_map[channel]) < 0) | ||
2657 | return NULL; | ||
2658 | |||
2659 | if (stream == SNDRV_PCM_STREAM_CAPTURE) { | ||
2660 | return hdspm->capture_buffer + | ||
2661 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | ||
2662 | } else { | ||
2663 | return hdspm->playback_buffer + | ||
2664 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | ||
2665 | } | ||
2666 | } | ||
2667 | |||
2668 | |||
2669 | /* dont know why need it ??? */ | ||
2670 | static int snd_hdspm_playback_copy(snd_pcm_substream_t * substream, | ||
2671 | int channel, snd_pcm_uframes_t pos, | ||
2672 | void __user *src, snd_pcm_uframes_t count) | ||
2673 | { | ||
2674 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
2675 | char *channel_buf; | ||
2676 | |||
2677 | snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, | ||
2678 | return -EINVAL); | ||
2679 | |||
2680 | channel_buf = hdspm_channel_buffer_location(hdspm, | ||
2681 | substream->pstr-> | ||
2682 | stream, channel); | ||
2683 | |||
2684 | snd_assert(channel_buf != NULL, return -EIO); | ||
2685 | |||
2686 | return copy_from_user(channel_buf + pos * 4, src, count * 4); | ||
2687 | } | ||
2688 | |||
2689 | static int snd_hdspm_capture_copy(snd_pcm_substream_t * substream, | ||
2690 | int channel, snd_pcm_uframes_t pos, | ||
2691 | void __user *dst, snd_pcm_uframes_t count) | ||
2692 | { | ||
2693 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
2694 | char *channel_buf; | ||
2695 | |||
2696 | snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4, | ||
2697 | return -EINVAL); | ||
2698 | |||
2699 | channel_buf = hdspm_channel_buffer_location(hdspm, | ||
2700 | substream->pstr-> | ||
2701 | stream, channel); | ||
2702 | snd_assert(channel_buf != NULL, return -EIO); | ||
2703 | return copy_to_user(dst, channel_buf + pos * 4, count * 4); | ||
2704 | } | ||
2705 | |||
2706 | static int snd_hdspm_hw_silence(snd_pcm_substream_t * substream, | ||
2707 | int channel, snd_pcm_uframes_t pos, | ||
2708 | snd_pcm_uframes_t count) | ||
2709 | { | ||
2710 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
2711 | char *channel_buf; | ||
2712 | |||
2713 | channel_buf = | ||
2714 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, | ||
2715 | channel); | ||
2716 | snd_assert(channel_buf != NULL, return -EIO); | ||
2717 | memset(channel_buf + pos * 4, 0, count * 4); | ||
2718 | return 0; | ||
2719 | } | ||
2720 | |||
2721 | static int snd_hdspm_reset(snd_pcm_substream_t * substream) | ||
2722 | { | ||
2723 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
2724 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
2725 | snd_pcm_substream_t *other; | ||
2726 | |||
2727 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
2728 | other = hdspm->capture_substream; | ||
2729 | else | ||
2730 | other = hdspm->playback_substream; | ||
2731 | |||
2732 | if (hdspm->running) | ||
2733 | runtime->status->hw_ptr = hdspm_hw_pointer(hdspm); | ||
2734 | else | ||
2735 | runtime->status->hw_ptr = 0; | ||
2736 | if (other) { | ||
2737 | struct list_head *pos; | ||
2738 | snd_pcm_substream_t *s; | ||
2739 | snd_pcm_runtime_t *oruntime = other->runtime; | ||
2740 | snd_pcm_group_for_each(pos, substream) { | ||
2741 | s = snd_pcm_group_substream_entry(pos); | ||
2742 | if (s == other) { | ||
2743 | oruntime->status->hw_ptr = | ||
2744 | runtime->status->hw_ptr; | ||
2745 | break; | ||
2746 | } | ||
2747 | } | ||
2748 | } | ||
2749 | return 0; | ||
2750 | } | ||
2751 | |||
2752 | static int snd_hdspm_hw_params(snd_pcm_substream_t * substream, | ||
2753 | snd_pcm_hw_params_t * params) | ||
2754 | { | ||
2755 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
2756 | int err; | ||
2757 | int i; | ||
2758 | pid_t this_pid; | ||
2759 | pid_t other_pid; | ||
2760 | struct snd_sg_buf *sgbuf; | ||
2761 | |||
2762 | |||
2763 | spin_lock_irq(&hdspm->lock); | ||
2764 | |||
2765 | if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
2766 | this_pid = hdspm->playback_pid; | ||
2767 | other_pid = hdspm->capture_pid; | ||
2768 | } else { | ||
2769 | this_pid = hdspm->capture_pid; | ||
2770 | other_pid = hdspm->playback_pid; | ||
2771 | } | ||
2772 | |||
2773 | if ((other_pid > 0) && (this_pid != other_pid)) { | ||
2774 | |||
2775 | /* The other stream is open, and not by the same | ||
2776 | task as this one. Make sure that the parameters | ||
2777 | that matter are the same. | ||
2778 | */ | ||
2779 | |||
2780 | if (params_rate(params) != hdspm->system_sample_rate) { | ||
2781 | spin_unlock_irq(&hdspm->lock); | ||
2782 | _snd_pcm_hw_param_setempty(params, | ||
2783 | SNDRV_PCM_HW_PARAM_RATE); | ||
2784 | return -EBUSY; | ||
2785 | } | ||
2786 | |||
2787 | if (params_period_size(params) != hdspm->period_bytes / 4) { | ||
2788 | spin_unlock_irq(&hdspm->lock); | ||
2789 | _snd_pcm_hw_param_setempty(params, | ||
2790 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | ||
2791 | return -EBUSY; | ||
2792 | } | ||
2793 | |||
2794 | } | ||
2795 | /* We're fine. */ | ||
2796 | spin_unlock_irq(&hdspm->lock); | ||
2797 | |||
2798 | /* how to make sure that the rate matches an externally-set one ? */ | ||
2799 | |||
2800 | spin_lock_irq(&hdspm->lock); | ||
2801 | if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) { | ||
2802 | spin_unlock_irq(&hdspm->lock); | ||
2803 | _snd_pcm_hw_param_setempty(params, | ||
2804 | SNDRV_PCM_HW_PARAM_RATE); | ||
2805 | return err; | ||
2806 | } | ||
2807 | spin_unlock_irq(&hdspm->lock); | ||
2808 | |||
2809 | if ((err = | ||
2810 | hdspm_set_interrupt_interval(hdspm, | ||
2811 | params_period_size(params))) < | ||
2812 | 0) { | ||
2813 | _snd_pcm_hw_param_setempty(params, | ||
2814 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | ||
2815 | return err; | ||
2816 | } | ||
2817 | |||
2818 | /* Memory allocation, takashi's method, dont know if we should spinlock */ | ||
2819 | /* malloc all buffer even if not enabled to get sure */ | ||
2820 | /* malloc only needed bytes */ | ||
2821 | err = | ||
2822 | snd_pcm_lib_malloc_pages(substream, | ||
2823 | HDSPM_CHANNEL_BUFFER_BYTES * | ||
2824 | params_channels(params)); | ||
2825 | if (err < 0) | ||
2826 | return err; | ||
2827 | |||
2828 | sgbuf = snd_pcm_substream_sgbuf(substream); | ||
2829 | |||
2830 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
2831 | |||
2832 | hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut, | ||
2833 | params_channels(params)); | ||
2834 | |||
2835 | for (i = 0; i < params_channels(params); ++i) | ||
2836 | snd_hdspm_enable_out(hdspm, i, 1); | ||
2837 | |||
2838 | hdspm->playback_buffer = | ||
2839 | (unsigned char *) substream->runtime->dma_area; | ||
2840 | } else { | ||
2841 | hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn, | ||
2842 | params_channels(params)); | ||
2843 | |||
2844 | for (i = 0; i < params_channels(params); ++i) | ||
2845 | snd_hdspm_enable_in(hdspm, i, 1); | ||
2846 | |||
2847 | hdspm->capture_buffer = | ||
2848 | (unsigned char *) substream->runtime->dma_area; | ||
2849 | } | ||
2850 | return 0; | ||
2851 | } | ||
2852 | |||
2853 | static int snd_hdspm_hw_free(snd_pcm_substream_t * substream) | ||
2854 | { | ||
2855 | int i; | ||
2856 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
2857 | |||
2858 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
2859 | |||
2860 | /* params_channels(params) should be enough, | ||
2861 | but to get sure in case of error */ | ||
2862 | for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) | ||
2863 | snd_hdspm_enable_out(hdspm, i, 0); | ||
2864 | |||
2865 | hdspm->playback_buffer = NULL; | ||
2866 | } else { | ||
2867 | for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) | ||
2868 | snd_hdspm_enable_in(hdspm, i, 0); | ||
2869 | |||
2870 | hdspm->capture_buffer = NULL; | ||
2871 | |||
2872 | } | ||
2873 | |||
2874 | snd_pcm_lib_free_pages(substream); | ||
2875 | |||
2876 | return 0; | ||
2877 | } | ||
2878 | |||
2879 | static int snd_hdspm_channel_info(snd_pcm_substream_t * substream, | ||
2880 | snd_pcm_channel_info_t * info) | ||
2881 | { | ||
2882 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
2883 | int mapped_channel; | ||
2884 | |||
2885 | snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL); | ||
2886 | |||
2887 | if ((mapped_channel = hdspm->channel_map[info->channel]) < 0) | ||
2888 | return -EINVAL; | ||
2889 | |||
2890 | info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | ||
2891 | info->first = 0; | ||
2892 | info->step = 32; | ||
2893 | return 0; | ||
2894 | } | ||
2895 | |||
2896 | static int snd_hdspm_ioctl(snd_pcm_substream_t * substream, | ||
2897 | unsigned int cmd, void *arg) | ||
2898 | { | ||
2899 | switch (cmd) { | ||
2900 | case SNDRV_PCM_IOCTL1_RESET: | ||
2901 | { | ||
2902 | return snd_hdspm_reset(substream); | ||
2903 | } | ||
2904 | |||
2905 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: | ||
2906 | { | ||
2907 | snd_pcm_channel_info_t *info = arg; | ||
2908 | return snd_hdspm_channel_info(substream, info); | ||
2909 | } | ||
2910 | default: | ||
2911 | break; | ||
2912 | } | ||
2913 | |||
2914 | return snd_pcm_lib_ioctl(substream, cmd, arg); | ||
2915 | } | ||
2916 | |||
2917 | static int snd_hdspm_trigger(snd_pcm_substream_t * substream, int cmd) | ||
2918 | { | ||
2919 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
2920 | snd_pcm_substream_t *other; | ||
2921 | int running; | ||
2922 | |||
2923 | spin_lock(&hdspm->lock); | ||
2924 | running = hdspm->running; | ||
2925 | switch (cmd) { | ||
2926 | case SNDRV_PCM_TRIGGER_START: | ||
2927 | running |= 1 << substream->stream; | ||
2928 | break; | ||
2929 | case SNDRV_PCM_TRIGGER_STOP: | ||
2930 | running &= ~(1 << substream->stream); | ||
2931 | break; | ||
2932 | default: | ||
2933 | snd_BUG(); | ||
2934 | spin_unlock(&hdspm->lock); | ||
2935 | return -EINVAL; | ||
2936 | } | ||
2937 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
2938 | other = hdspm->capture_substream; | ||
2939 | else | ||
2940 | other = hdspm->playback_substream; | ||
2941 | |||
2942 | if (other) { | ||
2943 | struct list_head *pos; | ||
2944 | snd_pcm_substream_t *s; | ||
2945 | snd_pcm_group_for_each(pos, substream) { | ||
2946 | s = snd_pcm_group_substream_entry(pos); | ||
2947 | if (s == other) { | ||
2948 | snd_pcm_trigger_done(s, substream); | ||
2949 | if (cmd == SNDRV_PCM_TRIGGER_START) | ||
2950 | running |= 1 << s->stream; | ||
2951 | else | ||
2952 | running &= ~(1 << s->stream); | ||
2953 | goto _ok; | ||
2954 | } | ||
2955 | } | ||
2956 | if (cmd == SNDRV_PCM_TRIGGER_START) { | ||
2957 | if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) | ||
2958 | && substream->stream == | ||
2959 | SNDRV_PCM_STREAM_CAPTURE) | ||
2960 | hdspm_silence_playback(hdspm); | ||
2961 | } else { | ||
2962 | if (running && | ||
2963 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
2964 | hdspm_silence_playback(hdspm); | ||
2965 | } | ||
2966 | } else { | ||
2967 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
2968 | hdspm_silence_playback(hdspm); | ||
2969 | } | ||
2970 | _ok: | ||
2971 | snd_pcm_trigger_done(substream, substream); | ||
2972 | if (!hdspm->running && running) | ||
2973 | hdspm_start_audio(hdspm); | ||
2974 | else if (hdspm->running && !running) | ||
2975 | hdspm_stop_audio(hdspm); | ||
2976 | hdspm->running = running; | ||
2977 | spin_unlock(&hdspm->lock); | ||
2978 | |||
2979 | return 0; | ||
2980 | } | ||
2981 | |||
2982 | static int snd_hdspm_prepare(snd_pcm_substream_t * substream) | ||
2983 | { | ||
2984 | return 0; | ||
2985 | } | ||
2986 | |||
2987 | static unsigned int period_sizes[] = | ||
2988 | { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; | ||
2989 | |||
2990 | static snd_pcm_hardware_t snd_hdspm_playback_subinfo = { | ||
2991 | .info = (SNDRV_PCM_INFO_MMAP | | ||
2992 | SNDRV_PCM_INFO_MMAP_VALID | | ||
2993 | SNDRV_PCM_INFO_NONINTERLEAVED | | ||
2994 | SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE), | ||
2995 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
2996 | .rates = (SNDRV_PCM_RATE_32000 | | ||
2997 | SNDRV_PCM_RATE_44100 | | ||
2998 | SNDRV_PCM_RATE_48000 | | ||
2999 | SNDRV_PCM_RATE_64000 | | ||
3000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), | ||
3001 | .rate_min = 32000, | ||
3002 | .rate_max = 96000, | ||
3003 | .channels_min = 1, | ||
3004 | .channels_max = HDSPM_MAX_CHANNELS, | ||
3005 | .buffer_bytes_max = | ||
3006 | HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, | ||
3007 | .period_bytes_min = (64 * 4), | ||
3008 | .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, | ||
3009 | .periods_min = 2, | ||
3010 | .periods_max = 2, | ||
3011 | .fifo_size = 0 | ||
3012 | }; | ||
3013 | |||
3014 | static snd_pcm_hardware_t snd_hdspm_capture_subinfo = { | ||
3015 | .info = (SNDRV_PCM_INFO_MMAP | | ||
3016 | SNDRV_PCM_INFO_MMAP_VALID | | ||
3017 | SNDRV_PCM_INFO_NONINTERLEAVED | | ||
3018 | SNDRV_PCM_INFO_SYNC_START), | ||
3019 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
3020 | .rates = (SNDRV_PCM_RATE_32000 | | ||
3021 | SNDRV_PCM_RATE_44100 | | ||
3022 | SNDRV_PCM_RATE_48000 | | ||
3023 | SNDRV_PCM_RATE_64000 | | ||
3024 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), | ||
3025 | .rate_min = 32000, | ||
3026 | .rate_max = 96000, | ||
3027 | .channels_min = 1, | ||
3028 | .channels_max = HDSPM_MAX_CHANNELS, | ||
3029 | .buffer_bytes_max = | ||
3030 | HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, | ||
3031 | .period_bytes_min = (64 * 4), | ||
3032 | .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, | ||
3033 | .periods_min = 2, | ||
3034 | .periods_max = 2, | ||
3035 | .fifo_size = 0 | ||
3036 | }; | ||
3037 | |||
3038 | static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = { | ||
3039 | .count = ARRAY_SIZE(period_sizes), | ||
3040 | .list = period_sizes, | ||
3041 | .mask = 0 | ||
3042 | }; | ||
3043 | |||
3044 | |||
3045 | static int snd_hdspm_hw_rule_channels_rate(snd_pcm_hw_params_t * params, | ||
3046 | snd_pcm_hw_rule_t * rule) | ||
3047 | { | ||
3048 | hdspm_t *hdspm = rule->private; | ||
3049 | snd_interval_t *c = | ||
3050 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
3051 | snd_interval_t *r = | ||
3052 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
3053 | |||
3054 | if (r->min > 48000) { | ||
3055 | snd_interval_t t = { | ||
3056 | .min = 1, | ||
3057 | .max = hdspm->ds_channels, | ||
3058 | .integer = 1, | ||
3059 | }; | ||
3060 | return snd_interval_refine(c, &t); | ||
3061 | } else if (r->max < 64000) { | ||
3062 | snd_interval_t t = { | ||
3063 | .min = 1, | ||
3064 | .max = hdspm->ss_channels, | ||
3065 | .integer = 1, | ||
3066 | }; | ||
3067 | return snd_interval_refine(c, &t); | ||
3068 | } | ||
3069 | return 0; | ||
3070 | } | ||
3071 | |||
3072 | static int snd_hdspm_hw_rule_rate_channels(snd_pcm_hw_params_t * params, | ||
3073 | snd_pcm_hw_rule_t * rule) | ||
3074 | { | ||
3075 | hdspm_t *hdspm = rule->private; | ||
3076 | snd_interval_t *c = | ||
3077 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
3078 | snd_interval_t *r = | ||
3079 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
3080 | |||
3081 | if (c->min <= hdspm->ss_channels) { | ||
3082 | snd_interval_t t = { | ||
3083 | .min = 32000, | ||
3084 | .max = 48000, | ||
3085 | .integer = 1, | ||
3086 | }; | ||
3087 | return snd_interval_refine(r, &t); | ||
3088 | } else if (c->max > hdspm->ss_channels) { | ||
3089 | snd_interval_t t = { | ||
3090 | .min = 64000, | ||
3091 | .max = 96000, | ||
3092 | .integer = 1, | ||
3093 | }; | ||
3094 | |||
3095 | return snd_interval_refine(r, &t); | ||
3096 | } | ||
3097 | return 0; | ||
3098 | } | ||
3099 | |||
3100 | static int snd_hdspm_playback_open(snd_pcm_substream_t * substream) | ||
3101 | { | ||
3102 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
3103 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
3104 | |||
3105 | snd_printdd("Open device substream %d\n", substream->stream); | ||
3106 | |||
3107 | spin_lock_irq(&hdspm->lock); | ||
3108 | |||
3109 | snd_pcm_set_sync(substream); | ||
3110 | |||
3111 | runtime->hw = snd_hdspm_playback_subinfo; | ||
3112 | |||
3113 | if (hdspm->capture_substream == NULL) | ||
3114 | hdspm_stop_audio(hdspm); | ||
3115 | |||
3116 | hdspm->playback_pid = current->pid; | ||
3117 | hdspm->playback_substream = substream; | ||
3118 | |||
3119 | spin_unlock_irq(&hdspm->lock); | ||
3120 | |||
3121 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | ||
3122 | |||
3123 | snd_pcm_hw_constraint_list(runtime, 0, | ||
3124 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
3125 | &hw_constraints_period_sizes); | ||
3126 | |||
3127 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
3128 | snd_hdspm_hw_rule_channels_rate, hdspm, | ||
3129 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
3130 | |||
3131 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
3132 | snd_hdspm_hw_rule_rate_channels, hdspm, | ||
3133 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
3134 | |||
3135 | return 0; | ||
3136 | } | ||
3137 | |||
3138 | static int snd_hdspm_playback_release(snd_pcm_substream_t * substream) | ||
3139 | { | ||
3140 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
3141 | |||
3142 | spin_lock_irq(&hdspm->lock); | ||
3143 | |||
3144 | hdspm->playback_pid = -1; | ||
3145 | hdspm->playback_substream = NULL; | ||
3146 | |||
3147 | spin_unlock_irq(&hdspm->lock); | ||
3148 | |||
3149 | return 0; | ||
3150 | } | ||
3151 | |||
3152 | |||
3153 | static int snd_hdspm_capture_open(snd_pcm_substream_t * substream) | ||
3154 | { | ||
3155 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
3156 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
3157 | |||
3158 | spin_lock_irq(&hdspm->lock); | ||
3159 | snd_pcm_set_sync(substream); | ||
3160 | runtime->hw = snd_hdspm_capture_subinfo; | ||
3161 | |||
3162 | if (hdspm->playback_substream == NULL) | ||
3163 | hdspm_stop_audio(hdspm); | ||
3164 | |||
3165 | hdspm->capture_pid = current->pid; | ||
3166 | hdspm->capture_substream = substream; | ||
3167 | |||
3168 | spin_unlock_irq(&hdspm->lock); | ||
3169 | |||
3170 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | ||
3171 | snd_pcm_hw_constraint_list(runtime, 0, | ||
3172 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
3173 | &hw_constraints_period_sizes); | ||
3174 | |||
3175 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
3176 | snd_hdspm_hw_rule_channels_rate, hdspm, | ||
3177 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
3178 | |||
3179 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
3180 | snd_hdspm_hw_rule_rate_channels, hdspm, | ||
3181 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
3182 | return 0; | ||
3183 | } | ||
3184 | |||
3185 | static int snd_hdspm_capture_release(snd_pcm_substream_t * substream) | ||
3186 | { | ||
3187 | hdspm_t *hdspm = snd_pcm_substream_chip(substream); | ||
3188 | |||
3189 | spin_lock_irq(&hdspm->lock); | ||
3190 | |||
3191 | hdspm->capture_pid = -1; | ||
3192 | hdspm->capture_substream = NULL; | ||
3193 | |||
3194 | spin_unlock_irq(&hdspm->lock); | ||
3195 | return 0; | ||
3196 | } | ||
3197 | |||
3198 | static int snd_hdspm_hwdep_dummy_op(snd_hwdep_t * hw, struct file *file) | ||
3199 | { | ||
3200 | /* we have nothing to initialize but the call is required */ | ||
3201 | return 0; | ||
3202 | } | ||
3203 | |||
3204 | |||
3205 | static int snd_hdspm_hwdep_ioctl(snd_hwdep_t * hw, struct file *file, | ||
3206 | unsigned int cmd, unsigned long arg) | ||
3207 | { | ||
3208 | hdspm_t *hdspm = (hdspm_t *) hw->private_data; | ||
3209 | struct sndrv_hdspm_mixer_ioctl mixer; | ||
3210 | hdspm_config_info_t info; | ||
3211 | hdspm_version_t hdspm_version; | ||
3212 | struct sndrv_hdspm_peak_rms_ioctl rms; | ||
3213 | |||
3214 | switch (cmd) { | ||
3215 | |||
3216 | |||
3217 | case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: | ||
3218 | if (copy_from_user(&rms, (void __user *)arg, sizeof(rms))) | ||
3219 | return -EFAULT; | ||
3220 | /* maybe there is a chance to memorymap in future so dont touch just copy */ | ||
3221 | if(copy_to_user_fromio((void __user *)rms.peak, | ||
3222 | hdspm->iobase+HDSPM_MADI_peakrmsbase, | ||
3223 | sizeof(hdspm_peak_rms_t)) != 0 ) | ||
3224 | return -EFAULT; | ||
3225 | |||
3226 | break; | ||
3227 | |||
3228 | |||
3229 | case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO: | ||
3230 | |||
3231 | spin_lock_irq(&hdspm->lock); | ||
3232 | info.pref_sync_ref = | ||
3233 | (unsigned char) hdspm_pref_sync_ref(hdspm); | ||
3234 | info.wordclock_sync_check = | ||
3235 | (unsigned char) hdspm_wc_sync_check(hdspm); | ||
3236 | |||
3237 | info.system_sample_rate = hdspm->system_sample_rate; | ||
3238 | info.autosync_sample_rate = | ||
3239 | hdspm_external_sample_rate(hdspm); | ||
3240 | info.system_clock_mode = | ||
3241 | (unsigned char) hdspm_system_clock_mode(hdspm); | ||
3242 | info.clock_source = | ||
3243 | (unsigned char) hdspm_clock_source(hdspm); | ||
3244 | info.autosync_ref = | ||
3245 | (unsigned char) hdspm_autosync_ref(hdspm); | ||
3246 | info.line_out = (unsigned char) hdspm_line_out(hdspm); | ||
3247 | info.passthru = 0; | ||
3248 | spin_unlock_irq(&hdspm->lock); | ||
3249 | if (copy_to_user((void __user *) arg, &info, sizeof(info))) | ||
3250 | return -EFAULT; | ||
3251 | break; | ||
3252 | |||
3253 | case SNDRV_HDSPM_IOCTL_GET_VERSION: | ||
3254 | hdspm_version.firmware_rev = hdspm->firmware_rev; | ||
3255 | if (copy_to_user((void __user *) arg, &hdspm_version, | ||
3256 | sizeof(hdspm_version))) | ||
3257 | return -EFAULT; | ||
3258 | break; | ||
3259 | |||
3260 | case SNDRV_HDSPM_IOCTL_GET_MIXER: | ||
3261 | if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer))) | ||
3262 | return -EFAULT; | ||
3263 | if (copy_to_user | ||
3264 | ((void __user *)mixer.mixer, hdspm->mixer, sizeof(hdspm_mixer_t))) | ||
3265 | return -EFAULT; | ||
3266 | break; | ||
3267 | |||
3268 | default: | ||
3269 | return -EINVAL; | ||
3270 | } | ||
3271 | return 0; | ||
3272 | } | ||
3273 | |||
3274 | static snd_pcm_ops_t snd_hdspm_playback_ops = { | ||
3275 | .open = snd_hdspm_playback_open, | ||
3276 | .close = snd_hdspm_playback_release, | ||
3277 | .ioctl = snd_hdspm_ioctl, | ||
3278 | .hw_params = snd_hdspm_hw_params, | ||
3279 | .hw_free = snd_hdspm_hw_free, | ||
3280 | .prepare = snd_hdspm_prepare, | ||
3281 | .trigger = snd_hdspm_trigger, | ||
3282 | .pointer = snd_hdspm_hw_pointer, | ||
3283 | .copy = snd_hdspm_playback_copy, | ||
3284 | .silence = snd_hdspm_hw_silence, | ||
3285 | .page = snd_pcm_sgbuf_ops_page, | ||
3286 | }; | ||
3287 | |||
3288 | static snd_pcm_ops_t snd_hdspm_capture_ops = { | ||
3289 | .open = snd_hdspm_capture_open, | ||
3290 | .close = snd_hdspm_capture_release, | ||
3291 | .ioctl = snd_hdspm_ioctl, | ||
3292 | .hw_params = snd_hdspm_hw_params, | ||
3293 | .hw_free = snd_hdspm_hw_free, | ||
3294 | .prepare = snd_hdspm_prepare, | ||
3295 | .trigger = snd_hdspm_trigger, | ||
3296 | .pointer = snd_hdspm_hw_pointer, | ||
3297 | .copy = snd_hdspm_capture_copy, | ||
3298 | .page = snd_pcm_sgbuf_ops_page, | ||
3299 | }; | ||
3300 | |||
3301 | static int __devinit snd_hdspm_create_hwdep(snd_card_t * card, | ||
3302 | hdspm_t * hdspm) | ||
3303 | { | ||
3304 | snd_hwdep_t *hw; | ||
3305 | int err; | ||
3306 | |||
3307 | if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0) | ||
3308 | return err; | ||
3309 | |||
3310 | hdspm->hwdep = hw; | ||
3311 | hw->private_data = hdspm; | ||
3312 | strcpy(hw->name, "HDSPM hwdep interface"); | ||
3313 | |||
3314 | hw->ops.open = snd_hdspm_hwdep_dummy_op; | ||
3315 | hw->ops.ioctl = snd_hdspm_hwdep_ioctl; | ||
3316 | hw->ops.release = snd_hdspm_hwdep_dummy_op; | ||
3317 | |||
3318 | return 0; | ||
3319 | } | ||
3320 | |||
3321 | |||
3322 | /*------------------------------------------------------------ | ||
3323 | memory interface | ||
3324 | ------------------------------------------------------------*/ | ||
3325 | static int __devinit snd_hdspm_preallocate_memory(hdspm_t * hdspm) | ||
3326 | { | ||
3327 | int err; | ||
3328 | snd_pcm_t *pcm; | ||
3329 | size_t wanted; | ||
3330 | |||
3331 | pcm = hdspm->pcm; | ||
3332 | |||
3333 | wanted = HDSPM_DMA_AREA_BYTES + 4096; /* dont know why, but it works */ | ||
3334 | |||
3335 | if ((err = | ||
3336 | snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
3337 | SNDRV_DMA_TYPE_DEV_SG, | ||
3338 | snd_dma_pci_data(hdspm->pci), | ||
3339 | wanted, | ||
3340 | wanted)) < 0) { | ||
3341 | snd_printdd("Could not preallocate %d Bytes\n", wanted); | ||
3342 | |||
3343 | return err; | ||
3344 | } else | ||
3345 | snd_printdd(" Preallocated %d Bytes\n", wanted); | ||
3346 | |||
3347 | return 0; | ||
3348 | } | ||
3349 | |||
3350 | static int snd_hdspm_memory_free(hdspm_t * hdspm) | ||
3351 | { | ||
3352 | snd_printdd("memory_free_for_all %p\n", hdspm->pcm); | ||
3353 | |||
3354 | snd_pcm_lib_preallocate_free_for_all(hdspm->pcm); | ||
3355 | return 0; | ||
3356 | } | ||
3357 | |||
3358 | |||
3359 | static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf, | ||
3360 | unsigned int reg, int channels) | ||
3361 | { | ||
3362 | int i; | ||
3363 | for (i = 0; i < (channels * 16); i++) | ||
3364 | hdspm_write(hdspm, reg + 4 * i, | ||
3365 | snd_pcm_sgbuf_get_addr(sgbuf, | ||
3366 | (size_t) 4096 * i)); | ||
3367 | } | ||
3368 | |||
3369 | /* ------------- ALSA Devices ---------------------------- */ | ||
3370 | static int __devinit snd_hdspm_create_pcm(snd_card_t * card, | ||
3371 | hdspm_t * hdspm) | ||
3372 | { | ||
3373 | snd_pcm_t *pcm; | ||
3374 | int err; | ||
3375 | |||
3376 | if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0) | ||
3377 | return err; | ||
3378 | |||
3379 | hdspm->pcm = pcm; | ||
3380 | pcm->private_data = hdspm; | ||
3381 | strcpy(pcm->name, hdspm->card_name); | ||
3382 | |||
3383 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
3384 | &snd_hdspm_playback_ops); | ||
3385 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
3386 | &snd_hdspm_capture_ops); | ||
3387 | |||
3388 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; | ||
3389 | |||
3390 | if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0) | ||
3391 | return err; | ||
3392 | |||
3393 | return 0; | ||
3394 | } | ||
3395 | |||
3396 | static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm) | ||
3397 | { | ||
3398 | snd_hdspm_flush_midi_input(hdspm, 0); | ||
3399 | snd_hdspm_flush_midi_input(hdspm, 1); | ||
3400 | } | ||
3401 | |||
3402 | static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card, | ||
3403 | hdspm_t * hdspm) | ||
3404 | { | ||
3405 | int err; | ||
3406 | |||
3407 | snd_printdd("Create card...\n"); | ||
3408 | if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0) | ||
3409 | return err; | ||
3410 | |||
3411 | if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0) | ||
3412 | return err; | ||
3413 | |||
3414 | if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0) | ||
3415 | return err; | ||
3416 | |||
3417 | if ((err = snd_hdspm_create_controls(card, hdspm)) < 0) | ||
3418 | return err; | ||
3419 | |||
3420 | if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0) | ||
3421 | return err; | ||
3422 | |||
3423 | snd_printdd("proc init...\n"); | ||
3424 | snd_hdspm_proc_init(hdspm); | ||
3425 | |||
3426 | hdspm->system_sample_rate = -1; | ||
3427 | hdspm->last_external_sample_rate = -1; | ||
3428 | hdspm->last_internal_sample_rate = -1; | ||
3429 | hdspm->playback_pid = -1; | ||
3430 | hdspm->capture_pid = -1; | ||
3431 | hdspm->capture_substream = NULL; | ||
3432 | hdspm->playback_substream = NULL; | ||
3433 | |||
3434 | snd_printdd("Set defaults...\n"); | ||
3435 | if ((err = snd_hdspm_set_defaults(hdspm)) < 0) | ||
3436 | return err; | ||
3437 | |||
3438 | snd_printdd("Update mixer controls...\n"); | ||
3439 | hdspm_update_simple_mixer_controls(hdspm); | ||
3440 | |||
3441 | snd_printdd("Initializeing complete ???\n"); | ||
3442 | |||
3443 | if ((err = snd_card_register(card)) < 0) { | ||
3444 | snd_printk(KERN_ERR "HDSPM: error registering card\n"); | ||
3445 | return err; | ||
3446 | } | ||
3447 | |||
3448 | snd_printdd("... yes now\n"); | ||
3449 | |||
3450 | return 0; | ||
3451 | } | ||
3452 | |||
3453 | static int __devinit snd_hdspm_create(snd_card_t * card, hdspm_t * hdspm, | ||
3454 | int precise_ptr, int enable_monitor) | ||
3455 | { | ||
3456 | struct pci_dev *pci = hdspm->pci; | ||
3457 | int err; | ||
3458 | int i; | ||
3459 | |||
3460 | unsigned long io_extent; | ||
3461 | |||
3462 | hdspm->irq = -1; | ||
3463 | hdspm->irq_count = 0; | ||
3464 | |||
3465 | hdspm->midi[0].rmidi = NULL; | ||
3466 | hdspm->midi[1].rmidi = NULL; | ||
3467 | hdspm->midi[0].input = NULL; | ||
3468 | hdspm->midi[1].input = NULL; | ||
3469 | hdspm->midi[0].output = NULL; | ||
3470 | hdspm->midi[1].output = NULL; | ||
3471 | spin_lock_init(&hdspm->midi[0].lock); | ||
3472 | spin_lock_init(&hdspm->midi[1].lock); | ||
3473 | hdspm->iobase = NULL; | ||
3474 | hdspm->control_register = 0; | ||
3475 | hdspm->control2_register = 0; | ||
3476 | |||
3477 | hdspm->playback_buffer = NULL; | ||
3478 | hdspm->capture_buffer = NULL; | ||
3479 | |||
3480 | for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) | ||
3481 | hdspm->playback_mixer_ctls[i] = NULL; | ||
3482 | hdspm->mixer = NULL; | ||
3483 | |||
3484 | hdspm->card = card; | ||
3485 | |||
3486 | spin_lock_init(&hdspm->lock); | ||
3487 | |||
3488 | tasklet_init(&hdspm->midi_tasklet, | ||
3489 | hdspm_midi_tasklet, (unsigned long) hdspm); | ||
3490 | |||
3491 | pci_read_config_word(hdspm->pci, | ||
3492 | PCI_CLASS_REVISION, &hdspm->firmware_rev); | ||
3493 | |||
3494 | strcpy(card->driver, "HDSPM"); | ||
3495 | strcpy(card->mixername, "Xilinx FPGA"); | ||
3496 | hdspm->card_name = "RME HDSPM MADI"; | ||
3497 | |||
3498 | if ((err = pci_enable_device(pci)) < 0) | ||
3499 | return err; | ||
3500 | |||
3501 | pci_set_master(hdspm->pci); | ||
3502 | |||
3503 | if ((err = pci_request_regions(pci, "hdspm")) < 0) | ||
3504 | return err; | ||
3505 | |||
3506 | hdspm->port = pci_resource_start(pci, 0); | ||
3507 | io_extent = pci_resource_len(pci, 0); | ||
3508 | |||
3509 | snd_printdd("grabbed memory region 0x%lx-0x%lx\n", | ||
3510 | hdspm->port, hdspm->port + io_extent - 1); | ||
3511 | |||
3512 | |||
3513 | if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) { | ||
3514 | snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n", | ||
3515 | hdspm->port, hdspm->port + io_extent - 1); | ||
3516 | return -EBUSY; | ||
3517 | } | ||
3518 | snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n", | ||
3519 | (unsigned long)hdspm->iobase, hdspm->port, | ||
3520 | hdspm->port + io_extent - 1); | ||
3521 | |||
3522 | if (request_irq(pci->irq, snd_hdspm_interrupt, | ||
3523 | SA_INTERRUPT | SA_SHIRQ, "hdspm", | ||
3524 | (void *) hdspm)) { | ||
3525 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); | ||
3526 | return -EBUSY; | ||
3527 | } | ||
3528 | |||
3529 | snd_printdd("use IRQ %d\n", pci->irq); | ||
3530 | |||
3531 | hdspm->irq = pci->irq; | ||
3532 | hdspm->precise_ptr = precise_ptr; | ||
3533 | |||
3534 | hdspm->monitor_outs = enable_monitor; | ||
3535 | |||
3536 | snd_printdd("kmalloc Mixer memory of %d Bytes\n", | ||
3537 | sizeof(hdspm_mixer_t)); | ||
3538 | if ((hdspm->mixer = | ||
3539 | (hdspm_mixer_t *) kmalloc(sizeof(hdspm_mixer_t), GFP_KERNEL)) | ||
3540 | == NULL) { | ||
3541 | snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n", | ||
3542 | (int)sizeof(hdspm_mixer_t)); | ||
3543 | return err; | ||
3544 | } | ||
3545 | |||
3546 | hdspm->ss_channels = MADI_SS_CHANNELS; | ||
3547 | hdspm->ds_channels = MADI_DS_CHANNELS; | ||
3548 | hdspm->qs_channels = MADI_QS_CHANNELS; | ||
3549 | |||
3550 | snd_printdd("create alsa devices.\n"); | ||
3551 | if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0) | ||
3552 | return err; | ||
3553 | |||
3554 | snd_hdspm_initialize_midi_flush(hdspm); | ||
3555 | |||
3556 | return 0; | ||
3557 | } | ||
3558 | |||
3559 | static int snd_hdspm_free(hdspm_t * hdspm) | ||
3560 | { | ||
3561 | |||
3562 | if (hdspm->port) { | ||
3563 | |||
3564 | /* stop th audio, and cancel all interrupts */ | ||
3565 | hdspm->control_register &= | ||
3566 | ~(HDSPM_Start | HDSPM_AudioInterruptEnable | ||
3567 | | HDSPM_Midi0InterruptEnable | | ||
3568 | HDSPM_Midi1InterruptEnable); | ||
3569 | hdspm_write(hdspm, HDSPM_controlRegister, | ||
3570 | hdspm->control_register); | ||
3571 | } | ||
3572 | |||
3573 | if (hdspm->irq >= 0) | ||
3574 | free_irq(hdspm->irq, (void *) hdspm); | ||
3575 | |||
3576 | |||
3577 | if (hdspm->mixer) | ||
3578 | kfree(hdspm->mixer); | ||
3579 | |||
3580 | if (hdspm->iobase) | ||
3581 | iounmap(hdspm->iobase); | ||
3582 | |||
3583 | snd_hdspm_memory_free(hdspm); | ||
3584 | |||
3585 | if (hdspm->port) | ||
3586 | pci_release_regions(hdspm->pci); | ||
3587 | |||
3588 | pci_disable_device(hdspm->pci); | ||
3589 | return 0; | ||
3590 | } | ||
3591 | |||
3592 | static void snd_hdspm_card_free(snd_card_t * card) | ||
3593 | { | ||
3594 | hdspm_t *hdspm = (hdspm_t *) card->private_data; | ||
3595 | |||
3596 | if (hdspm) | ||
3597 | snd_hdspm_free(hdspm); | ||
3598 | } | ||
3599 | |||
3600 | static int __devinit snd_hdspm_probe(struct pci_dev *pci, | ||
3601 | const struct pci_device_id *pci_id) | ||
3602 | { | ||
3603 | static int dev; | ||
3604 | hdspm_t *hdspm; | ||
3605 | snd_card_t *card; | ||
3606 | int err; | ||
3607 | |||
3608 | if (dev >= SNDRV_CARDS) | ||
3609 | return -ENODEV; | ||
3610 | if (!enable[dev]) { | ||
3611 | dev++; | ||
3612 | return -ENOENT; | ||
3613 | } | ||
3614 | |||
3615 | if (!(card = snd_card_new(index[dev], id[dev], | ||
3616 | THIS_MODULE, sizeof(hdspm_t)))) | ||
3617 | return -ENOMEM; | ||
3618 | |||
3619 | hdspm = (hdspm_t *) card->private_data; | ||
3620 | card->private_free = snd_hdspm_card_free; | ||
3621 | hdspm->dev = dev; | ||
3622 | hdspm->pci = pci; | ||
3623 | |||
3624 | if ((err = | ||
3625 | snd_hdspm_create(card, hdspm, precise_ptr[dev], | ||
3626 | enable_monitor[dev])) < 0) { | ||
3627 | snd_card_free(card); | ||
3628 | return err; | ||
3629 | } | ||
3630 | |||
3631 | strcpy(card->shortname, "HDSPM MADI"); | ||
3632 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name, | ||
3633 | hdspm->port, hdspm->irq); | ||
3634 | |||
3635 | if ((err = snd_card_register(card)) < 0) { | ||
3636 | snd_card_free(card); | ||
3637 | return err; | ||
3638 | } | ||
3639 | |||
3640 | pci_set_drvdata(pci, card); | ||
3641 | |||
3642 | dev++; | ||
3643 | return 0; | ||
3644 | } | ||
3645 | |||
3646 | static void __devexit snd_hdspm_remove(struct pci_dev *pci) | ||
3647 | { | ||
3648 | snd_card_free(pci_get_drvdata(pci)); | ||
3649 | pci_set_drvdata(pci, NULL); | ||
3650 | } | ||
3651 | |||
3652 | static struct pci_driver driver = { | ||
3653 | .name = "RME Hammerfall DSP MADI", | ||
3654 | .id_table = snd_hdspm_ids, | ||
3655 | .probe = snd_hdspm_probe, | ||
3656 | .remove = __devexit_p(snd_hdspm_remove), | ||
3657 | }; | ||
3658 | |||
3659 | |||
3660 | static int __init alsa_card_hdspm_init(void) | ||
3661 | { | ||
3662 | return pci_register_driver(&driver); | ||
3663 | } | ||
3664 | |||
3665 | static void __exit alsa_card_hdspm_exit(void) | ||
3666 | { | ||
3667 | pci_unregister_driver(&driver); | ||
3668 | } | ||
3669 | |||
3670 | module_init(alsa_card_hdspm_init) | ||
3671 | module_exit(alsa_card_hdspm_exit) | ||
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 69cd81eaa111..1bc9d0df8516 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -303,18 +303,22 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer | |||
303 | { | 303 | { |
304 | dmab->dev.type = SNDRV_DMA_TYPE_DEV; | 304 | dmab->dev.type = SNDRV_DMA_TYPE_DEV; |
305 | dmab->dev.dev = snd_dma_pci_data(pci); | 305 | dmab->dev.dev = snd_dma_pci_data(pci); |
306 | if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { | 306 | if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) { |
307 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | 307 | if (dmab->bytes >= size) |
308 | size, dmab) < 0) | 308 | return 0; |
309 | return -ENOMEM; | ||
310 | } | 309 | } |
310 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | ||
311 | size, dmab) < 0) | ||
312 | return -ENOMEM; | ||
311 | return 0; | 313 | return 0; |
312 | } | 314 | } |
313 | 315 | ||
314 | static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) | 316 | static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci) |
315 | { | 317 | { |
316 | if (dmab->area) | 318 | if (dmab->area) { |
319 | dmab->dev.dev = NULL; /* make it anonymous */ | ||
317 | snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci)); | 320 | snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci)); |
321 | } | ||
318 | } | 322 | } |
319 | 323 | ||
320 | 324 | ||
@@ -1466,7 +1470,7 @@ static int snd_rme9652_get_tc_valid(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu | |||
1466 | return 0; | 1470 | return 0; |
1467 | } | 1471 | } |
1468 | 1472 | ||
1469 | #if ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE | 1473 | #ifdef ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE |
1470 | 1474 | ||
1471 | /* FIXME: this routine needs a port to the new control API --jk */ | 1475 | /* FIXME: this routine needs a port to the new control API --jk */ |
1472 | 1476 | ||
@@ -2664,7 +2668,7 @@ static struct pci_driver driver = { | |||
2664 | 2668 | ||
2665 | static int __init alsa_card_hammerfall_init(void) | 2669 | static int __init alsa_card_hammerfall_init(void) |
2666 | { | 2670 | { |
2667 | return pci_module_init(&driver); | 2671 | return pci_register_driver(&driver); |
2668 | } | 2672 | } |
2669 | 2673 | ||
2670 | static void __exit alsa_card_hammerfall_exit(void) | 2674 | static void __exit alsa_card_hammerfall_exit(void) |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index cfd2c5fd6ddf..60ecb2bdb65e 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -1522,7 +1522,7 @@ static struct pci_driver driver = { | |||
1522 | 1522 | ||
1523 | static int __init alsa_card_sonicvibes_init(void) | 1523 | static int __init alsa_card_sonicvibes_init(void) |
1524 | { | 1524 | { |
1525 | return pci_module_init(&driver); | 1525 | return pci_register_driver(&driver); |
1526 | } | 1526 | } |
1527 | 1527 | ||
1528 | static void __exit alsa_card_sonicvibes_exit(void) | 1528 | static void __exit alsa_card_sonicvibes_exit(void) |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index ad58e08d66e2..940d531575c0 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -143,7 +143,8 @@ static int __devinit snd_trident_probe(struct pci_dev *pci, | |||
143 | return err; | 143 | return err; |
144 | } | 144 | } |
145 | } | 145 | } |
146 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, | 146 | if (trident->device != TRIDENT_DEVICE_ID_SI7018 && |
147 | (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, | ||
147 | trident->midi_port, 1, | 148 | trident->midi_port, 1, |
148 | trident->irq, 0, &trident->rmidi)) < 0) { | 149 | trident->irq, 0, &trident->rmidi)) < 0) { |
149 | snd_card_free(card); | 150 | snd_card_free(card); |
@@ -184,7 +185,7 @@ static struct pci_driver driver = { | |||
184 | 185 | ||
185 | static int __init alsa_card_trident_init(void) | 186 | static int __init alsa_card_trident_init(void) |
186 | { | 187 | { |
187 | return pci_module_init(&driver); | 188 | return pci_register_driver(&driver); |
188 | } | 189 | } |
189 | 190 | ||
190 | static void __exit alsa_card_trident_exit(void) | 191 | static void __exit alsa_card_trident_exit(void) |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index ccd5ca2ba16f..29d89bfba0a4 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -472,6 +472,7 @@ void snd_trident_write_voice_regs(trident_t * trident, | |||
472 | break; | 472 | break; |
473 | default: | 473 | default: |
474 | snd_BUG(); | 474 | snd_BUG(); |
475 | return; | ||
475 | } | 476 | } |
476 | 477 | ||
477 | outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); | 478 | outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); |
@@ -3152,8 +3153,7 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode) | |||
3152 | switch (mode) { | 3153 | switch (mode) { |
3153 | case GAMEPORT_MODE_COOKED: | 3154 | case GAMEPORT_MODE_COOKED: |
3154 | outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR)); | 3155 | outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR)); |
3155 | set_current_state(TASK_UNINTERRUPTIBLE); | 3156 | msleep(20); |
3156 | schedule_timeout(1 + 20 * HZ / 1000); /* 20msec */ | ||
3157 | return 0; | 3157 | return 0; |
3158 | case GAMEPORT_MODE_RAW: | 3158 | case GAMEPORT_MODE_RAW: |
3159 | outb(0, TRID_REG(chip, GAMEPORT_GCR)); | 3159 | outb(0, TRID_REG(chip, GAMEPORT_GCR)); |
@@ -3204,7 +3204,7 @@ static inline void snd_trident_free_gameport(trident_t *chip) { } | |||
3204 | /* | 3204 | /* |
3205 | * delay for 1 tick | 3205 | * delay for 1 tick |
3206 | */ | 3206 | */ |
3207 | inline static void do_delay(trident_t *chip) | 3207 | static inline void do_delay(trident_t *chip) |
3208 | { | 3208 | { |
3209 | set_current_state(TASK_UNINTERRUPTIBLE); | 3209 | set_current_state(TASK_UNINTERRUPTIBLE); |
3210 | schedule_timeout(1); | 3210 | schedule_timeout(1); |
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 6cc282681e09..333d3790692a 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c | |||
@@ -118,7 +118,7 @@ static inline void set_silent_tlb(trident_t *trident, int page) | |||
118 | #endif /* PAGE_SIZE */ | 118 | #endif /* PAGE_SIZE */ |
119 | 119 | ||
120 | /* calculate buffer pointer from offset address */ | 120 | /* calculate buffer pointer from offset address */ |
121 | inline static void *offset_ptr(trident_t *trident, int offset) | 121 | static inline void *offset_ptr(trident_t *trident, int offset) |
122 | { | 122 | { |
123 | char *ptr; | 123 | char *ptr; |
124 | ptr = page_to_ptr(trident, get_aligned_page(offset)); | 124 | ptr = page_to_ptr(trident, get_aligned_page(offset)); |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 9b4d74d49f98..4889600387c8 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -101,7 +101,7 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); | |||
101 | module_param_array(ac97_quirk, charp, NULL, 0444); | 101 | module_param_array(ac97_quirk, charp, NULL, 0444); |
102 | MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); | 102 | MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); |
103 | module_param_array(dxs_support, int, NULL, 0444); | 103 | module_param_array(dxs_support, int, NULL, 0444); |
104 | MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA)"); | 104 | MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)"); |
105 | 105 | ||
106 | 106 | ||
107 | /* pci ids */ | 107 | /* pci ids */ |
@@ -302,6 +302,7 @@ DEFINE_VIA_REGSET(CAPTURE_8233, 0x60); | |||
302 | #define VIA_DXS_DISABLE 2 | 302 | #define VIA_DXS_DISABLE 2 |
303 | #define VIA_DXS_48K 3 | 303 | #define VIA_DXS_48K 3 |
304 | #define VIA_DXS_NO_VRA 4 | 304 | #define VIA_DXS_NO_VRA 4 |
305 | #define VIA_DXS_SRC 5 | ||
305 | 306 | ||
306 | 307 | ||
307 | /* | 308 | /* |
@@ -380,6 +381,7 @@ struct _snd_via82xx { | |||
380 | struct via_rate_lock rates[2]; /* playback and capture */ | 381 | struct via_rate_lock rates[2]; /* playback and capture */ |
381 | unsigned int dxs_fixed: 1; /* DXS channel accepts only 48kHz */ | 382 | unsigned int dxs_fixed: 1; /* DXS channel accepts only 48kHz */ |
382 | unsigned int no_vra: 1; /* no need to set VRA on DXS channels */ | 383 | unsigned int no_vra: 1; /* no need to set VRA on DXS channels */ |
384 | unsigned int dxs_src: 1; /* use full SRC capabilities of DXS */ | ||
383 | unsigned int spdif_on: 1; /* only spdif rates work to external DACs */ | 385 | unsigned int spdif_on: 1; /* only spdif rates work to external DACs */ |
384 | 386 | ||
385 | snd_pcm_t *pcms[2]; | 387 | snd_pcm_t *pcms[2]; |
@@ -489,10 +491,8 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream, | |||
489 | snd_dma_free_pages(&dev->table); | 491 | snd_dma_free_pages(&dev->table); |
490 | dev->table.area = NULL; | 492 | dev->table.area = NULL; |
491 | } | 493 | } |
492 | if (dev->idx_table) { | 494 | kfree(dev->idx_table); |
493 | kfree(dev->idx_table); | 495 | dev->idx_table = NULL; |
494 | dev->idx_table = NULL; | ||
495 | } | ||
496 | return 0; | 496 | return 0; |
497 | } | 497 | } |
498 | 498 | ||
@@ -547,8 +547,7 @@ static void snd_via82xx_codec_wait(ac97_t *ac97) | |||
547 | int err; | 547 | int err; |
548 | err = snd_via82xx_codec_ready(chip, ac97->num); | 548 | err = snd_via82xx_codec_ready(chip, ac97->num); |
549 | /* here we need to wait fairly for long time.. */ | 549 | /* here we need to wait fairly for long time.. */ |
550 | set_current_state(TASK_UNINTERRUPTIBLE); | 550 | msleep(500); |
551 | schedule_timeout(HZ/2); | ||
552 | } | 551 | } |
553 | 552 | ||
554 | static void snd_via82xx_codec_write(ac97_t *ac97, | 553 | static void snd_via82xx_codec_write(ac97_t *ac97, |
@@ -924,15 +923,17 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream) | |||
924 | via82xx_t *chip = snd_pcm_substream_chip(substream); | 923 | via82xx_t *chip = snd_pcm_substream_chip(substream); |
925 | viadev_t *viadev = (viadev_t *)substream->runtime->private_data; | 924 | viadev_t *viadev = (viadev_t *)substream->runtime->private_data; |
926 | snd_pcm_runtime_t *runtime = substream->runtime; | 925 | snd_pcm_runtime_t *runtime = substream->runtime; |
926 | int ac97_rate = chip->dxs_src ? 48000 : runtime->rate; | ||
927 | int rate_changed; | 927 | int rate_changed; |
928 | u32 rbits; | 928 | u32 rbits; |
929 | 929 | ||
930 | if ((rate_changed = via_lock_rate(&chip->rates[0], runtime->rate)) < 0) | 930 | if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0) |
931 | return rate_changed; | 931 | return rate_changed; |
932 | if (rate_changed) { | 932 | if (rate_changed) { |
933 | snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, | 933 | snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, |
934 | chip->no_vra ? 48000 : runtime->rate); | 934 | chip->no_vra ? 48000 : runtime->rate); |
935 | snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate); | 935 | snd_ac97_set_rate(chip->ac97, AC97_SPDIF, |
936 | chip->no_vra ? 48000 : runtime->rate); | ||
936 | } | 937 | } |
937 | if (runtime->rate == 48000) | 938 | if (runtime->rate == 48000) |
938 | rbits = 0xfffff; | 939 | rbits = 0xfffff; |
@@ -1074,6 +1075,12 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst | |||
1074 | /* fixed DXS playback rate */ | 1075 | /* fixed DXS playback rate */ |
1075 | runtime->hw.rates = SNDRV_PCM_RATE_48000; | 1076 | runtime->hw.rates = SNDRV_PCM_RATE_48000; |
1076 | runtime->hw.rate_min = runtime->hw.rate_max = 48000; | 1077 | runtime->hw.rate_min = runtime->hw.rate_max = 48000; |
1078 | } else if (chip->dxs_src && viadev->reg_offset < 0x40) { | ||
1079 | /* use full SRC capabilities of DXS */ | ||
1080 | runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS | | ||
1081 | SNDRV_PCM_RATE_8000_48000); | ||
1082 | runtime->hw.rate_min = 8000; | ||
1083 | runtime->hw.rate_max = 48000; | ||
1077 | } else if (! ratep->rate) { | 1084 | } else if (! ratep->rate) { |
1078 | int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; | 1085 | int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; |
1079 | runtime->hw.rates = chip->ac97->rates[idx]; | 1086 | runtime->hw.rates = chip->ac97->rates[idx]; |
@@ -1550,51 +1557,51 @@ static void snd_via82xx_mixer_free_ac97(ac97_t *ac97) | |||
1550 | 1557 | ||
1551 | static struct ac97_quirk ac97_quirks[] = { | 1558 | static struct ac97_quirk ac97_quirks[] = { |
1552 | { | 1559 | { |
1553 | .vendor = 0x1106, | 1560 | .subvendor = 0x1106, |
1554 | .device = 0x4161, | 1561 | .subdevice = 0x4161, |
1555 | .codec_id = 0x56494161, /* VT1612A */ | 1562 | .codec_id = 0x56494161, /* VT1612A */ |
1556 | .name = "Soltek SL-75DRV5", | 1563 | .name = "Soltek SL-75DRV5", |
1557 | .type = AC97_TUNE_NONE | 1564 | .type = AC97_TUNE_NONE |
1558 | }, | 1565 | }, |
1559 | { /* FIXME: which codec? */ | 1566 | { /* FIXME: which codec? */ |
1560 | .vendor = 0x1106, | 1567 | .subvendor = 0x1106, |
1561 | .device = 0x4161, | 1568 | .subdevice = 0x4161, |
1562 | .name = "ASRock K7VT2", | 1569 | .name = "ASRock K7VT2", |
1563 | .type = AC97_TUNE_HP_ONLY | 1570 | .type = AC97_TUNE_HP_ONLY |
1564 | }, | 1571 | }, |
1565 | { | 1572 | { |
1566 | .vendor = 0x1019, | 1573 | .subvendor = 0x1019, |
1567 | .device = 0x0a81, | 1574 | .subdevice = 0x0a81, |
1568 | .name = "ECS K7VTA3", | 1575 | .name = "ECS K7VTA3", |
1569 | .type = AC97_TUNE_HP_ONLY | 1576 | .type = AC97_TUNE_HP_ONLY |
1570 | }, | 1577 | }, |
1571 | { | 1578 | { |
1572 | .vendor = 0x1019, | 1579 | .subvendor = 0x1019, |
1573 | .device = 0x0a85, | 1580 | .subdevice = 0x0a85, |
1574 | .name = "ECS L7VMM2", | 1581 | .name = "ECS L7VMM2", |
1575 | .type = AC97_TUNE_HP_ONLY | 1582 | .type = AC97_TUNE_HP_ONLY |
1576 | }, | 1583 | }, |
1577 | { | 1584 | { |
1578 | .vendor = 0x1849, | 1585 | .subvendor = 0x1849, |
1579 | .device = 0x3059, | 1586 | .subdevice = 0x3059, |
1580 | .name = "ASRock K7VM2", | 1587 | .name = "ASRock K7VM2", |
1581 | .type = AC97_TUNE_HP_ONLY /* VT1616 */ | 1588 | .type = AC97_TUNE_HP_ONLY /* VT1616 */ |
1582 | }, | 1589 | }, |
1583 | { | 1590 | { |
1584 | .vendor = 0x14cd, | 1591 | .subvendor = 0x14cd, |
1585 | .device = 0x7002, | 1592 | .subdevice = 0x7002, |
1586 | .name = "Unknown", | 1593 | .name = "Unknown", |
1587 | .type = AC97_TUNE_ALC_JACK | 1594 | .type = AC97_TUNE_ALC_JACK |
1588 | }, | 1595 | }, |
1589 | { | 1596 | { |
1590 | .vendor = 0x1071, | 1597 | .subvendor = 0x1071, |
1591 | .device = 0x8590, | 1598 | .subdevice = 0x8590, |
1592 | .name = "Mitac Mobo", | 1599 | .name = "Mitac Mobo", |
1593 | .type = AC97_TUNE_ALC_JACK | 1600 | .type = AC97_TUNE_ALC_JACK |
1594 | }, | 1601 | }, |
1595 | { | 1602 | { |
1596 | .vendor = 0x161f, | 1603 | .subvendor = 0x161f, |
1597 | .device = 0x202b, | 1604 | .subdevice = 0x202b, |
1598 | .name = "Arima Notebook", | 1605 | .name = "Arima Notebook", |
1599 | .type = AC97_TUNE_HP_ONLY, | 1606 | .type = AC97_TUNE_HP_ONLY, |
1600 | }, | 1607 | }, |
@@ -1839,7 +1846,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip) | |||
1839 | static int snd_via82xx_chip_init(via82xx_t *chip) | 1846 | static int snd_via82xx_chip_init(via82xx_t *chip) |
1840 | { | 1847 | { |
1841 | unsigned int val; | 1848 | unsigned int val; |
1842 | int max_count; | 1849 | unsigned long end_time; |
1843 | unsigned char pval; | 1850 | unsigned char pval; |
1844 | 1851 | ||
1845 | #if 0 /* broken on K7M? */ | 1852 | #if 0 /* broken on K7M? */ |
@@ -1881,14 +1888,14 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
1881 | } | 1888 | } |
1882 | 1889 | ||
1883 | /* wait until codec ready */ | 1890 | /* wait until codec ready */ |
1884 | max_count = ((3 * HZ) / 4) + 1; | 1891 | end_time = jiffies + msecs_to_jiffies(750); |
1885 | do { | 1892 | do { |
1886 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 1893 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
1887 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 1894 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
1888 | break; | 1895 | break; |
1889 | set_current_state(TASK_UNINTERRUPTIBLE); | 1896 | set_current_state(TASK_UNINTERRUPTIBLE); |
1890 | schedule_timeout(1); | 1897 | schedule_timeout(1); |
1891 | } while (--max_count > 0); | 1898 | } while (time_before(jiffies, end_time)); |
1892 | 1899 | ||
1893 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 1900 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
1894 | snd_printk("AC'97 codec is not ready [0x%x]\n", val); | 1901 | snd_printk("AC'97 codec is not ready [0x%x]\n", val); |
@@ -1897,7 +1904,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
1897 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | | 1904 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | |
1898 | VIA_REG_AC97_SECONDARY_VALID | | 1905 | VIA_REG_AC97_SECONDARY_VALID | |
1899 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); | 1906 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); |
1900 | max_count = ((3 * HZ) / 4) + 1; | 1907 | end_time = jiffies + msecs_to_jiffies(750); |
1901 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | | 1908 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | |
1902 | VIA_REG_AC97_SECONDARY_VALID | | 1909 | VIA_REG_AC97_SECONDARY_VALID | |
1903 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); | 1910 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); |
@@ -1908,7 +1915,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
1908 | } | 1915 | } |
1909 | set_current_state(TASK_INTERRUPTIBLE); | 1916 | set_current_state(TASK_INTERRUPTIBLE); |
1910 | schedule_timeout(1); | 1917 | schedule_timeout(1); |
1911 | } while (--max_count > 0); | 1918 | } while (time_before(jiffies, end_time)); |
1912 | /* This is ok, the most of motherboards have only one codec */ | 1919 | /* This is ok, the most of motherboards have only one codec */ |
1913 | 1920 | ||
1914 | __ac97_ok2: | 1921 | __ac97_ok2: |
@@ -2132,8 +2139,8 @@ static struct via823x_info via823x_cards[] __devinitdata = { | |||
2132 | * auto detection of DXS channel supports. | 2139 | * auto detection of DXS channel supports. |
2133 | */ | 2140 | */ |
2134 | struct dxs_whitelist { | 2141 | struct dxs_whitelist { |
2135 | unsigned short vendor; | 2142 | unsigned short subvendor; |
2136 | unsigned short device; | 2143 | unsigned short subdevice; |
2137 | unsigned short mask; | 2144 | unsigned short mask; |
2138 | short action; /* new dxs_support value */ | 2145 | short action; /* new dxs_support value */ |
2139 | }; | 2146 | }; |
@@ -2141,38 +2148,45 @@ struct dxs_whitelist { | |||
2141 | static int __devinit check_dxs_list(struct pci_dev *pci) | 2148 | static int __devinit check_dxs_list(struct pci_dev *pci) |
2142 | { | 2149 | { |
2143 | static struct dxs_whitelist whitelist[] = { | 2150 | static struct dxs_whitelist whitelist[] = { |
2144 | { .vendor = 0x1005, .device = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */ | 2151 | { .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */ |
2145 | { .vendor = 0x1019, .device = 0x0996, .action = VIA_DXS_48K }, | 2152 | { .subvendor = 0x1019, .subdevice = 0x0996, .action = VIA_DXS_48K }, |
2146 | { .vendor = 0x1019, .device = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */ | 2153 | { .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */ |
2147 | { .vendor = 0x1019, .device = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */ | 2154 | { .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */ |
2148 | { .vendor = 0x1025, .device = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */ | 2155 | { .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */ |
2149 | { .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/ | 2156 | { .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/ |
2150 | { .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */ | 2157 | { .subvendor = 0x1043, .subdevice = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */ |
2151 | { .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ | 2158 | { .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ |
2152 | { .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ | 2159 | { .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */ |
2153 | { .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */ | 2160 | { .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ |
2154 | { .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */ | 2161 | { .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */ |
2155 | { .vendor = 0x1106, .device = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */ | 2162 | { .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */ |
2156 | { .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */ | 2163 | { .subvendor = 0x1106, .subdevice = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */ |
2157 | { .vendor = 0x1297, .device = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */ | 2164 | { .subvendor = 0x1106, .subdevice = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */ |
2158 | { .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */ | 2165 | { .subvendor = 0x1106, .subdevice = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */ |
2159 | { .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */ | 2166 | { .subvendor = 0x1106, .subdevice = 0xc001, .action = VIA_DXS_SRC }, /* Insight P4-ITX */ |
2160 | { .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ | 2167 | { .subvendor = 0x1297, .subdevice = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */ |
2161 | { .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */ | 2168 | { .subvendor = 0x1297, .subdevice = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */ |
2162 | { .vendor = 0x1462, .device = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */ | 2169 | { .subvendor = 0x1458, .subdevice = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */ |
2163 | { .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */ | 2170 | { .subvendor = 0x1462, .subdevice = 0x0080, .action = VIA_DXS_SRC }, /* MSI K8T Neo-FIS2R */ |
2164 | { .vendor = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */ | 2171 | { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ |
2165 | { .vendor = 0x147b, .device = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */ | 2172 | { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */ |
2166 | { .vendor = 0x147b, .device = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */ | 2173 | { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */ |
2167 | { .vendor = 0x147b, .device = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ | 2174 | { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */ |
2168 | { .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ | 2175 | { .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */ |
2169 | { .vendor = 0x1584, .device = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ | 2176 | { .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */ |
2170 | { .vendor = 0x1584, .device = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ | 2177 | { .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */ |
2171 | { .vendor = 0x161f, .device = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ | 2178 | { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ |
2172 | { .vendor = 0x161f, .device = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */ | 2179 | { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ |
2173 | { .vendor = 0x1631, .device = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */ | 2180 | { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_SRC }, /* Twinhead laptop */ |
2174 | { .vendor = 0x1695, .device = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ | 2181 | { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ |
2175 | { .vendor = 0x1849, .device = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ | 2182 | { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ |
2183 | { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ | ||
2184 | { .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */ | ||
2185 | { .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */ | ||
2186 | { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ | ||
2187 | { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ | ||
2188 | { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */ | ||
2189 | { .subvendor = 0x4005, .subdevice = 0x4710, .action = VIA_DXS_SRC }, /* MSI K7T266 Pro2 (MS-6380 V2.0) BIOS 3.7 */ | ||
2176 | { } /* terminator */ | 2190 | { } /* terminator */ |
2177 | }; | 2191 | }; |
2178 | struct dxs_whitelist *w; | 2192 | struct dxs_whitelist *w; |
@@ -2182,14 +2196,14 @@ static int __devinit check_dxs_list(struct pci_dev *pci) | |||
2182 | pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); | 2196 | pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); |
2183 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device); | 2197 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device); |
2184 | 2198 | ||
2185 | for (w = whitelist; w->vendor; w++) { | 2199 | for (w = whitelist; w->subvendor; w++) { |
2186 | if (w->vendor != subsystem_vendor) | 2200 | if (w->subvendor != subsystem_vendor) |
2187 | continue; | 2201 | continue; |
2188 | if (w->mask) { | 2202 | if (w->mask) { |
2189 | if ((w->mask & subsystem_device) == w->device) | 2203 | if ((w->mask & subsystem_device) == w->subdevice) |
2190 | return w->action; | 2204 | return w->action; |
2191 | } else { | 2205 | } else { |
2192 | if (subsystem_device == w->device) | 2206 | if (subsystem_device == w->subdevice) |
2193 | return w->action; | 2207 | return w->action; |
2194 | } | 2208 | } |
2195 | } | 2209 | } |
@@ -2198,8 +2212,9 @@ static int __devinit check_dxs_list(struct pci_dev *pci) | |||
2198 | * not detected, try 48k rate only to be sure. | 2212 | * not detected, try 48k rate only to be sure. |
2199 | */ | 2213 | */ |
2200 | printk(KERN_INFO "via82xx: Assuming DXS channels with 48k fixed sample rate.\n"); | 2214 | printk(KERN_INFO "via82xx: Assuming DXS channels with 48k fixed sample rate.\n"); |
2201 | printk(KERN_INFO " Please try dxs_support=1 or dxs_support=4 option\n"); | 2215 | printk(KERN_INFO " Please try dxs_support=5 option\n"); |
2202 | printk(KERN_INFO " and report if it works on your machine.\n"); | 2216 | printk(KERN_INFO " and report if it works on your machine.\n"); |
2217 | printk(KERN_INFO " For more details, read ALSA-Configuration.txt.\n"); | ||
2203 | return VIA_DXS_48K; | 2218 | return VIA_DXS_48K; |
2204 | }; | 2219 | }; |
2205 | 2220 | ||
@@ -2288,6 +2303,10 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, | |||
2288 | chip->dxs_fixed = 1; | 2303 | chip->dxs_fixed = 1; |
2289 | else if (dxs_support[dev] == VIA_DXS_NO_VRA) | 2304 | else if (dxs_support[dev] == VIA_DXS_NO_VRA) |
2290 | chip->no_vra = 1; | 2305 | chip->no_vra = 1; |
2306 | else if (dxs_support[dev] == VIA_DXS_SRC) { | ||
2307 | chip->no_vra = 1; | ||
2308 | chip->dxs_src = 1; | ||
2309 | } | ||
2291 | } | 2310 | } |
2292 | if ((err = snd_via8233_init_misc(chip, dev)) < 0) | 2311 | if ((err = snd_via8233_init_misc(chip, dev)) < 0) |
2293 | goto __error; | 2312 | goto __error; |
@@ -2334,7 +2353,7 @@ static struct pci_driver driver = { | |||
2334 | 2353 | ||
2335 | static int __init alsa_card_via82xx_init(void) | 2354 | static int __init alsa_card_via82xx_init(void) |
2336 | { | 2355 | { |
2337 | return pci_module_init(&driver); | 2356 | return pci_register_driver(&driver); |
2338 | } | 2357 | } |
2339 | 2358 | ||
2340 | static void __exit alsa_card_via82xx_exit(void) | 2359 | static void __exit alsa_card_via82xx_exit(void) |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index ea5c6f640159..4a9779cc9733 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -352,10 +352,8 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream, | |||
352 | snd_dma_free_pages(&dev->table); | 352 | snd_dma_free_pages(&dev->table); |
353 | dev->table.area = NULL; | 353 | dev->table.area = NULL; |
354 | } | 354 | } |
355 | if (dev->idx_table) { | 355 | kfree(dev->idx_table); |
356 | kfree(dev->idx_table); | 356 | dev->idx_table = NULL; |
357 | dev->idx_table = NULL; | ||
358 | } | ||
359 | return 0; | 357 | return 0; |
360 | } | 358 | } |
361 | 359 | ||
@@ -410,8 +408,7 @@ static void snd_via82xx_codec_wait(ac97_t *ac97) | |||
410 | int err; | 408 | int err; |
411 | err = snd_via82xx_codec_ready(chip, ac97->num); | 409 | err = snd_via82xx_codec_ready(chip, ac97->num); |
412 | /* here we need to wait fairly for long time.. */ | 410 | /* here we need to wait fairly for long time.. */ |
413 | set_current_state(TASK_UNINTERRUPTIBLE); | 411 | msleep(500); |
414 | schedule_timeout(HZ/2); | ||
415 | } | 412 | } |
416 | 413 | ||
417 | static void snd_via82xx_codec_write(ac97_t *ac97, | 414 | static void snd_via82xx_codec_write(ac97_t *ac97, |
@@ -420,7 +417,10 @@ static void snd_via82xx_codec_write(ac97_t *ac97, | |||
420 | { | 417 | { |
421 | via82xx_t *chip = ac97->private_data; | 418 | via82xx_t *chip = ac97->private_data; |
422 | unsigned int xval; | 419 | unsigned int xval; |
423 | 420 | if(reg == AC97_GPIO_STATUS) { | |
421 | outl(val, VIAREG(chip, GPI_STATUS)); | ||
422 | return; | ||
423 | } | ||
424 | xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY; | 424 | xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY; |
425 | xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; | 425 | xval <<= VIA_REG_AC97_CODEC_ID_SHIFT; |
426 | xval |= reg << VIA_REG_AC97_CMD_SHIFT; | 426 | xval |= reg << VIA_REG_AC97_CMD_SHIFT; |
@@ -544,25 +544,6 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd) | |||
544 | return 0; | 544 | return 0; |
545 | } | 545 | } |
546 | 546 | ||
547 | static int snd_via82xx_modem_pcm_trigger(snd_pcm_substream_t * substream, int cmd) | ||
548 | { | ||
549 | via82xx_t *chip = snd_pcm_substream_chip(substream); | ||
550 | unsigned int val = 0; | ||
551 | switch (cmd) { | ||
552 | case SNDRV_PCM_TRIGGER_START: | ||
553 | val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS); | ||
554 | outl(val|AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS)); | ||
555 | break; | ||
556 | case SNDRV_PCM_TRIGGER_STOP: | ||
557 | val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS); | ||
558 | outl(val&~AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS)); | ||
559 | break; | ||
560 | default: | ||
561 | break; | ||
562 | } | ||
563 | return snd_via82xx_pcm_trigger(substream, cmd); | ||
564 | } | ||
565 | |||
566 | /* | 547 | /* |
567 | * pointer callbacks | 548 | * pointer callbacks |
568 | */ | 549 | */ |
@@ -806,7 +787,7 @@ static snd_pcm_ops_t snd_via686_playback_ops = { | |||
806 | .hw_params = snd_via82xx_hw_params, | 787 | .hw_params = snd_via82xx_hw_params, |
807 | .hw_free = snd_via82xx_hw_free, | 788 | .hw_free = snd_via82xx_hw_free, |
808 | .prepare = snd_via82xx_pcm_prepare, | 789 | .prepare = snd_via82xx_pcm_prepare, |
809 | .trigger = snd_via82xx_modem_pcm_trigger, | 790 | .trigger = snd_via82xx_pcm_trigger, |
810 | .pointer = snd_via686_pcm_pointer, | 791 | .pointer = snd_via686_pcm_pointer, |
811 | .page = snd_pcm_sgbuf_ops_page, | 792 | .page = snd_pcm_sgbuf_ops_page, |
812 | }; | 793 | }; |
@@ -819,7 +800,7 @@ static snd_pcm_ops_t snd_via686_capture_ops = { | |||
819 | .hw_params = snd_via82xx_hw_params, | 800 | .hw_params = snd_via82xx_hw_params, |
820 | .hw_free = snd_via82xx_hw_free, | 801 | .hw_free = snd_via82xx_hw_free, |
821 | .prepare = snd_via82xx_pcm_prepare, | 802 | .prepare = snd_via82xx_pcm_prepare, |
822 | .trigger = snd_via82xx_modem_pcm_trigger, | 803 | .trigger = snd_via82xx_pcm_trigger, |
823 | .pointer = snd_via686_pcm_pointer, | 804 | .pointer = snd_via686_pcm_pointer, |
824 | .page = snd_pcm_sgbuf_ops_page, | 805 | .page = snd_pcm_sgbuf_ops_page, |
825 | }; | 806 | }; |
@@ -938,10 +919,10 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip) | |||
938 | * | 919 | * |
939 | */ | 920 | */ |
940 | 921 | ||
941 | static int __devinit snd_via82xx_chip_init(via82xx_t *chip) | 922 | static int snd_via82xx_chip_init(via82xx_t *chip) |
942 | { | 923 | { |
943 | unsigned int val; | 924 | unsigned int val; |
944 | int max_count; | 925 | unsigned long end_time; |
945 | unsigned char pval; | 926 | unsigned char pval; |
946 | 927 | ||
947 | pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval); | 928 | pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval); |
@@ -980,14 +961,14 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip) | |||
980 | } | 961 | } |
981 | 962 | ||
982 | /* wait until codec ready */ | 963 | /* wait until codec ready */ |
983 | max_count = ((3 * HZ) / 4) + 1; | 964 | end_time = jiffies + msecs_to_jiffies(750); |
984 | do { | 965 | do { |
985 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 966 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
986 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 967 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
987 | break; | 968 | break; |
988 | set_current_state(TASK_UNINTERRUPTIBLE); | 969 | set_current_state(TASK_UNINTERRUPTIBLE); |
989 | schedule_timeout(1); | 970 | schedule_timeout(1); |
990 | } while (--max_count > 0); | 971 | } while (time_before(jiffies, end_time)); |
991 | 972 | ||
992 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 973 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
993 | snd_printk("AC'97 codec is not ready [0x%x]\n", val); | 974 | snd_printk("AC'97 codec is not ready [0x%x]\n", val); |
@@ -995,7 +976,7 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip) | |||
995 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | | 976 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | |
996 | VIA_REG_AC97_SECONDARY_VALID | | 977 | VIA_REG_AC97_SECONDARY_VALID | |
997 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); | 978 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); |
998 | max_count = ((3 * HZ) / 4) + 1; | 979 | end_time = jiffies + msecs_to_jiffies(750); |
999 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | | 980 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | |
1000 | VIA_REG_AC97_SECONDARY_VALID | | 981 | VIA_REG_AC97_SECONDARY_VALID | |
1001 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); | 982 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); |
@@ -1006,7 +987,7 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip) | |||
1006 | } | 987 | } |
1007 | set_current_state(TASK_INTERRUPTIBLE); | 988 | set_current_state(TASK_INTERRUPTIBLE); |
1008 | schedule_timeout(1); | 989 | schedule_timeout(1); |
1009 | } while (--max_count > 0); | 990 | } while (time_before(jiffies, end_time)); |
1010 | /* This is ok, the most of motherboards have only one codec */ | 991 | /* This is ok, the most of motherboards have only one codec */ |
1011 | 992 | ||
1012 | __ac97_ok2: | 993 | __ac97_ok2: |
@@ -1233,7 +1214,7 @@ static struct pci_driver driver = { | |||
1233 | 1214 | ||
1234 | static int __init alsa_card_via82xx_init(void) | 1215 | static int __init alsa_card_via82xx_init(void) |
1235 | { | 1216 | { |
1236 | return pci_module_init(&driver); | 1217 | return pci_register_driver(&driver); |
1237 | } | 1218 | } |
1238 | 1219 | ||
1239 | static void __exit alsa_card_via82xx_exit(void) | 1220 | static void __exit alsa_card_via82xx_exit(void) |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index 4ffbb25658a5..dca6bd2c7580 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
@@ -260,7 +260,7 @@ static struct pci_driver driver = { | |||
260 | 260 | ||
261 | static int __init alsa_card_vx222_init(void) | 261 | static int __init alsa_card_vx222_init(void) |
262 | { | 262 | { |
263 | return pci_module_init(&driver); | 263 | return pci_register_driver(&driver); |
264 | } | 264 | } |
265 | 265 | ||
266 | static void __exit alsa_card_vx222_exit(void) | 266 | static void __exit alsa_card_vx222_exit(void) |
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 683e9799976f..967bd5e6b23c 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c | |||
@@ -82,7 +82,7 @@ static int vx2_reg_index[VX_REG_MAX] = { | |||
82 | [VX_GPIOC] = 0, /* on the PLX */ | 82 | [VX_GPIOC] = 0, /* on the PLX */ |
83 | }; | 83 | }; |
84 | 84 | ||
85 | inline static unsigned long vx2_reg_addr(vx_core_t *_chip, int reg) | 85 | static inline unsigned long vx2_reg_addr(vx_core_t *_chip, int reg) |
86 | { | 86 | { |
87 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; | 87 | struct snd_vx222 *chip = (struct snd_vx222 *)_chip; |
88 | return chip->port[vx2_reg_index[reg]] + vx2_reg_offset[reg]; | 88 | return chip->port[vx2_reg_index[reg]] + vx2_reg_offset[reg]; |
@@ -235,7 +235,7 @@ static void vx2_setup_pseudo_dma(vx_core_t *chip, int do_write) | |||
235 | /* | 235 | /* |
236 | * vx_release_pseudo_dma - disable the pseudo-DMA mode | 236 | * vx_release_pseudo_dma - disable the pseudo-DMA mode |
237 | */ | 237 | */ |
238 | inline static void vx2_release_pseudo_dma(vx_core_t *chip) | 238 | static inline void vx2_release_pseudo_dma(vx_core_t *chip) |
239 | { | 239 | { |
240 | /* HREQ pin disabled. */ | 240 | /* HREQ pin disabled. */ |
241 | vx_outl(chip, ICR, 0); | 241 | vx_outl(chip, ICR, 0); |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 9f3ef22df08d..5b5b624b47d0 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -360,7 +360,7 @@ static struct pci_driver driver = { | |||
360 | 360 | ||
361 | static int __init alsa_card_ymfpci_init(void) | 361 | static int __init alsa_card_ymfpci_init(void) |
362 | { | 362 | { |
363 | return pci_module_init(&driver); | 363 | return pci_register_driver(&driver); |
364 | } | 364 | } |
365 | 365 | ||
366 | static void __exit alsa_card_ymfpci_exit(void) | 366 | static void __exit alsa_card_ymfpci_exit(void) |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 05f1629760bc..d54f88a1b525 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -84,16 +84,16 @@ static inline void snd_ymfpci_writel(ymfpci_t *chip, u32 offset, u32 val) | |||
84 | 84 | ||
85 | static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary) | 85 | static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary) |
86 | { | 86 | { |
87 | signed long end_time; | 87 | unsigned long end_time; |
88 | u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR; | 88 | u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR; |
89 | 89 | ||
90 | end_time = (jiffies + ((3 * HZ) / 4)) + 1; | 90 | end_time = jiffies + msecs_to_jiffies(750); |
91 | do { | 91 | do { |
92 | if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0) | 92 | if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0) |
93 | return 0; | 93 | return 0; |
94 | set_current_state(TASK_UNINTERRUPTIBLE); | 94 | set_current_state(TASK_UNINTERRUPTIBLE); |
95 | schedule_timeout(1); | 95 | schedule_timeout(1); |
96 | } while (end_time - (signed long)jiffies >= 0); | 96 | } while (time_before(jiffies, end_time)); |
97 | snd_printk("codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); | 97 | snd_printk("codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); |
98 | return -EBUSY; | 98 | return -EBUSY; |
99 | } | 99 | } |
@@ -829,9 +829,7 @@ static snd_pcm_hardware_t snd_ymfpci_capture = | |||
829 | 829 | ||
830 | static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime) | 830 | static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime) |
831 | { | 831 | { |
832 | ymfpci_pcm_t *ypcm = runtime->private_data; | 832 | kfree(runtime->private_data); |
833 | |||
834 | kfree(ypcm); | ||
835 | } | 833 | } |
836 | 834 | ||
837 | static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream) | 835 | static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream) |
@@ -1421,17 +1419,15 @@ static snd_kcontrol_new_t snd_ymfpci_drec_source __devinitdata = { | |||
1421 | 1419 | ||
1422 | static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) | 1420 | static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) |
1423 | { | 1421 | { |
1424 | unsigned int mask = 1; | ||
1425 | |||
1426 | switch (kcontrol->private_value) { | 1422 | switch (kcontrol->private_value) { |
1427 | case YDSXGR_SPDIFOUTCTRL: break; | 1423 | case YDSXGR_SPDIFOUTCTRL: break; |
1428 | case YDSXGR_SPDIFINCTRL: break; | 1424 | case YDSXGR_SPDIFINCTRL: break; |
1429 | default: return -EINVAL; | 1425 | default: return -EINVAL; |
1430 | } | 1426 | } |
1431 | uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | 1427 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
1432 | uinfo->count = 1; | 1428 | uinfo->count = 1; |
1433 | uinfo->value.integer.min = 0; | 1429 | uinfo->value.integer.min = 0; |
1434 | uinfo->value.integer.max = mask; | 1430 | uinfo->value.integer.max = 1; |
1435 | return 0; | 1431 | return 0; |
1436 | } | 1432 | } |
1437 | 1433 | ||
@@ -1439,7 +1435,7 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1439 | { | 1435 | { |
1440 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); | 1436 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); |
1441 | int reg = kcontrol->private_value; | 1437 | int reg = kcontrol->private_value; |
1442 | unsigned int shift = 0, mask = 1, invert = 0; | 1438 | unsigned int shift = 0, mask = 1; |
1443 | 1439 | ||
1444 | switch (kcontrol->private_value) { | 1440 | switch (kcontrol->private_value) { |
1445 | case YDSXGR_SPDIFOUTCTRL: break; | 1441 | case YDSXGR_SPDIFOUTCTRL: break; |
@@ -1447,8 +1443,6 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1447 | default: return -EINVAL; | 1443 | default: return -EINVAL; |
1448 | } | 1444 | } |
1449 | ucontrol->value.integer.value[0] = (snd_ymfpci_readl(chip, reg) >> shift) & mask; | 1445 | ucontrol->value.integer.value[0] = (snd_ymfpci_readl(chip, reg) >> shift) & mask; |
1450 | if (invert) | ||
1451 | ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; | ||
1452 | return 0; | 1446 | return 0; |
1453 | } | 1447 | } |
1454 | 1448 | ||
@@ -1456,7 +1450,7 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1456 | { | 1450 | { |
1457 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); | 1451 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); |
1458 | int reg = kcontrol->private_value; | 1452 | int reg = kcontrol->private_value; |
1459 | unsigned int shift = 0, mask = 1, invert = 0; | 1453 | unsigned int shift = 0, mask = 1; |
1460 | int change; | 1454 | int change; |
1461 | unsigned int val, oval; | 1455 | unsigned int val, oval; |
1462 | 1456 | ||
@@ -1466,8 +1460,6 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1466 | default: return -EINVAL; | 1460 | default: return -EINVAL; |
1467 | } | 1461 | } |
1468 | val = (ucontrol->value.integer.value[0] & mask); | 1462 | val = (ucontrol->value.integer.value[0] & mask); |
1469 | if (invert) | ||
1470 | val = mask - val; | ||
1471 | val <<= shift; | 1463 | val <<= shift; |
1472 | spin_lock_irq(&chip->reg_lock); | 1464 | spin_lock_irq(&chip->reg_lock); |
1473 | oval = snd_ymfpci_readl(chip, reg); | 1465 | oval = snd_ymfpci_readl(chip, reg); |
@@ -1487,14 +1479,13 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1487 | static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) | 1479 | static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) |
1488 | { | 1480 | { |
1489 | unsigned int reg = kcontrol->private_value; | 1481 | unsigned int reg = kcontrol->private_value; |
1490 | unsigned int mask = 16383; | ||
1491 | 1482 | ||
1492 | if (reg < 0x80 || reg >= 0xc0) | 1483 | if (reg < 0x80 || reg >= 0xc0) |
1493 | return -EINVAL; | 1484 | return -EINVAL; |
1494 | uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | 1485 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1495 | uinfo->count = 2; | 1486 | uinfo->count = 2; |
1496 | uinfo->value.integer.min = 0; | 1487 | uinfo->value.integer.min = 0; |
1497 | uinfo->value.integer.max = mask; | 1488 | uinfo->value.integer.max = 16383; |
1498 | return 0; | 1489 | return 0; |
1499 | } | 1490 | } |
1500 | 1491 | ||
@@ -1502,7 +1493,7 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1502 | { | 1493 | { |
1503 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); | 1494 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); |
1504 | unsigned int reg = kcontrol->private_value; | 1495 | unsigned int reg = kcontrol->private_value; |
1505 | unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0; | 1496 | unsigned int shift_left = 0, shift_right = 16, mask = 16383; |
1506 | unsigned int val; | 1497 | unsigned int val; |
1507 | 1498 | ||
1508 | if (reg < 0x80 || reg >= 0xc0) | 1499 | if (reg < 0x80 || reg >= 0xc0) |
@@ -1512,10 +1503,6 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1512 | spin_unlock_irq(&chip->reg_lock); | 1503 | spin_unlock_irq(&chip->reg_lock); |
1513 | ucontrol->value.integer.value[0] = (val >> shift_left) & mask; | 1504 | ucontrol->value.integer.value[0] = (val >> shift_left) & mask; |
1514 | ucontrol->value.integer.value[1] = (val >> shift_right) & mask; | 1505 | ucontrol->value.integer.value[1] = (val >> shift_right) & mask; |
1515 | if (invert) { | ||
1516 | ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; | ||
1517 | ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1]; | ||
1518 | } | ||
1519 | return 0; | 1506 | return 0; |
1520 | } | 1507 | } |
1521 | 1508 | ||
@@ -1523,7 +1510,7 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1523 | { | 1510 | { |
1524 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); | 1511 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); |
1525 | unsigned int reg = kcontrol->private_value; | 1512 | unsigned int reg = kcontrol->private_value; |
1526 | unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0; | 1513 | unsigned int shift_left = 0, shift_right = 16, mask = 16383; |
1527 | int change; | 1514 | int change; |
1528 | unsigned int val1, val2, oval; | 1515 | unsigned int val1, val2, oval; |
1529 | 1516 | ||
@@ -1531,10 +1518,6 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1531 | return -EINVAL; | 1518 | return -EINVAL; |
1532 | val1 = ucontrol->value.integer.value[0] & mask; | 1519 | val1 = ucontrol->value.integer.value[0] & mask; |
1533 | val2 = ucontrol->value.integer.value[1] & mask; | 1520 | val2 = ucontrol->value.integer.value[1] & mask; |
1534 | if (invert) { | ||
1535 | val1 = mask - val1; | ||
1536 | val2 = mask - val2; | ||
1537 | } | ||
1538 | val1 <<= shift_left; | 1521 | val1 <<= shift_left; |
1539 | val2 <<= shift_right; | 1522 | val2 <<= shift_right; |
1540 | spin_lock_irq(&chip->reg_lock); | 1523 | spin_lock_irq(&chip->reg_lock); |
diff --git a/sound/pcmcia/Kconfig b/sound/pcmcia/Kconfig index 3611e298834f..5d1b0b762efa 100644 --- a/sound/pcmcia/Kconfig +++ b/sound/pcmcia/Kconfig | |||
@@ -8,23 +8,12 @@ config SND_VXPOCKET | |||
8 | depends on SND && PCMCIA && ISA | 8 | depends on SND && PCMCIA && ISA |
9 | select SND_VX_LIB | 9 | select SND_VX_LIB |
10 | help | 10 | help |
11 | Say Y here to include support for Digigram VXpocket | 11 | Say Y here to include support for Digigram VXpocket and |
12 | soundcards. | 12 | VXpocket 440 soundcards. |
13 | 13 | ||
14 | To compile this driver as a module, choose M here: the module | 14 | To compile this driver as a module, choose M here: the module |
15 | will be called snd-vxpocket. | 15 | will be called snd-vxpocket. |
16 | 16 | ||
17 | config SND_VXP440 | ||
18 | tristate "Digigram VXpocket 440" | ||
19 | depends on SND && PCMCIA && ISA | ||
20 | select SND_VX_LIB | ||
21 | help | ||
22 | Say Y here to include support for Digigram VXpocket 440 | ||
23 | soundcards. | ||
24 | |||
25 | To compile this driver as a module, choose M here: the module | ||
26 | will be called snd-vxp440. | ||
27 | |||
28 | config SND_PDAUDIOCF | 17 | config SND_PDAUDIOCF |
29 | tristate "Sound Core PDAudioCF" | 18 | tristate "Sound Core PDAudioCF" |
30 | depends on SND && PCMCIA && ISA | 19 | depends on SND && PCMCIA && ISA |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index f72c81cc9952..d6918b453f28 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <sound/core.h> | 22 | #include <sound/core.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/moduleparam.h> | 24 | #include <linux/moduleparam.h> |
25 | #include <pcmcia/version.h> | ||
26 | #include <pcmcia/ciscode.h> | 25 | #include <pcmcia/ciscode.h> |
27 | #include <pcmcia/cisreg.h> | 26 | #include <pcmcia/cisreg.h> |
28 | #include "pdaudiocf.h" | 27 | #include "pdaudiocf.h" |
@@ -171,14 +170,6 @@ static dev_link_t *snd_pdacf_attach(void) | |||
171 | 170 | ||
172 | /* Register with Card Services */ | 171 | /* Register with Card Services */ |
173 | client_reg.dev_info = &dev_info; | 172 | client_reg.dev_info = &dev_info; |
174 | client_reg.EventMask = | ||
175 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | ||
176 | #ifdef CONFIG_PM | ||
177 | | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | ||
178 | | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME | ||
179 | #endif | ||
180 | ; | ||
181 | client_reg.event_handler = &pdacf_event; | ||
182 | client_reg.Version = 0x0210; | 173 | client_reg.Version = 0x0210; |
183 | client_reg.event_callback_args.client_data = link; | 174 | client_reg.event_callback_args.client_data = link; |
184 | 175 | ||
@@ -380,13 +371,21 @@ static int pdacf_event(event_t event, int priority, event_callback_args_t *args) | |||
380 | /* | 371 | /* |
381 | * Module entry points | 372 | * Module entry points |
382 | */ | 373 | */ |
374 | static struct pcmcia_device_id snd_pdacf_ids[] = { | ||
375 | PCMCIA_DEVICE_MANF_CARD(0x015d, 0x4c45), | ||
376 | PCMCIA_DEVICE_NULL | ||
377 | }; | ||
378 | MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids); | ||
379 | |||
383 | static struct pcmcia_driver pdacf_cs_driver = { | 380 | static struct pcmcia_driver pdacf_cs_driver = { |
384 | .owner = THIS_MODULE, | 381 | .owner = THIS_MODULE, |
385 | .drv = { | 382 | .drv = { |
386 | .name = "snd-pdaudiocf", | 383 | .name = "snd-pdaudiocf", |
387 | }, | 384 | }, |
388 | .attach = snd_pdacf_attach, | 385 | .attach = snd_pdacf_attach, |
389 | .detach = snd_pdacf_detach | 386 | .event = pdacf_event, |
387 | .detach = snd_pdacf_detach, | ||
388 | .id_table = snd_pdacf_ids, | ||
390 | }; | 389 | }; |
391 | 390 | ||
392 | static int __init init_pdacf(void) | 391 | static int __init init_pdacf(void) |
diff --git a/sound/pcmcia/vx/Makefile b/sound/pcmcia/vx/Makefile index f35dfa1af094..54971f01e968 100644 --- a/sound/pcmcia/vx/Makefile +++ b/sound/pcmcia/vx/Makefile | |||
@@ -3,9 +3,6 @@ | |||
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-vx-cs-objs := vx_entry.o vxp_ops.o vxp_mixer.o | 6 | snd-vxpocket-objs := vxpocket.o vxp_ops.o vxp_mixer.o |
7 | snd-vxpocket-objs := vxpocket.o | ||
8 | snd-vxp440-objs := vxp440.o | ||
9 | 7 | ||
10 | obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o snd-vx-cs.o | 8 | obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o |
11 | obj-$(CONFIG_SND_VXP440) += snd-vxp440.o snd-vx-cs.o | ||
diff --git a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c deleted file mode 100644 index 53d8172c52ae..000000000000 --- a/sound/pcmcia/vx/vx_entry.c +++ /dev/null | |||
@@ -1,384 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for Digigram VXpocket soundcards | ||
3 | * | ||
4 | * PCMCIA entry part | ||
5 | * | ||
6 | * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <sound/driver.h> | ||
24 | #include <sound/core.h> | ||
25 | #include "vxpocket.h" | ||
26 | #include <pcmcia/ciscode.h> | ||
27 | #include <pcmcia/cisreg.h> | ||
28 | |||
29 | |||
30 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); | ||
31 | MODULE_DESCRIPTION("Common routines for Digigram PCMCIA VX drivers"); | ||
32 | MODULE_LICENSE("GPL"); | ||
33 | |||
34 | /* | ||
35 | * prototypes | ||
36 | */ | ||
37 | static void vxpocket_config(dev_link_t *link); | ||
38 | static int vxpocket_event(event_t event, int priority, event_callback_args_t *args); | ||
39 | |||
40 | |||
41 | static void vxpocket_release(dev_link_t *link) | ||
42 | { | ||
43 | if (link->state & DEV_CONFIG) { | ||
44 | /* release cs resources */ | ||
45 | pcmcia_release_configuration(link->handle); | ||
46 | pcmcia_release_io(link->handle, &link->io); | ||
47 | pcmcia_release_irq(link->handle, &link->irq); | ||
48 | link->state &= ~DEV_CONFIG; | ||
49 | } | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * destructor | ||
54 | */ | ||
55 | static int snd_vxpocket_free(vx_core_t *chip) | ||
56 | { | ||
57 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
58 | struct snd_vxp_entry *hw; | ||
59 | dev_link_t *link = &vxp->link; | ||
60 | |||
61 | vxpocket_release(link); | ||
62 | |||
63 | /* Break the link with Card Services */ | ||
64 | if (link->handle) | ||
65 | pcmcia_deregister_client(link->handle); | ||
66 | |||
67 | hw = vxp->hw_entry; | ||
68 | if (hw) | ||
69 | hw->card_list[vxp->index] = NULL; | ||
70 | chip->card = NULL; | ||
71 | if (chip->dev) | ||
72 | kfree(chip->dev); | ||
73 | |||
74 | snd_vx_free_firmware(chip); | ||
75 | kfree(chip); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int snd_vxpocket_dev_free(snd_device_t *device) | ||
80 | { | ||
81 | vx_core_t *chip = device->device_data; | ||
82 | return snd_vxpocket_free(chip); | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * snd_vxpocket_attach - attach callback for cs | ||
87 | * @hw: the hardware information | ||
88 | */ | ||
89 | dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw) | ||
90 | { | ||
91 | client_reg_t client_reg; /* Register with cardmgr */ | ||
92 | dev_link_t *link; /* Info for cardmgr */ | ||
93 | int i, ret; | ||
94 | vx_core_t *chip; | ||
95 | struct snd_vxpocket *vxp; | ||
96 | snd_card_t *card; | ||
97 | static snd_device_ops_t ops = { | ||
98 | .dev_free = snd_vxpocket_dev_free, | ||
99 | }; | ||
100 | |||
101 | snd_printdd(KERN_DEBUG "vxpocket_attach called\n"); | ||
102 | /* find an empty slot from the card list */ | ||
103 | for (i = 0; i < SNDRV_CARDS; i++) { | ||
104 | if (! hw->card_list[i]) | ||
105 | break; | ||
106 | } | ||
107 | if (i >= SNDRV_CARDS) { | ||
108 | snd_printk(KERN_ERR "vxpocket: too many cards found\n"); | ||
109 | return NULL; | ||
110 | } | ||
111 | if (! hw->enable_table[i]) | ||
112 | return NULL; /* disabled explicitly */ | ||
113 | |||
114 | /* ok, create a card instance */ | ||
115 | card = snd_card_new(hw->index_table[i], hw->id_table[i], THIS_MODULE, 0); | ||
116 | if (card == NULL) { | ||
117 | snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); | ||
118 | return NULL; | ||
119 | } | ||
120 | |||
121 | chip = snd_vx_create(card, hw->hardware, hw->ops, | ||
122 | sizeof(struct snd_vxpocket) - sizeof(vx_core_t)); | ||
123 | if (! chip) | ||
124 | return NULL; | ||
125 | |||
126 | #ifdef SND_VX_FW_LOADER | ||
127 | /* fake a device here since pcmcia doesn't give a valid device... */ | ||
128 | chip->dev = kcalloc(1, sizeof(*chip->dev), GFP_KERNEL); | ||
129 | if (! chip->dev) { | ||
130 | snd_printk(KERN_ERR "vxp: can't malloc chip->dev\n"); | ||
131 | kfree(chip); | ||
132 | snd_card_free(card); | ||
133 | return NULL; | ||
134 | } | ||
135 | device_initialize(chip->dev); | ||
136 | sprintf(chip->dev->bus_id, "vxpocket%d", i); | ||
137 | #endif | ||
138 | |||
139 | if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) { | ||
140 | kfree(chip); | ||
141 | snd_card_free(card); | ||
142 | return NULL; | ||
143 | } | ||
144 | |||
145 | vxp = (struct snd_vxpocket *)chip; | ||
146 | vxp->index = i; | ||
147 | vxp->hw_entry = hw; | ||
148 | chip->ibl.size = hw->ibl[i]; | ||
149 | hw->card_list[i] = chip; | ||
150 | |||
151 | link = &vxp->link; | ||
152 | link->priv = chip; | ||
153 | |||
154 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
155 | link->io.NumPorts1 = 16; | ||
156 | |||
157 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
158 | // link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | ||
159 | |||
160 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
161 | link->irq.Handler = &snd_vx_irq_handler; | ||
162 | link->irq.Instance = chip; | ||
163 | |||
164 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
165 | link->conf.Vcc = 50; | ||
166 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
167 | link->conf.ConfigIndex = 1; | ||
168 | link->conf.Present = PRESENT_OPTION; | ||
169 | |||
170 | /* Register with Card Services */ | ||
171 | memset(&client_reg, 0, sizeof(client_reg)); | ||
172 | client_reg.dev_info = hw->dev_info; | ||
173 | client_reg.EventMask = | ||
174 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | ||
175 | #ifdef CONFIG_PM | ||
176 | | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | ||
177 | | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME | ||
178 | #endif | ||
179 | ; | ||
180 | client_reg.event_handler = &vxpocket_event; | ||
181 | client_reg.Version = 0x0210; | ||
182 | client_reg.event_callback_args.client_data = link; | ||
183 | |||
184 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
185 | if (ret != CS_SUCCESS) { | ||
186 | cs_error(link->handle, RegisterClient, ret); | ||
187 | snd_card_free(card); | ||
188 | return NULL; | ||
189 | } | ||
190 | |||
191 | /* Chain drivers */ | ||
192 | link->next = hw->dev_list; | ||
193 | hw->dev_list = link; | ||
194 | |||
195 | /* snd_card_set_pm_callback(card, snd_vxpocket_suspend, snd_vxpocket_resume, chip); */ | ||
196 | |||
197 | return link; | ||
198 | } | ||
199 | |||
200 | |||
201 | /** | ||
202 | * snd_vxpocket_assign_resources - initialize the hardware and card instance. | ||
203 | * @port: i/o port for the card | ||
204 | * @irq: irq number for the card | ||
205 | * | ||
206 | * this function assigns the specified port and irq, boot the card, | ||
207 | * create pcm and control instances, and initialize the rest hardware. | ||
208 | * | ||
209 | * returns 0 if successful, or a negative error code. | ||
210 | */ | ||
211 | static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq) | ||
212 | { | ||
213 | int err; | ||
214 | snd_card_t *card = chip->card; | ||
215 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
216 | |||
217 | snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); | ||
218 | vxp->port = port; | ||
219 | |||
220 | sprintf(card->shortname, "Digigram %s", card->driver); | ||
221 | sprintf(card->longname, "%s at 0x%x, irq %i", | ||
222 | card->shortname, port, irq); | ||
223 | |||
224 | chip->irq = irq; | ||
225 | |||
226 | if ((err = snd_vx_setup_firmware(chip)) < 0) | ||
227 | return err; | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | |||
233 | /* | ||
234 | * snd_vxpocket_detach - detach callback for cs | ||
235 | * @hw: the hardware information | ||
236 | */ | ||
237 | void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link) | ||
238 | { | ||
239 | vx_core_t *chip; | ||
240 | |||
241 | if (! link) | ||
242 | return; | ||
243 | |||
244 | chip = link->priv; | ||
245 | |||
246 | snd_printdd(KERN_DEBUG "vxpocket_detach called\n"); | ||
247 | /* Remove the interface data from the linked list */ | ||
248 | if (hw) { | ||
249 | dev_link_t **linkp; | ||
250 | /* Locate device structure */ | ||
251 | for (linkp = &hw->dev_list; *linkp; linkp = &(*linkp)->next) | ||
252 | if (*linkp == link) { | ||
253 | *linkp = link->next; | ||
254 | break; | ||
255 | } | ||
256 | } | ||
257 | chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ | ||
258 | snd_card_disconnect(chip->card); | ||
259 | snd_card_free_in_thread(chip->card); | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * configuration callback | ||
264 | */ | ||
265 | |||
266 | #define CS_CHECK(fn, ret) \ | ||
267 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
268 | |||
269 | static void vxpocket_config(dev_link_t *link) | ||
270 | { | ||
271 | client_handle_t handle = link->handle; | ||
272 | vx_core_t *chip = link->priv; | ||
273 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
274 | tuple_t tuple; | ||
275 | cisparse_t *parse = NULL; | ||
276 | u_short buf[32]; | ||
277 | int last_fn, last_ret; | ||
278 | |||
279 | snd_printdd(KERN_DEBUG "vxpocket_config called\n"); | ||
280 | parse = kmalloc(sizeof(*parse), GFP_KERNEL); | ||
281 | if (! parse) { | ||
282 | snd_printk(KERN_ERR "vx: cannot allocate\n"); | ||
283 | return; | ||
284 | } | ||
285 | tuple.Attributes = 0; | ||
286 | tuple.TupleData = (cisdata_t *)buf; | ||
287 | tuple.TupleDataMax = sizeof(buf); | ||
288 | tuple.TupleOffset = 0; | ||
289 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
290 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
291 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
292 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); | ||
293 | link->conf.ConfigBase = parse->config.base; | ||
294 | link->conf.Present = parse->config.rmask[0]; | ||
295 | |||
296 | /* Configure card */ | ||
297 | link->state |= DEV_CONFIG; | ||
298 | |||
299 | CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io)); | ||
300 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | ||
301 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | ||
302 | |||
303 | if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0) | ||
304 | goto failed; | ||
305 | |||
306 | link->dev = &vxp->node; | ||
307 | link->state &= ~DEV_CONFIG_PENDING; | ||
308 | kfree(parse); | ||
309 | return; | ||
310 | |||
311 | cs_failed: | ||
312 | cs_error(link->handle, last_fn, last_ret); | ||
313 | failed: | ||
314 | pcmcia_release_configuration(link->handle); | ||
315 | pcmcia_release_io(link->handle, &link->io); | ||
316 | pcmcia_release_irq(link->handle, &link->irq); | ||
317 | link->state &= ~DEV_CONFIG; | ||
318 | kfree(parse); | ||
319 | } | ||
320 | |||
321 | |||
322 | /* | ||
323 | * event callback | ||
324 | */ | ||
325 | static int vxpocket_event(event_t event, int priority, event_callback_args_t *args) | ||
326 | { | ||
327 | dev_link_t *link = args->client_data; | ||
328 | vx_core_t *chip = link->priv; | ||
329 | |||
330 | switch (event) { | ||
331 | case CS_EVENT_CARD_REMOVAL: | ||
332 | snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n"); | ||
333 | link->state &= ~DEV_PRESENT; | ||
334 | if (link->state & DEV_CONFIG) { | ||
335 | chip->chip_status |= VX_STAT_IS_STALE; | ||
336 | } | ||
337 | break; | ||
338 | case CS_EVENT_CARD_INSERTION: | ||
339 | snd_printdd(KERN_DEBUG "CARD_INSERTION..\n"); | ||
340 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
341 | vxpocket_config(link); | ||
342 | break; | ||
343 | #ifdef CONFIG_PM | ||
344 | case CS_EVENT_PM_SUSPEND: | ||
345 | snd_printdd(KERN_DEBUG "SUSPEND\n"); | ||
346 | link->state |= DEV_SUSPEND; | ||
347 | if (chip && chip->card->pm_suspend) { | ||
348 | snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); | ||
349 | chip->card->pm_suspend(chip->card, PMSG_SUSPEND); | ||
350 | } | ||
351 | /* Fall through... */ | ||
352 | case CS_EVENT_RESET_PHYSICAL: | ||
353 | snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n"); | ||
354 | if (link->state & DEV_CONFIG) | ||
355 | pcmcia_release_configuration(link->handle); | ||
356 | break; | ||
357 | case CS_EVENT_PM_RESUME: | ||
358 | snd_printdd(KERN_DEBUG "RESUME\n"); | ||
359 | link->state &= ~DEV_SUSPEND; | ||
360 | /* Fall through... */ | ||
361 | case CS_EVENT_CARD_RESET: | ||
362 | snd_printdd(KERN_DEBUG "CARD_RESET\n"); | ||
363 | if (DEV_OK(link)) { | ||
364 | //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
365 | snd_printdd(KERN_DEBUG "requestconfig...\n"); | ||
366 | pcmcia_request_configuration(link->handle, &link->conf); | ||
367 | if (chip && chip->card->pm_resume) { | ||
368 | snd_printdd(KERN_DEBUG "calling snd_vx_resume\n"); | ||
369 | chip->card->pm_resume(chip->card); | ||
370 | } | ||
371 | } | ||
372 | snd_printdd(KERN_DEBUG "resume done!\n"); | ||
373 | break; | ||
374 | #endif | ||
375 | } | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * exported stuffs | ||
381 | */ | ||
382 | EXPORT_SYMBOL(snd_vxpocket_ops); | ||
383 | EXPORT_SYMBOL(snd_vxpocket_attach); | ||
384 | EXPORT_SYMBOL(snd_vxpocket_detach); | ||
diff --git a/sound/pcmcia/vx/vxp440.c b/sound/pcmcia/vx/vxp440.c deleted file mode 100644 index 59190a833001..000000000000 --- a/sound/pcmcia/vx/vxp440.c +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | #define COMPILE_VXP440 | ||
2 | |||
3 | /* | ||
4 | add the following as /etc/pcmcia/vxp440.conf: | ||
5 | |||
6 | device "snd-vxp440" | ||
7 | class "audio" module "snd-vxp440" | ||
8 | |||
9 | card "Digigram VX-POCKET440" | ||
10 | manfid 0x01f1, 0x0100 | ||
11 | bind "snd-vxp440" | ||
12 | */ | ||
13 | |||
14 | #include "vxpocket.c" | ||
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index ef6734271607..6f15c3d03ab5 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c | |||
@@ -49,7 +49,7 @@ static int vxp_reg_offset[VX_REG_MAX] = { | |||
49 | }; | 49 | }; |
50 | 50 | ||
51 | 51 | ||
52 | inline static unsigned long vxp_reg_addr(vx_core_t *_chip, int reg) | 52 | static inline unsigned long vxp_reg_addr(vx_core_t *_chip, int reg) |
53 | { | 53 | { |
54 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; | 54 | struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; |
55 | return chip->port + vxp_reg_offset[reg]; | 55 | return chip->port + vxp_reg_offset[reg]; |
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index fce2ad04fd8b..3a82161d3b24 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
@@ -18,39 +18,23 @@ | |||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | /* | ||
22 | please add the following as /etc/pcmcia/vxpocket.conf: | ||
23 | |||
24 | device "snd-vxpocket" | ||
25 | class "audio" module "snd-vxpocket" | ||
26 | |||
27 | card "Digigram VX-POCKET" | ||
28 | manfid 0x01f1, 0x0100 | ||
29 | bind "snd-vxpocket" | ||
30 | |||
31 | */ | ||
32 | 21 | ||
33 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
34 | #include <linux/init.h> | 23 | #include <linux/init.h> |
35 | #include <linux/moduleparam.h> | 24 | #include <linux/moduleparam.h> |
36 | #include <sound/core.h> | 25 | #include <sound/core.h> |
37 | #include <pcmcia/version.h> | ||
38 | #include "vxpocket.h" | 26 | #include "vxpocket.h" |
27 | #include <pcmcia/ciscode.h> | ||
28 | #include <pcmcia/cisreg.h> | ||
39 | #include <sound/initval.h> | 29 | #include <sound/initval.h> |
40 | 30 | ||
41 | /* | 31 | /* |
42 | */ | 32 | */ |
43 | 33 | ||
44 | #ifdef COMPILE_VXP440 | ||
45 | #define CARD_NAME "VXPocket440" | ||
46 | #else | ||
47 | #define CARD_NAME "VXPocket" | ||
48 | #endif | ||
49 | |||
50 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); | 34 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); |
51 | MODULE_DESCRIPTION("Digigram " CARD_NAME); | 35 | MODULE_DESCRIPTION("Digigram VXPocket"); |
52 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
53 | MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}"); | 37 | MODULE_SUPPORTED_DEVICE("{{Digigram,VXPocket},{Digigram,VXPocket440}}"); |
54 | 38 | ||
55 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 39 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
56 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 40 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
@@ -58,95 +42,425 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ | |||
58 | static int ibl[SNDRV_CARDS]; | 42 | static int ibl[SNDRV_CARDS]; |
59 | 43 | ||
60 | module_param_array(index, int, NULL, 0444); | 44 | module_param_array(index, int, NULL, 0444); |
61 | MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); | 45 | MODULE_PARM_DESC(index, "Index value for VXPocket soundcard."); |
62 | module_param_array(id, charp, NULL, 0444); | 46 | module_param_array(id, charp, NULL, 0444); |
63 | MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); | 47 | MODULE_PARM_DESC(id, "ID string for VXPocket soundcard."); |
64 | module_param_array(enable, bool, NULL, 0444); | 48 | module_param_array(enable, bool, NULL, 0444); |
65 | MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); | 49 | MODULE_PARM_DESC(enable, "Enable VXPocket soundcard."); |
66 | module_param_array(ibl, int, NULL, 0444); | 50 | module_param_array(ibl, int, NULL, 0444); |
67 | MODULE_PARM_DESC(ibl, "Capture IBL size for " CARD_NAME " soundcard."); | 51 | MODULE_PARM_DESC(ibl, "Capture IBL size for VXPocket soundcard."); |
68 | 52 | ||
69 | 53 | ||
70 | /* | 54 | /* |
71 | */ | 55 | */ |
72 | 56 | ||
73 | #ifdef COMPILE_VXP440 | 57 | static unsigned int card_alloc; |
58 | static dev_link_t *dev_list; /* Linked list of devices */ | ||
59 | static dev_info_t dev_info = "snd-vxpocket"; | ||
60 | |||
61 | |||
62 | static int vxpocket_event(event_t event, int priority, event_callback_args_t *args); | ||
74 | 63 | ||
75 | /* 1 DSP, 1 sync UER, 1 sync World Clock (NIY) */ | ||
76 | /* SMPTE (NIY) */ | ||
77 | /* 2 stereo analog input (line/micro) */ | ||
78 | /* 2 stereo analog output */ | ||
79 | /* Only output levels can be modified */ | ||
80 | /* UER, but only for the first two inputs and outputs. */ | ||
81 | 64 | ||
82 | #define NUM_CODECS 2 | 65 | /* |
83 | #define CARD_TYPE VX_TYPE_VXP440 | 66 | */ |
84 | #define DEV_INFO "snd-vxp440" | 67 | static void vxpocket_release(dev_link_t *link) |
68 | { | ||
69 | if (link->state & DEV_CONFIG) { | ||
70 | /* release cs resources */ | ||
71 | pcmcia_release_configuration(link->handle); | ||
72 | pcmcia_release_io(link->handle, &link->io); | ||
73 | pcmcia_release_irq(link->handle, &link->irq); | ||
74 | link->state &= ~DEV_CONFIG; | ||
75 | } | ||
76 | if (link->handle) { | ||
77 | /* Break the link with Card Services */ | ||
78 | pcmcia_deregister_client(link->handle); | ||
79 | link->handle = NULL; | ||
80 | } | ||
81 | } | ||
85 | 82 | ||
86 | #else | 83 | /* |
84 | * destructor, called from snd_card_free_in_thread() | ||
85 | */ | ||
86 | static int snd_vxpocket_dev_free(snd_device_t *device) | ||
87 | { | ||
88 | vx_core_t *chip = device->device_data; | ||
87 | 89 | ||
88 | /* 1 DSP, 1 sync UER */ | 90 | snd_vx_free_firmware(chip); |
89 | /* 1 programmable clock (NIY) */ | 91 | kfree(chip); |
90 | /* 1 stereo analog input (line/micro) */ | 92 | return 0; |
91 | /* 1 stereo analog output */ | 93 | } |
92 | /* Only output levels can be modified */ | ||
93 | 94 | ||
94 | #define NUM_CODECS 1 | ||
95 | #define CARD_TYPE VX_TYPE_VXPOCKET | ||
96 | #define DEV_INFO "snd-vxpocket" | ||
97 | 95 | ||
98 | #endif | 96 | /* |
97 | * Hardware information | ||
98 | */ | ||
99 | 99 | ||
100 | static dev_info_t dev_info = DEV_INFO; | 100 | /* VX-pocket V2 |
101 | * | ||
102 | * 1 DSP, 1 sync UER | ||
103 | * 1 programmable clock (NIY) | ||
104 | * 1 stereo analog input (line/micro) | ||
105 | * 1 stereo analog output | ||
106 | * Only output levels can be modified | ||
107 | */ | ||
101 | 108 | ||
102 | static struct snd_vx_hardware vxp_hw = { | 109 | static struct snd_vx_hardware vxpocket_hw = { |
103 | .name = CARD_NAME, | 110 | .name = "VXPocket", |
104 | .type = CARD_TYPE, | 111 | .type = VX_TYPE_VXPOCKET, |
105 | 112 | ||
106 | /* hardware specs */ | 113 | /* hardware specs */ |
107 | .num_codecs = NUM_CODECS, | 114 | .num_codecs = 1, |
108 | .num_ins = NUM_CODECS, | 115 | .num_ins = 1, |
109 | .num_outs = NUM_CODECS, | 116 | .num_outs = 1, |
110 | .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, | 117 | .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, |
111 | }; | 118 | }; |
112 | 119 | ||
113 | static struct snd_vxp_entry hw_entry = { | 120 | /* VX-pocket 440 |
114 | .dev_info = &dev_info, | 121 | * |
122 | * 1 DSP, 1 sync UER, 1 sync World Clock (NIY) | ||
123 | * SMPTE (NIY) | ||
124 | * 2 stereo analog input (line/micro) | ||
125 | * 2 stereo analog output | ||
126 | * Only output levels can be modified | ||
127 | * UER, but only for the first two inputs and outputs. | ||
128 | */ | ||
129 | |||
130 | static struct snd_vx_hardware vxp440_hw = { | ||
131 | .name = "VXPocket440", | ||
132 | .type = VX_TYPE_VXP440, | ||
115 | 133 | ||
116 | /* module parameters */ | 134 | /* hardware specs */ |
117 | .index_table = index, | 135 | .num_codecs = 2, |
118 | .id_table = id, | 136 | .num_ins = 2, |
119 | .enable_table = enable, | 137 | .num_outs = 2, |
120 | .ibl = ibl, | 138 | .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, |
139 | }; | ||
140 | |||
141 | |||
142 | /* | ||
143 | * create vxpocket instance | ||
144 | */ | ||
145 | static struct snd_vxpocket *snd_vxpocket_new(snd_card_t *card, int ibl) | ||
146 | { | ||
147 | client_reg_t client_reg; /* Register with cardmgr */ | ||
148 | dev_link_t *link; /* Info for cardmgr */ | ||
149 | vx_core_t *chip; | ||
150 | struct snd_vxpocket *vxp; | ||
151 | int ret; | ||
152 | static snd_device_ops_t ops = { | ||
153 | .dev_free = snd_vxpocket_dev_free, | ||
154 | }; | ||
155 | |||
156 | chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops, | ||
157 | sizeof(struct snd_vxpocket) - sizeof(vx_core_t)); | ||
158 | if (! chip) | ||
159 | return NULL; | ||
160 | |||
161 | if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) { | ||
162 | kfree(chip); | ||
163 | return NULL; | ||
164 | } | ||
165 | chip->ibl.size = ibl; | ||
166 | |||
167 | vxp = (struct snd_vxpocket *)chip; | ||
168 | |||
169 | link = &vxp->link; | ||
170 | link->priv = chip; | ||
171 | |||
172 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
173 | link->io.NumPorts1 = 16; | ||
174 | |||
175 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
176 | |||
177 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
178 | link->irq.Handler = &snd_vx_irq_handler; | ||
179 | link->irq.Instance = chip; | ||
180 | |||
181 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
182 | link->conf.Vcc = 50; | ||
183 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
184 | link->conf.ConfigIndex = 1; | ||
185 | link->conf.Present = PRESENT_OPTION; | ||
186 | |||
187 | /* Register with Card Services */ | ||
188 | memset(&client_reg, 0, sizeof(client_reg)); | ||
189 | client_reg.dev_info = &dev_info; | ||
190 | client_reg.EventMask = | ||
191 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | ||
192 | #ifdef CONFIG_PM | ||
193 | | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | ||
194 | | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME | ||
195 | #endif | ||
196 | ; | ||
197 | client_reg.event_handler = &vxpocket_event; | ||
198 | client_reg.Version = 0x0210; | ||
199 | client_reg.event_callback_args.client_data = link; | ||
200 | |||
201 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
202 | if (ret != CS_SUCCESS) { | ||
203 | cs_error(link->handle, RegisterClient, ret); | ||
204 | return NULL; | ||
205 | } | ||
206 | |||
207 | return vxp; | ||
208 | } | ||
209 | |||
210 | |||
211 | /** | ||
212 | * snd_vxpocket_assign_resources - initialize the hardware and card instance. | ||
213 | * @port: i/o port for the card | ||
214 | * @irq: irq number for the card | ||
215 | * | ||
216 | * this function assigns the specified port and irq, boot the card, | ||
217 | * create pcm and control instances, and initialize the rest hardware. | ||
218 | * | ||
219 | * returns 0 if successful, or a negative error code. | ||
220 | */ | ||
221 | static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq) | ||
222 | { | ||
223 | int err; | ||
224 | snd_card_t *card = chip->card; | ||
225 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
226 | |||
227 | snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); | ||
228 | vxp->port = port; | ||
229 | |||
230 | sprintf(card->shortname, "Digigram %s", card->driver); | ||
231 | sprintf(card->longname, "%s at 0x%x, irq %i", | ||
232 | card->shortname, port, irq); | ||
233 | |||
234 | chip->irq = irq; | ||
235 | |||
236 | if ((err = snd_vx_setup_firmware(chip)) < 0) | ||
237 | return err; | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | |||
243 | /* | ||
244 | * configuration callback | ||
245 | */ | ||
246 | |||
247 | #define CS_CHECK(fn, ret) \ | ||
248 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
249 | |||
250 | static void vxpocket_config(dev_link_t *link) | ||
251 | { | ||
252 | client_handle_t handle = link->handle; | ||
253 | vx_core_t *chip = link->priv; | ||
254 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
255 | tuple_t tuple; | ||
256 | cisparse_t *parse; | ||
257 | u_short buf[32]; | ||
258 | int last_fn, last_ret; | ||
259 | |||
260 | snd_printdd(KERN_DEBUG "vxpocket_config called\n"); | ||
261 | parse = kmalloc(sizeof(*parse), GFP_KERNEL); | ||
262 | if (! parse) { | ||
263 | snd_printk(KERN_ERR "vx: cannot allocate\n"); | ||
264 | return; | ||
265 | } | ||
266 | tuple.Attributes = 0; | ||
267 | tuple.TupleData = (cisdata_t *)buf; | ||
268 | tuple.TupleDataMax = sizeof(buf); | ||
269 | tuple.TupleOffset = 0; | ||
270 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
271 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
272 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
273 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); | ||
274 | link->conf.ConfigBase = parse->config.base; | ||
275 | link->conf.Present = parse->config.rmask[0]; | ||
276 | |||
277 | /* redefine hardware record according to the VERSION1 string */ | ||
278 | tuple.DesiredTuple = CISTPL_VERS_1; | ||
279 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
280 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
281 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); | ||
282 | if (! strcmp(parse->version_1.str + parse->version_1.ofs[1], "VX-POCKET")) { | ||
283 | snd_printdd("VX-pocket is detected\n"); | ||
284 | } else { | ||
285 | snd_printdd("VX-pocket 440 is detected\n"); | ||
286 | /* overwrite the hardware information */ | ||
287 | chip->hw = &vxp440_hw; | ||
288 | chip->type = vxp440_hw.type; | ||
289 | strcpy(chip->card->driver, vxp440_hw.name); | ||
290 | } | ||
291 | |||
292 | /* Configure card */ | ||
293 | link->state |= DEV_CONFIG; | ||
294 | |||
295 | CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io)); | ||
296 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | ||
297 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | ||
298 | |||
299 | chip->dev = &handle_to_dev(link->handle); | ||
300 | |||
301 | if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0) | ||
302 | goto failed; | ||
303 | |||
304 | link->dev = &vxp->node; | ||
305 | link->state &= ~DEV_CONFIG_PENDING; | ||
306 | kfree(parse); | ||
307 | return; | ||
308 | |||
309 | cs_failed: | ||
310 | cs_error(link->handle, last_fn, last_ret); | ||
311 | failed: | ||
312 | pcmcia_release_configuration(link->handle); | ||
313 | pcmcia_release_io(link->handle, &link->io); | ||
314 | pcmcia_release_irq(link->handle, &link->irq); | ||
315 | link->state &= ~DEV_CONFIG; | ||
316 | kfree(parse); | ||
317 | } | ||
318 | |||
319 | |||
320 | /* | ||
321 | * event callback | ||
322 | */ | ||
323 | static int vxpocket_event(event_t event, int priority, event_callback_args_t *args) | ||
324 | { | ||
325 | dev_link_t *link = args->client_data; | ||
326 | vx_core_t *chip = link->priv; | ||
327 | |||
328 | switch (event) { | ||
329 | case CS_EVENT_CARD_REMOVAL: | ||
330 | snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n"); | ||
331 | link->state &= ~DEV_PRESENT; | ||
332 | if (link->state & DEV_CONFIG) | ||
333 | chip->chip_status |= VX_STAT_IS_STALE; | ||
334 | break; | ||
335 | case CS_EVENT_CARD_INSERTION: | ||
336 | snd_printdd(KERN_DEBUG "CARD_INSERTION..\n"); | ||
337 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
338 | vxpocket_config(link); | ||
339 | break; | ||
340 | #ifdef CONFIG_PM | ||
341 | case CS_EVENT_PM_SUSPEND: | ||
342 | snd_printdd(KERN_DEBUG "SUSPEND\n"); | ||
343 | link->state |= DEV_SUSPEND; | ||
344 | if (chip && chip->card->pm_suspend) { | ||
345 | snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); | ||
346 | chip->card->pm_suspend(chip->card, PMSG_SUSPEND); | ||
347 | } | ||
348 | /* Fall through... */ | ||
349 | case CS_EVENT_RESET_PHYSICAL: | ||
350 | snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n"); | ||
351 | if (link->state & DEV_CONFIG) | ||
352 | pcmcia_release_configuration(link->handle); | ||
353 | break; | ||
354 | case CS_EVENT_PM_RESUME: | ||
355 | snd_printdd(KERN_DEBUG "RESUME\n"); | ||
356 | link->state &= ~DEV_SUSPEND; | ||
357 | /* Fall through... */ | ||
358 | case CS_EVENT_CARD_RESET: | ||
359 | snd_printdd(KERN_DEBUG "CARD_RESET\n"); | ||
360 | if (DEV_OK(link)) { | ||
361 | //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
362 | snd_printdd(KERN_DEBUG "requestconfig...\n"); | ||
363 | pcmcia_request_configuration(link->handle, &link->conf); | ||
364 | if (chip && chip->card->pm_resume) { | ||
365 | snd_printdd(KERN_DEBUG "calling snd_vx_resume\n"); | ||
366 | chip->card->pm_resume(chip->card); | ||
367 | } | ||
368 | } | ||
369 | snd_printdd(KERN_DEBUG "resume done!\n"); | ||
370 | break; | ||
371 | #endif | ||
372 | } | ||
373 | return 0; | ||
374 | } | ||
121 | 375 | ||
122 | /* h/w config */ | ||
123 | .hardware = &vxp_hw, | ||
124 | .ops = &snd_vxpocket_ops, | ||
125 | }; | ||
126 | 376 | ||
127 | /* | 377 | /* |
128 | */ | 378 | */ |
129 | static dev_link_t *vxp_attach(void) | 379 | static dev_link_t *vxp_attach(void) |
130 | { | 380 | { |
131 | return snd_vxpocket_attach(&hw_entry); | 381 | snd_card_t *card; |
382 | struct snd_vxpocket *vxp; | ||
383 | int i; | ||
384 | |||
385 | /* find an empty slot from the card list */ | ||
386 | for (i = 0; i < SNDRV_CARDS; i++) { | ||
387 | if (! card_alloc & (1 << i)) | ||
388 | break; | ||
389 | } | ||
390 | if (i >= SNDRV_CARDS) { | ||
391 | snd_printk(KERN_ERR "vxpocket: too many cards found\n"); | ||
392 | return NULL; | ||
393 | } | ||
394 | if (! enable[i]) | ||
395 | return NULL; /* disabled explicitly */ | ||
396 | |||
397 | /* ok, create a card instance */ | ||
398 | card = snd_card_new(index[i], id[i], THIS_MODULE, 0); | ||
399 | if (card == NULL) { | ||
400 | snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); | ||
401 | return NULL; | ||
402 | } | ||
403 | |||
404 | vxp = snd_vxpocket_new(card, ibl[i]); | ||
405 | if (! vxp) { | ||
406 | snd_card_free(card); | ||
407 | return NULL; | ||
408 | } | ||
409 | |||
410 | vxp->index = index[i]; | ||
411 | card_alloc |= 1 << i; | ||
412 | |||
413 | /* Chain drivers */ | ||
414 | vxp->link.next = dev_list; | ||
415 | dev_list = &vxp->link; | ||
416 | |||
417 | return &vxp->link; | ||
132 | } | 418 | } |
133 | 419 | ||
134 | static void vxp_detach(dev_link_t *link) | 420 | static void vxp_detach(dev_link_t *link) |
135 | { | 421 | { |
136 | snd_vxpocket_detach(&hw_entry, link); | 422 | struct snd_vxpocket *vxp; |
423 | vx_core_t *chip; | ||
424 | dev_link_t **linkp; | ||
425 | |||
426 | if (! link) | ||
427 | return; | ||
428 | |||
429 | vxp = link->priv; | ||
430 | chip = (vx_core_t *)vxp; | ||
431 | card_alloc &= ~(1 << vxp->index); | ||
432 | |||
433 | /* Remove the interface data from the linked list */ | ||
434 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
435 | if (*linkp == link) { | ||
436 | *linkp = link->next; | ||
437 | break; | ||
438 | } | ||
439 | |||
440 | chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ | ||
441 | snd_card_disconnect(chip->card); | ||
442 | vxpocket_release(link); | ||
443 | snd_card_free_in_thread(chip->card); | ||
137 | } | 444 | } |
138 | 445 | ||
139 | /* | 446 | /* |
140 | * Module entry points | 447 | * Module entry points |
141 | */ | 448 | */ |
142 | 449 | ||
450 | static struct pcmcia_device_id vxp_ids[] = { | ||
451 | PCMCIA_DEVICE_MANF_CARD(0x01f1, 0x0100), | ||
452 | PCMCIA_DEVICE_NULL | ||
453 | }; | ||
454 | MODULE_DEVICE_TABLE(pcmcia, vxp_ids); | ||
455 | |||
143 | static struct pcmcia_driver vxp_cs_driver = { | 456 | static struct pcmcia_driver vxp_cs_driver = { |
144 | .owner = THIS_MODULE, | 457 | .owner = THIS_MODULE, |
145 | .drv = { | 458 | .drv = { |
146 | .name = DEV_INFO, | 459 | .name = "snd-vxpocket", |
147 | }, | 460 | }, |
148 | .attach = vxp_attach, | 461 | .attach = vxp_attach, |
149 | .detach = vxp_detach | 462 | .detach = vxp_detach, |
463 | .id_table = vxp_ids, | ||
150 | }; | 464 | }; |
151 | 465 | ||
152 | static int __init init_vxpocket(void) | 466 | static int __init init_vxpocket(void) |
@@ -157,7 +471,7 @@ static int __init init_vxpocket(void) | |||
157 | static void __exit exit_vxpocket(void) | 471 | static void __exit exit_vxpocket(void) |
158 | { | 472 | { |
159 | pcmcia_unregister_driver(&vxp_cs_driver); | 473 | pcmcia_unregister_driver(&vxp_cs_driver); |
160 | BUG_ON(hw_entry.dev_list != NULL); | 474 | BUG_ON(dev_list != NULL); |
161 | } | 475 | } |
162 | 476 | ||
163 | module_init(init_vxpocket); | 477 | module_init(init_vxpocket); |
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h index 4462c04a4e8f..70754aa3dd11 100644 --- a/sound/pcmcia/vx/vxpocket.h +++ b/sound/pcmcia/vx/vxpocket.h | |||
@@ -28,24 +28,6 @@ | |||
28 | #include <pcmcia/cistpl.h> | 28 | #include <pcmcia/cistpl.h> |
29 | #include <pcmcia/ds.h> | 29 | #include <pcmcia/ds.h> |
30 | 30 | ||
31 | struct snd_vxp_entry { | ||
32 | dev_info_t *dev_info; | ||
33 | |||
34 | /* module parameters */ | ||
35 | int *index_table; | ||
36 | char **id_table; | ||
37 | int *enable_table; | ||
38 | int *ibl; | ||
39 | |||
40 | /* h/w config */ | ||
41 | struct snd_vx_hardware *hardware; | ||
42 | struct snd_vx_ops *ops; | ||
43 | |||
44 | /* slots */ | ||
45 | vx_core_t *card_list[SNDRV_CARDS]; | ||
46 | dev_link_t *dev_list; /* Linked list of devices */ | ||
47 | }; | ||
48 | |||
49 | struct snd_vxpocket { | 31 | struct snd_vxpocket { |
50 | 32 | ||
51 | vx_core_t core; | 33 | vx_core_t core; |
@@ -57,8 +39,7 @@ struct snd_vxpocket { | |||
57 | unsigned int regCDSP; /* current CDSP register */ | 39 | unsigned int regCDSP; /* current CDSP register */ |
58 | unsigned int regDIALOG; /* current DIALOG register */ | 40 | unsigned int regDIALOG; /* current DIALOG register */ |
59 | 41 | ||
60 | int index; | 42 | int index; /* card index */ |
61 | struct snd_vxp_entry *hw_entry; | ||
62 | 43 | ||
63 | /* pcmcia stuff */ | 44 | /* pcmcia stuff */ |
64 | dev_link_t link; | 45 | dev_link_t link; |
@@ -70,12 +51,6 @@ extern struct snd_vx_ops snd_vxpocket_ops; | |||
70 | void vx_set_mic_boost(vx_core_t *chip, int boost); | 51 | void vx_set_mic_boost(vx_core_t *chip, int boost); |
71 | void vx_set_mic_level(vx_core_t *chip, int level); | 52 | void vx_set_mic_level(vx_core_t *chip, int level); |
72 | 53 | ||
73 | /* | ||
74 | * pcmcia stuff | ||
75 | */ | ||
76 | dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw); | ||
77 | void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link); | ||
78 | |||
79 | int vxp_add_mic_controls(vx_core_t *chip); | 54 | int vxp_add_mic_controls(vx_core_t *chip); |
80 | 55 | ||
81 | /* Constants used to access the CDSP register (0x08). */ | 56 | /* Constants used to access the CDSP register (0x08). */ |
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index e052bd071e5b..758ca1bcbcf2 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c | |||
@@ -90,7 +90,7 @@ snd_pmac_awacs_write_noreg(pmac_t *chip, int reg, int val) | |||
90 | snd_pmac_awacs_write(chip, val | (reg << 12)); | 90 | snd_pmac_awacs_write(chip, val | (reg << 12)); |
91 | } | 91 | } |
92 | 92 | ||
93 | #ifdef CONFIG_PMAC_PBOOK | 93 | #ifdef CONFIG_PM |
94 | /* Recalibrate chip */ | 94 | /* Recalibrate chip */ |
95 | static void screamer_recalibrate(pmac_t *chip) | 95 | static void screamer_recalibrate(pmac_t *chip) |
96 | { | 96 | { |
@@ -103,7 +103,7 @@ static void screamer_recalibrate(pmac_t *chip) | |||
103 | snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); | 103 | snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); |
104 | if (chip->manufacturer == 0x1) | 104 | if (chip->manufacturer == 0x1) |
105 | /* delay for broken crystal part */ | 105 | /* delay for broken crystal part */ |
106 | big_mdelay(750); | 106 | msleep(750); |
107 | snd_pmac_awacs_write_noreg(chip, 1, | 107 | snd_pmac_awacs_write_noreg(chip, 1, |
108 | chip->awacs_reg[1] | MASK_RECALIBRATE | MASK_CMUTE | MASK_AMUTE); | 108 | chip->awacs_reg[1] | MASK_RECALIBRATE | MASK_CMUTE | MASK_AMUTE); |
109 | snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); | 109 | snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); |
@@ -642,7 +642,7 @@ static void awacs_restore_all_regs(pmac_t *chip) | |||
642 | } | 642 | } |
643 | } | 643 | } |
644 | 644 | ||
645 | #ifdef CONFIG_PMAC_PBOOK | 645 | #ifdef CONFIG_PM |
646 | static void snd_pmac_awacs_suspend(pmac_t *chip) | 646 | static void snd_pmac_awacs_suspend(pmac_t *chip) |
647 | { | 647 | { |
648 | snd_pmac_awacs_write_noreg(chip, 1, (chip->awacs_reg[1] | 648 | snd_pmac_awacs_write_noreg(chip, 1, (chip->awacs_reg[1] |
@@ -653,10 +653,10 @@ static void snd_pmac_awacs_resume(pmac_t *chip) | |||
653 | { | 653 | { |
654 | if (machine_is_compatible("PowerBook3,1") | 654 | if (machine_is_compatible("PowerBook3,1") |
655 | || machine_is_compatible("PowerBook3,2")) { | 655 | || machine_is_compatible("PowerBook3,2")) { |
656 | big_mdelay(100); | 656 | msleep(100); |
657 | snd_pmac_awacs_write_reg(chip, 1, | 657 | snd_pmac_awacs_write_reg(chip, 1, |
658 | chip->awacs_reg[1] & ~MASK_PAROUT); | 658 | chip->awacs_reg[1] & ~MASK_PAROUT); |
659 | big_mdelay(300); | 659 | msleep(300); |
660 | } | 660 | } |
661 | 661 | ||
662 | awacs_restore_all_regs(chip); | 662 | awacs_restore_all_regs(chip); |
@@ -676,7 +676,7 @@ static void snd_pmac_awacs_resume(pmac_t *chip) | |||
676 | } | 676 | } |
677 | #endif | 677 | #endif |
678 | } | 678 | } |
679 | #endif /* CONFIG_PMAC_PBOOK */ | 679 | #endif /* CONFIG_PM */ |
680 | 680 | ||
681 | #ifdef PMAC_SUPPORT_AUTOMUTE | 681 | #ifdef PMAC_SUPPORT_AUTOMUTE |
682 | /* | 682 | /* |
@@ -883,7 +883,7 @@ snd_pmac_awacs_init(pmac_t *chip) | |||
883 | * set lowlevel callbacks | 883 | * set lowlevel callbacks |
884 | */ | 884 | */ |
885 | chip->set_format = snd_pmac_awacs_set_format; | 885 | chip->set_format = snd_pmac_awacs_set_format; |
886 | #ifdef CONFIG_PMAC_PBOOK | 886 | #ifdef CONFIG_PM |
887 | chip->suspend = snd_pmac_awacs_suspend; | 887 | chip->suspend = snd_pmac_awacs_suspend; |
888 | chip->resume = snd_pmac_awacs_resume; | 888 | chip->resume = snd_pmac_awacs_resume; |
889 | #endif | 889 | #endif |
diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c index 3f837d9f3eb1..edbc0484e22a 100644 --- a/sound/ppc/burgundy.c +++ b/sound/ppc/burgundy.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | 31 | ||
32 | /* Waits for busy flag to clear */ | 32 | /* Waits for busy flag to clear */ |
33 | inline static void | 33 | static inline void |
34 | snd_pmac_burgundy_busy_wait(pmac_t *chip) | 34 | snd_pmac_burgundy_busy_wait(pmac_t *chip) |
35 | { | 35 | { |
36 | int timeout = 50; | 36 | int timeout = 50; |
@@ -40,7 +40,7 @@ snd_pmac_burgundy_busy_wait(pmac_t *chip) | |||
40 | printk(KERN_DEBUG "burgundy_busy_wait: timeout\n"); | 40 | printk(KERN_DEBUG "burgundy_busy_wait: timeout\n"); |
41 | } | 41 | } |
42 | 42 | ||
43 | inline static void | 43 | static inline void |
44 | snd_pmac_burgundy_extend_wait(pmac_t *chip) | 44 | snd_pmac_burgundy_extend_wait(pmac_t *chip) |
45 | { | 45 | { |
46 | int timeout; | 46 | int timeout; |
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c index f24a91693616..a737f298e77d 100644 --- a/sound/ppc/daca.c +++ b/sound/ppc/daca.c | |||
@@ -218,7 +218,7 @@ static snd_kcontrol_new_t daca_mixers[] = { | |||
218 | }; | 218 | }; |
219 | 219 | ||
220 | 220 | ||
221 | #ifdef CONFIG_PMAC_PBOOK | 221 | #ifdef CONFIG_PM |
222 | static void daca_resume(pmac_t *chip) | 222 | static void daca_resume(pmac_t *chip) |
223 | { | 223 | { |
224 | pmac_daca_t *mix = chip->mixer_data; | 224 | pmac_daca_t *mix = chip->mixer_data; |
@@ -227,7 +227,7 @@ static void daca_resume(pmac_t *chip) | |||
227 | mix->amp_on ? 0x05 : 0x04); | 227 | mix->amp_on ? 0x05 : 0x04); |
228 | daca_set_volume(mix); | 228 | daca_set_volume(mix); |
229 | } | 229 | } |
230 | #endif /* CONFIG_PMAC_PBOOK */ | 230 | #endif /* CONFIG_PM */ |
231 | 231 | ||
232 | 232 | ||
233 | static void daca_cleanup(pmac_t *chip) | 233 | static void daca_cleanup(pmac_t *chip) |
@@ -275,7 +275,7 @@ int __init snd_pmac_daca_init(pmac_t *chip) | |||
275 | return err; | 275 | return err; |
276 | } | 276 | } |
277 | 277 | ||
278 | #ifdef CONFIG_PMAC_PBOOK | 278 | #ifdef CONFIG_PM |
279 | chip->resume = daca_resume; | 279 | chip->resume = daca_resume; |
280 | #endif | 280 | #endif |
281 | 281 | ||
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 080ef3928465..c89e82eb06a6 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <asm/pci-bridge.h> | 36 | #include <asm/pci-bridge.h> |
37 | 37 | ||
38 | 38 | ||
39 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) | 39 | #ifdef CONFIG_PM |
40 | static int snd_pmac_register_sleep_notifier(pmac_t *chip); | 40 | static int snd_pmac_register_sleep_notifier(pmac_t *chip); |
41 | static int snd_pmac_unregister_sleep_notifier(pmac_t *chip); | 41 | static int snd_pmac_unregister_sleep_notifier(pmac_t *chip); |
42 | static int snd_pmac_suspend(snd_card_t *card, pm_message_t state); | 42 | static int snd_pmac_suspend(snd_card_t *card, pm_message_t state); |
@@ -153,7 +153,7 @@ static pmac_stream_t *snd_pmac_get_stream(pmac_t *chip, int stream) | |||
153 | /* | 153 | /* |
154 | * wait while run status is on | 154 | * wait while run status is on |
155 | */ | 155 | */ |
156 | inline static void | 156 | static inline void |
157 | snd_pmac_wait_ack(pmac_stream_t *rec) | 157 | snd_pmac_wait_ack(pmac_stream_t *rec) |
158 | { | 158 | { |
159 | int timeout = 50000; | 159 | int timeout = 50000; |
@@ -177,7 +177,7 @@ static void snd_pmac_pcm_set_format(pmac_t *chip) | |||
177 | /* | 177 | /* |
178 | * stop the DMA transfer | 178 | * stop the DMA transfer |
179 | */ | 179 | */ |
180 | inline static void snd_pmac_dma_stop(pmac_stream_t *rec) | 180 | static inline void snd_pmac_dma_stop(pmac_stream_t *rec) |
181 | { | 181 | { |
182 | out_le32(&rec->dma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); | 182 | out_le32(&rec->dma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); |
183 | snd_pmac_wait_ack(rec); | 183 | snd_pmac_wait_ack(rec); |
@@ -186,7 +186,7 @@ inline static void snd_pmac_dma_stop(pmac_stream_t *rec) | |||
186 | /* | 186 | /* |
187 | * set the command pointer address | 187 | * set the command pointer address |
188 | */ | 188 | */ |
189 | inline static void snd_pmac_dma_set_command(pmac_stream_t *rec, pmac_dbdma_t *cmd) | 189 | static inline void snd_pmac_dma_set_command(pmac_stream_t *rec, pmac_dbdma_t *cmd) |
190 | { | 190 | { |
191 | out_le32(&rec->dma->cmdptr, cmd->addr); | 191 | out_le32(&rec->dma->cmdptr, cmd->addr); |
192 | } | 192 | } |
@@ -194,7 +194,7 @@ inline static void snd_pmac_dma_set_command(pmac_stream_t *rec, pmac_dbdma_t *cm | |||
194 | /* | 194 | /* |
195 | * start the DMA | 195 | * start the DMA |
196 | */ | 196 | */ |
197 | inline static void snd_pmac_dma_run(pmac_stream_t *rec, int status) | 197 | static inline void snd_pmac_dma_run(pmac_stream_t *rec, int status) |
198 | { | 198 | { |
199 | out_le32(&rec->dma->control, status | (status << 16)); | 199 | out_le32(&rec->dma->control, status | (status << 16)); |
200 | } | 200 | } |
@@ -765,7 +765,8 @@ snd_pmac_ctrl_intr(int irq, void *devid, struct pt_regs *regs) | |||
765 | */ | 765 | */ |
766 | static void snd_pmac_sound_feature(pmac_t *chip, int enable) | 766 | static void snd_pmac_sound_feature(pmac_t *chip, int enable) |
767 | { | 767 | { |
768 | ppc_md.feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, chip->node, 0, enable); | 768 | if (ppc_md.feature_call) |
769 | ppc_md.feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, chip->node, 0, enable); | ||
769 | } | 770 | } |
770 | 771 | ||
771 | /* | 772 | /* |
@@ -782,7 +783,7 @@ static int snd_pmac_free(pmac_t *chip) | |||
782 | } | 783 | } |
783 | 784 | ||
784 | snd_pmac_sound_feature(chip, 0); | 785 | snd_pmac_sound_feature(chip, 0); |
785 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) | 786 | #ifdef CONFIG_PM |
786 | snd_pmac_unregister_sleep_notifier(chip); | 787 | snd_pmac_unregister_sleep_notifier(chip); |
787 | #endif | 788 | #endif |
788 | 789 | ||
@@ -1292,7 +1293,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) | |||
1292 | /* Reset dbdma channels */ | 1293 | /* Reset dbdma channels */ |
1293 | snd_pmac_dbdma_reset(chip); | 1294 | snd_pmac_dbdma_reset(chip); |
1294 | 1295 | ||
1295 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) | 1296 | #ifdef CONFIG_PM |
1296 | /* add sleep notifier */ | 1297 | /* add sleep notifier */ |
1297 | if (! snd_pmac_register_sleep_notifier(chip)) | 1298 | if (! snd_pmac_register_sleep_notifier(chip)) |
1298 | snd_card_set_pm_callback(chip->card, snd_pmac_suspend, snd_pmac_resume, chip); | 1299 | snd_card_set_pm_callback(chip->card, snd_pmac_suspend, snd_pmac_resume, chip); |
@@ -1316,7 +1317,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) | |||
1316 | * sleep notify for powerbook | 1317 | * sleep notify for powerbook |
1317 | */ | 1318 | */ |
1318 | 1319 | ||
1319 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) | 1320 | #ifdef CONFIG_PM |
1320 | 1321 | ||
1321 | /* | 1322 | /* |
1322 | * Save state when going to sleep, restore it afterwards. | 1323 | * Save state when going to sleep, restore it afterwards. |
@@ -1414,4 +1415,5 @@ static int snd_pmac_unregister_sleep_notifier(pmac_t *chip) | |||
1414 | return 0; | 1415 | return 0; |
1415 | } | 1416 | } |
1416 | 1417 | ||
1417 | #endif /* CONFIG_PM && CONFIG_PMAC_PBOOK */ | 1418 | #endif /* CONFIG_PM */ |
1419 | |||
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index 0a84c05f714b..ae3bb6c6edff 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h | |||
@@ -167,7 +167,7 @@ struct snd_pmac { | |||
167 | void (*set_format)(pmac_t *chip); | 167 | void (*set_format)(pmac_t *chip); |
168 | void (*update_automute)(pmac_t *chip, int do_notify); | 168 | void (*update_automute)(pmac_t *chip, int do_notify); |
169 | int (*detect_headphone)(pmac_t *chip); | 169 | int (*detect_headphone)(pmac_t *chip); |
170 | #ifdef CONFIG_PMAC_PBOOK | 170 | #ifdef CONFIG_PM |
171 | void (*suspend)(pmac_t *chip); | 171 | void (*suspend)(pmac_t *chip); |
172 | void (*resume)(pmac_t *chip); | 172 | void (*resume)(pmac_t *chip); |
173 | #endif | 173 | #endif |
@@ -212,9 +212,4 @@ int snd_pmac_boolean_mono_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *ui | |||
212 | 212 | ||
213 | int snd_pmac_add_automute(pmac_t *chip); | 213 | int snd_pmac_add_automute(pmac_t *chip); |
214 | 214 | ||
215 | #define big_mdelay(msec) do {\ | ||
216 | set_current_state(TASK_UNINTERRUPTIBLE);\ | ||
217 | schedule_timeout(((msec) * HZ + 999) / 1000);\ | ||
218 | } while (0) | ||
219 | |||
220 | #endif /* __PMAC_H */ | 215 | #endif /* __PMAC_H */ |
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 9332237cb6a4..b94437c024b1 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c | |||
@@ -945,7 +945,7 @@ static void device_change_handler(void *self) | |||
945 | check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify, | 945 | check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify, |
946 | chip->lineout_sw_ctl); | 946 | chip->lineout_sw_ctl); |
947 | if (mix->anded_reset) | 947 | if (mix->anded_reset) |
948 | big_mdelay(10); | 948 | msleep(10); |
949 | check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, | 949 | check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, |
950 | chip->speaker_sw_ctl); | 950 | chip->speaker_sw_ctl); |
951 | mix->drc_enable = 0; | 951 | mix->drc_enable = 0; |
@@ -954,7 +954,7 @@ static void device_change_handler(void *self) | |||
954 | check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, | 954 | check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, |
955 | chip->speaker_sw_ctl); | 955 | chip->speaker_sw_ctl); |
956 | if (mix->anded_reset) | 956 | if (mix->anded_reset) |
957 | big_mdelay(10); | 957 | msleep(10); |
958 | check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, | 958 | check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, |
959 | chip->master_sw_ctl); | 959 | chip->master_sw_ctl); |
960 | if (mix->line_mute.addr != 0) | 960 | if (mix->line_mute.addr != 0) |
@@ -1109,26 +1109,26 @@ static void tumbler_reset_audio(pmac_t *chip) | |||
1109 | DBG("(I) codec anded reset !\n"); | 1109 | DBG("(I) codec anded reset !\n"); |
1110 | write_audio_gpio(&mix->hp_mute, 0); | 1110 | write_audio_gpio(&mix->hp_mute, 0); |
1111 | write_audio_gpio(&mix->amp_mute, 0); | 1111 | write_audio_gpio(&mix->amp_mute, 0); |
1112 | big_mdelay(200); | 1112 | msleep(200); |
1113 | write_audio_gpio(&mix->hp_mute, 1); | 1113 | write_audio_gpio(&mix->hp_mute, 1); |
1114 | write_audio_gpio(&mix->amp_mute, 1); | 1114 | write_audio_gpio(&mix->amp_mute, 1); |
1115 | big_mdelay(100); | 1115 | msleep(100); |
1116 | write_audio_gpio(&mix->hp_mute, 0); | 1116 | write_audio_gpio(&mix->hp_mute, 0); |
1117 | write_audio_gpio(&mix->amp_mute, 0); | 1117 | write_audio_gpio(&mix->amp_mute, 0); |
1118 | big_mdelay(100); | 1118 | msleep(100); |
1119 | } else { | 1119 | } else { |
1120 | DBG("(I) codec normal reset !\n"); | 1120 | DBG("(I) codec normal reset !\n"); |
1121 | 1121 | ||
1122 | write_audio_gpio(&mix->audio_reset, 0); | 1122 | write_audio_gpio(&mix->audio_reset, 0); |
1123 | big_mdelay(200); | 1123 | msleep(200); |
1124 | write_audio_gpio(&mix->audio_reset, 1); | 1124 | write_audio_gpio(&mix->audio_reset, 1); |
1125 | big_mdelay(100); | 1125 | msleep(100); |
1126 | write_audio_gpio(&mix->audio_reset, 0); | 1126 | write_audio_gpio(&mix->audio_reset, 0); |
1127 | big_mdelay(100); | 1127 | msleep(100); |
1128 | } | 1128 | } |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | #ifdef CONFIG_PMAC_PBOOK | 1131 | #ifdef CONFIG_PM |
1132 | /* suspend mixer */ | 1132 | /* suspend mixer */ |
1133 | static void tumbler_suspend(pmac_t *chip) | 1133 | static void tumbler_suspend(pmac_t *chip) |
1134 | { | 1134 | { |
@@ -1370,7 +1370,7 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) | |||
1370 | if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) | 1370 | if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) |
1371 | return err; | 1371 | return err; |
1372 | 1372 | ||
1373 | #ifdef CONFIG_PMAC_PBOOK | 1373 | #ifdef CONFIG_PM |
1374 | chip->suspend = tumbler_suspend; | 1374 | chip->suspend = tumbler_suspend; |
1375 | chip->resume = tumbler_resume; | 1375 | chip->resume = tumbler_resume; |
1376 | #endif | 1376 | #endif |
diff --git a/sound/sound_core.c b/sound/sound_core.c index 30f75c9288cb..21a69e096225 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c | |||
@@ -65,7 +65,7 @@ extern int msnd_classic_init(void); | |||
65 | extern int msnd_pinnacle_init(void); | 65 | extern int msnd_pinnacle_init(void); |
66 | #endif | 66 | #endif |
67 | 67 | ||
68 | struct class_simple *sound_class; | 68 | struct class *sound_class; |
69 | EXPORT_SYMBOL(sound_class); | 69 | EXPORT_SYMBOL(sound_class); |
70 | 70 | ||
71 | /* | 71 | /* |
@@ -174,7 +174,7 @@ static int sound_insert_unit(struct sound_unit **list, struct file_operations *f | |||
174 | 174 | ||
175 | devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor), | 175 | devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor), |
176 | S_IFCHR | mode, s->name); | 176 | S_IFCHR | mode, s->name); |
177 | class_simple_device_add(sound_class, MKDEV(SOUND_MAJOR, s->unit_minor), | 177 | class_device_create(sound_class, MKDEV(SOUND_MAJOR, s->unit_minor), |
178 | NULL, s->name+6); | 178 | NULL, s->name+6); |
179 | return r; | 179 | return r; |
180 | 180 | ||
@@ -198,7 +198,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit) | |||
198 | spin_unlock(&sound_loader_lock); | 198 | spin_unlock(&sound_loader_lock); |
199 | if (p) { | 199 | if (p) { |
200 | devfs_remove(p->name); | 200 | devfs_remove(p->name); |
201 | class_simple_device_remove(MKDEV(SOUND_MAJOR, p->unit_minor)); | 201 | class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor)); |
202 | kfree(p); | 202 | kfree(p); |
203 | } | 203 | } |
204 | } | 204 | } |
@@ -562,7 +562,7 @@ static void __exit cleanup_soundcore(void) | |||
562 | empty */ | 562 | empty */ |
563 | unregister_chrdev(SOUND_MAJOR, "sound"); | 563 | unregister_chrdev(SOUND_MAJOR, "sound"); |
564 | devfs_remove("sound"); | 564 | devfs_remove("sound"); |
565 | class_simple_destroy(sound_class); | 565 | class_destroy(sound_class); |
566 | } | 566 | } |
567 | 567 | ||
568 | static int __init init_soundcore(void) | 568 | static int __init init_soundcore(void) |
@@ -572,7 +572,7 @@ static int __init init_soundcore(void) | |||
572 | return -EBUSY; | 572 | return -EBUSY; |
573 | } | 573 | } |
574 | devfs_mk_dir ("sound"); | 574 | devfs_mk_dir ("sound"); |
575 | sound_class = class_simple_create(THIS_MODULE, "sound"); | 575 | sound_class = class_create(THIS_MODULE, "sound"); |
576 | if (IS_ERR(sound_class)) | 576 | if (IS_ERR(sound_class)) |
577 | return PTR_ERR(sound_class); | 577 | return PTR_ERR(sound_class); |
578 | 578 | ||
diff --git a/sound/sparc/Kconfig b/sound/sparc/Kconfig index 2358df1c45a9..25a8a558ef92 100644 --- a/sound/sparc/Kconfig +++ b/sound/sparc/Kconfig | |||
@@ -7,12 +7,30 @@ config SND_SUN_AMD7930 | |||
7 | tristate "Sun AMD7930" | 7 | tristate "Sun AMD7930" |
8 | depends on SBUS && SND | 8 | depends on SBUS && SND |
9 | select SND_PCM | 9 | select SND_PCM |
10 | help | ||
11 | Say Y here to include support for AMD7930 sound device on Sun. | ||
12 | |||
13 | To compile this driver as a module, choose M here: the module | ||
14 | will be called snd-sun-amd7930. | ||
10 | 15 | ||
11 | # dep_tristate 'Sun DBRI' CONFIG_SND_SUN_DBRI $CONFIG_SND | ||
12 | config SND_SUN_CS4231 | 16 | config SND_SUN_CS4231 |
13 | tristate "Sun CS4231" | 17 | tristate "Sun CS4231" |
14 | depends on SND | 18 | depends on SND |
15 | select SND_PCM | 19 | select SND_PCM |
20 | help | ||
21 | Say Y here to include support for CS4231 sound device on Sun. | ||
16 | 22 | ||
17 | endmenu | 23 | To compile this driver as a module, choose M here: the module |
24 | will be called snd-sun-cs4231. | ||
25 | |||
26 | config SND_SUN_DBRI | ||
27 | tristate "Sun DBRI" | ||
28 | depends on SND && SBUS | ||
29 | select SND_PCM | ||
30 | help | ||
31 | Say Y here to include support for DBRI sound device on Sun. | ||
32 | |||
33 | To compile this driver as a module, choose M here: the module | ||
34 | will be called snd-sun-dbri. | ||
18 | 35 | ||
36 | endmenu | ||
diff --git a/sound/sparc/Makefile b/sound/sparc/Makefile index 6809cc92d276..3cd89c67c2f2 100644 --- a/sound/sparc/Makefile +++ b/sound/sparc/Makefile | |||
@@ -4,9 +4,9 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | snd-sun-amd7930-objs := amd7930.o | 6 | snd-sun-amd7930-objs := amd7930.o |
7 | #snd-sun-dbri-objs := dbri.o | ||
8 | snd-sun-cs4231-objs := cs4231.o | 7 | snd-sun-cs4231-objs := cs4231.o |
8 | snd-sun-dbri-objs := dbri.o | ||
9 | 9 | ||
10 | obj-$(CONFIG_SND_SUN_AMD7930) += snd-sun-amd7930.o | 10 | obj-$(CONFIG_SND_SUN_AMD7930) += snd-sun-amd7930.o |
11 | #obj-$(CONFIG_SND_SUN_DBRI) += snd-sun-dbri.o | ||
12 | obj-$(CONFIG_SND_SUN_CS4231) += snd-sun-cs4231.o | 11 | obj-$(CONFIG_SND_SUN_CS4231) += snd-sun-cs4231.o |
12 | obj-$(CONFIG_SND_SUN_DBRI) += snd-sun-dbri.o | ||
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c new file mode 100644 index 000000000000..941c7b1e7ebb --- /dev/null +++ b/sound/sparc/dbri.c | |||
@@ -0,0 +1,2729 @@ | |||
1 | /* | ||
2 | * Driver for DBRI sound chip found on Sparcs. | ||
3 | * Copyright (C) 2004 Martin Habets (mhabets@users.sourceforge.net) | ||
4 | * | ||
5 | * Based entirely upon drivers/sbus/audio/dbri.c which is: | ||
6 | * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) | ||
7 | * Copyright (C) 1998, 1999 Brent Baccala (baccala@freesoft.org) | ||
8 | * | ||
9 | * This is the lowlevel driver for the DBRI & MMCODEC duo used for ISDN & AUDIO | ||
10 | * on Sun SPARCstation 10, 20, LX and Voyager models. | ||
11 | * | ||
12 | * - DBRI: AT&T T5900FX Dual Basic Rates ISDN Interface. It is a 32 channel | ||
13 | * data time multiplexer with ISDN support (aka T7259) | ||
14 | * Interfaces: SBus,ISDN NT & TE, CHI, 4 bits parallel. | ||
15 | * CHI: (spelled ki) Concentration Highway Interface (AT&T or Intel bus ?). | ||
16 | * Documentation: | ||
17 | * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Tranceiver" from | ||
18 | * Sparc Technology Business (courtesy of Sun Support) | ||
19 | * - Data sheet of the T7903, a newer but very similar ISA bus equivalent | ||
20 | * available from the Lucent (formarly AT&T microelectronics) home | ||
21 | * page. | ||
22 | * - http://www.freesoft.org/Linux/DBRI/ | ||
23 | * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec | ||
24 | * Interfaces: CHI, Audio In & Out, 2 bits parallel | ||
25 | * Documentation: from the Crystal Semiconductor home page. | ||
26 | * | ||
27 | * The DBRI is a 32 pipe machine, each pipe can transfer some bits between | ||
28 | * memory and a serial device (long pipes, nr 0-15) or between two serial | ||
29 | * devices (short pipes, nr 16-31), or simply send a fixed data to a serial | ||
30 | * device (short pipes). | ||
31 | * A timeslot defines the bit-offset and nr of bits read from a serial device. | ||
32 | * The timeslots are linked to 6 circular lists, one for each direction for | ||
33 | * each serial device (NT,TE,CHI). A timeslot is associated to 1 or 2 pipes | ||
34 | * (the second one is a monitor/tee pipe, valid only for serial input). | ||
35 | * | ||
36 | * The mmcodec is connected via the CHI bus and needs the data & some | ||
37 | * parameters (volume, balance, output selection) timemultiplexed in 8 byte | ||
38 | * chunks. It also has a control mode, which serves for audio format setting. | ||
39 | * | ||
40 | * Looking at the CS4215 data sheet it is easy to set up 2 or 4 codecs on | ||
41 | * the same CHI bus, so I thought perhaps it is possible to use the onboard | ||
42 | * & the speakerbox codec simultanously, giving 2 (not very independent :-) | ||
43 | * audio devices. But the SUN HW group decided against it, at least on my | ||
44 | * LX the speakerbox connector has at least 1 pin missing and 1 wrongly | ||
45 | * connected. | ||
46 | */ | ||
47 | |||
48 | #include <sound/driver.h> | ||
49 | #include <linux/interrupt.h> | ||
50 | #include <linux/delay.h> | ||
51 | |||
52 | #include <sound/core.h> | ||
53 | #include <sound/pcm.h> | ||
54 | #include <sound/pcm_params.h> | ||
55 | #include <sound/info.h> | ||
56 | #include <sound/control.h> | ||
57 | #include <sound/initval.h> | ||
58 | |||
59 | #include <asm/irq.h> | ||
60 | #include <asm/io.h> | ||
61 | #include <asm/sbus.h> | ||
62 | #include <asm/atomic.h> | ||
63 | |||
64 | MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets"); | ||
65 | MODULE_DESCRIPTION("Sun DBRI"); | ||
66 | MODULE_LICENSE("GPL"); | ||
67 | MODULE_SUPPORTED_DEVICE("{{Sun,DBRI}}"); | ||
68 | |||
69 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | ||
70 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | ||
71 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | ||
72 | |||
73 | module_param_array(index, int, NULL, 0444); | ||
74 | MODULE_PARM_DESC(index, "Index value for Sun DBRI soundcard."); | ||
75 | module_param_array(id, charp, NULL, 0444); | ||
76 | MODULE_PARM_DESC(id, "ID string for Sun DBRI soundcard."); | ||
77 | module_param_array(enable, bool, NULL, 0444); | ||
78 | MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard."); | ||
79 | |||
80 | #define DBRI_DEBUG | ||
81 | |||
82 | #define D_INT (1<<0) | ||
83 | #define D_GEN (1<<1) | ||
84 | #define D_CMD (1<<2) | ||
85 | #define D_MM (1<<3) | ||
86 | #define D_USR (1<<4) | ||
87 | #define D_DESC (1<<5) | ||
88 | |||
89 | static int dbri_debug = 0; | ||
90 | module_param(dbri_debug, int, 0444); | ||
91 | MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard."); | ||
92 | |||
93 | #ifdef DBRI_DEBUG | ||
94 | static char *cmds[] = { | ||
95 | "WAIT", "PAUSE", "JUMP", "IIQ", "REX", "SDP", "CDP", "DTS", | ||
96 | "SSP", "CHI", "NT", "TE", "CDEC", "TEST", "CDM", "RESRV" | ||
97 | }; | ||
98 | |||
99 | #define dprintk(a, x...) if(dbri_debug & a) printk(KERN_DEBUG x) | ||
100 | |||
101 | #define DBRI_CMD(cmd, intr, value) ((cmd << 28) | \ | ||
102 | (1 << 27) | \ | ||
103 | value) | ||
104 | #else | ||
105 | #define dprintk(a, x...) | ||
106 | |||
107 | #define DBRI_CMD(cmd, intr, value) ((cmd << 28) | \ | ||
108 | (intr << 27) | \ | ||
109 | value) | ||
110 | #endif /* DBRI_DEBUG */ | ||
111 | |||
112 | /*************************************************************************** | ||
113 | CS4215 specific definitions and structures | ||
114 | ****************************************************************************/ | ||
115 | |||
116 | struct cs4215 { | ||
117 | __u8 data[4]; /* Data mode: Time slots 5-8 */ | ||
118 | __u8 ctrl[4]; /* Ctrl mode: Time slots 1-4 */ | ||
119 | __u8 onboard; | ||
120 | __u8 offset; /* Bit offset from frame sync to time slot 1 */ | ||
121 | volatile __u32 status; | ||
122 | volatile __u32 version; | ||
123 | __u8 precision; /* In bits, either 8 or 16 */ | ||
124 | __u8 channels; /* 1 or 2 */ | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * Control mode first | ||
129 | */ | ||
130 | |||
131 | /* Time Slot 1, Status register */ | ||
132 | #define CS4215_CLB (1<<2) /* Control Latch Bit */ | ||
133 | #define CS4215_OLB (1<<3) /* 1: line: 2.0V, speaker 4V */ | ||
134 | /* 0: line: 2.8V, speaker 8V */ | ||
135 | #define CS4215_MLB (1<<4) /* 1: Microphone: 20dB gain disabled */ | ||
136 | #define CS4215_RSRVD_1 (1<<5) | ||
137 | |||
138 | /* Time Slot 2, Data Format Register */ | ||
139 | #define CS4215_DFR_LINEAR16 0 | ||
140 | #define CS4215_DFR_ULAW 1 | ||
141 | #define CS4215_DFR_ALAW 2 | ||
142 | #define CS4215_DFR_LINEAR8 3 | ||
143 | #define CS4215_DFR_STEREO (1<<2) | ||
144 | static struct { | ||
145 | unsigned short freq; | ||
146 | unsigned char xtal; | ||
147 | unsigned char csval; | ||
148 | } CS4215_FREQ[] = { | ||
149 | { 8000, (1 << 4), (0 << 3) }, | ||
150 | { 16000, (1 << 4), (1 << 3) }, | ||
151 | { 27429, (1 << 4), (2 << 3) }, /* Actually 24428.57 */ | ||
152 | { 32000, (1 << 4), (3 << 3) }, | ||
153 | /* { NA, (1 << 4), (4 << 3) }, */ | ||
154 | /* { NA, (1 << 4), (5 << 3) }, */ | ||
155 | { 48000, (1 << 4), (6 << 3) }, | ||
156 | { 9600, (1 << 4), (7 << 3) }, | ||
157 | { 5513, (2 << 4), (0 << 3) }, /* Actually 5512.5 */ | ||
158 | { 11025, (2 << 4), (1 << 3) }, | ||
159 | { 18900, (2 << 4), (2 << 3) }, | ||
160 | { 22050, (2 << 4), (3 << 3) }, | ||
161 | { 37800, (2 << 4), (4 << 3) }, | ||
162 | { 44100, (2 << 4), (5 << 3) }, | ||
163 | { 33075, (2 << 4), (6 << 3) }, | ||
164 | { 6615, (2 << 4), (7 << 3) }, | ||
165 | { 0, 0, 0} | ||
166 | }; | ||
167 | |||
168 | #define CS4215_HPF (1<<7) /* High Pass Filter, 1: Enabled */ | ||
169 | |||
170 | #define CS4215_12_MASK 0xfcbf /* Mask off reserved bits in slot 1 & 2 */ | ||
171 | |||
172 | /* Time Slot 3, Serial Port Control register */ | ||
173 | #define CS4215_XEN (1<<0) /* 0: Enable serial output */ | ||
174 | #define CS4215_XCLK (1<<1) /* 1: Master mode: Generate SCLK */ | ||
175 | #define CS4215_BSEL_64 (0<<2) /* Bitrate: 64 bits per frame */ | ||
176 | #define CS4215_BSEL_128 (1<<2) | ||
177 | #define CS4215_BSEL_256 (2<<2) | ||
178 | #define CS4215_MCK_MAST (0<<4) /* Master clock */ | ||
179 | #define CS4215_MCK_XTL1 (1<<4) /* 24.576 MHz clock source */ | ||
180 | #define CS4215_MCK_XTL2 (2<<4) /* 16.9344 MHz clock source */ | ||
181 | #define CS4215_MCK_CLK1 (3<<4) /* Clockin, 256 x Fs */ | ||
182 | #define CS4215_MCK_CLK2 (4<<4) /* Clockin, see DFR */ | ||
183 | |||
184 | /* Time Slot 4, Test Register */ | ||
185 | #define CS4215_DAD (1<<0) /* 0:Digital-Dig loop, 1:Dig-Analog-Dig loop */ | ||
186 | #define CS4215_ENL (1<<1) /* Enable Loopback Testing */ | ||
187 | |||
188 | /* Time Slot 5, Parallel Port Register */ | ||
189 | /* Read only here and the same as the in data mode */ | ||
190 | |||
191 | /* Time Slot 6, Reserved */ | ||
192 | |||
193 | /* Time Slot 7, Version Register */ | ||
194 | #define CS4215_VERSION_MASK 0xf /* Known versions 0/C, 1/D, 2/E */ | ||
195 | |||
196 | /* Time Slot 8, Reserved */ | ||
197 | |||
198 | /* | ||
199 | * Data mode | ||
200 | */ | ||
201 | /* Time Slot 1-2: Left Channel Data, 2-3: Right Channel Data */ | ||
202 | |||
203 | /* Time Slot 5, Output Setting */ | ||
204 | #define CS4215_LO(v) v /* Left Output Attenuation 0x3f: -94.5 dB */ | ||
205 | #define CS4215_LE (1<<6) /* Line Out Enable */ | ||
206 | #define CS4215_HE (1<<7) /* Headphone Enable */ | ||
207 | |||
208 | /* Time Slot 6, Output Setting */ | ||
209 | #define CS4215_RO(v) v /* Right Output Attenuation 0x3f: -94.5 dB */ | ||
210 | #define CS4215_SE (1<<6) /* Speaker Enable */ | ||
211 | #define CS4215_ADI (1<<7) /* A/D Data Invalid: Busy in calibration */ | ||
212 | |||
213 | /* Time Slot 7, Input Setting */ | ||
214 | #define CS4215_LG(v) v /* Left Gain Setting 0xf: 22.5 dB */ | ||
215 | #define CS4215_IS (1<<4) /* Input Select: 1=Microphone, 0=Line */ | ||
216 | #define CS4215_OVR (1<<5) /* 1: Overrange condition occurred */ | ||
217 | #define CS4215_PIO0 (1<<6) /* Parallel I/O 0 */ | ||
218 | #define CS4215_PIO1 (1<<7) | ||
219 | |||
220 | /* Time Slot 8, Input Setting */ | ||
221 | #define CS4215_RG(v) v /* Right Gain Setting 0xf: 22.5 dB */ | ||
222 | #define CS4215_MA(v) (v<<4) /* Monitor Path Attenuation 0xf: mute */ | ||
223 | |||
224 | /*************************************************************************** | ||
225 | DBRI specific definitions and structures | ||
226 | ****************************************************************************/ | ||
227 | |||
228 | /* DBRI main registers */ | ||
229 | #define REG0 0x00UL /* Status and Control */ | ||
230 | #define REG1 0x04UL /* Mode and Interrupt */ | ||
231 | #define REG2 0x08UL /* Parallel IO */ | ||
232 | #define REG3 0x0cUL /* Test */ | ||
233 | #define REG8 0x20UL /* Command Queue Pointer */ | ||
234 | #define REG9 0x24UL /* Interrupt Queue Pointer */ | ||
235 | |||
236 | #define DBRI_NO_CMDS 64 | ||
237 | #define DBRI_NO_INTS 1 /* Note: the value of this define was | ||
238 | * originally 2. The ringbuffer to store | ||
239 | * interrupts in dma is currently broken. | ||
240 | * This is a temporary fix until the ringbuffer | ||
241 | * is fixed. | ||
242 | */ | ||
243 | #define DBRI_INT_BLK 64 | ||
244 | #define DBRI_NO_DESCS 64 | ||
245 | #define DBRI_NO_PIPES 32 | ||
246 | |||
247 | #define DBRI_MM_ONB 1 | ||
248 | #define DBRI_MM_SB 2 | ||
249 | |||
250 | #define DBRI_REC 0 | ||
251 | #define DBRI_PLAY 1 | ||
252 | #define DBRI_NO_STREAMS 2 | ||
253 | |||
254 | /* One transmit/receive descriptor */ | ||
255 | struct dbri_mem { | ||
256 | volatile __u32 word1; | ||
257 | volatile __u32 ba; /* Transmit/Receive Buffer Address */ | ||
258 | volatile __u32 nda; /* Next Descriptor Address */ | ||
259 | volatile __u32 word4; | ||
260 | }; | ||
261 | |||
262 | /* This structure is in a DMA region where it can accessed by both | ||
263 | * the CPU and the DBRI | ||
264 | */ | ||
265 | struct dbri_dma { | ||
266 | volatile s32 cmd[DBRI_NO_CMDS]; /* Place for commands */ | ||
267 | volatile s32 intr[DBRI_NO_INTS * DBRI_INT_BLK]; /* Interrupt field */ | ||
268 | struct dbri_mem desc[DBRI_NO_DESCS]; /* Xmit/receive descriptors */ | ||
269 | }; | ||
270 | |||
271 | #define dbri_dma_off(member, elem) \ | ||
272 | ((u32)(unsigned long) \ | ||
273 | (&(((struct dbri_dma *)0)->member[elem]))) | ||
274 | |||
275 | enum in_or_out { PIPEinput, PIPEoutput }; | ||
276 | |||
277 | struct dbri_pipe { | ||
278 | u32 sdp; /* SDP command word */ | ||
279 | enum in_or_out direction; | ||
280 | int nextpipe; /* Next pipe in linked list */ | ||
281 | int prevpipe; | ||
282 | int cycle; /* Offset of timeslot (bits) */ | ||
283 | int length; /* Length of timeslot (bits) */ | ||
284 | int first_desc; /* Index of first descriptor */ | ||
285 | int desc; /* Index of active descriptor */ | ||
286 | volatile __u32 *recv_fixed_ptr; /* Ptr to receive fixed data */ | ||
287 | }; | ||
288 | |||
289 | struct dbri_desc { | ||
290 | int inuse; /* Boolean flag */ | ||
291 | int next; /* Index of next desc, or -1 */ | ||
292 | unsigned int len; | ||
293 | }; | ||
294 | |||
295 | /* Per stream (playback or record) information */ | ||
296 | typedef struct dbri_streaminfo { | ||
297 | snd_pcm_substream_t *substream; | ||
298 | u32 dvma_buffer; /* Device view of Alsa DMA buffer */ | ||
299 | int left; /* # of bytes left in DMA buffer */ | ||
300 | int size; /* Size of DMA buffer */ | ||
301 | size_t offset; /* offset in user buffer */ | ||
302 | int pipe; /* Data pipe used */ | ||
303 | int left_gain; /* mixer elements */ | ||
304 | int right_gain; | ||
305 | int balance; | ||
306 | } dbri_streaminfo_t; | ||
307 | |||
308 | /* This structure holds the information for both chips (DBRI & CS4215) */ | ||
309 | typedef struct snd_dbri { | ||
310 | snd_card_t *card; /* ALSA card */ | ||
311 | snd_pcm_t *pcm; | ||
312 | |||
313 | int regs_size, irq; /* Needed for unload */ | ||
314 | struct sbus_dev *sdev; /* SBUS device info */ | ||
315 | spinlock_t lock; | ||
316 | |||
317 | volatile struct dbri_dma *dma; /* Pointer to our DMA block */ | ||
318 | u32 dma_dvma; /* DBRI visible DMA address */ | ||
319 | |||
320 | void __iomem *regs; /* dbri HW regs */ | ||
321 | int dbri_version; /* 'e' and up is OK */ | ||
322 | int dbri_irqp; /* intr queue pointer */ | ||
323 | int wait_seen; | ||
324 | |||
325 | struct dbri_pipe pipes[DBRI_NO_PIPES]; /* DBRI's 32 data pipes */ | ||
326 | struct dbri_desc descs[DBRI_NO_DESCS]; | ||
327 | |||
328 | int chi_in_pipe; | ||
329 | int chi_out_pipe; | ||
330 | int chi_bpf; | ||
331 | |||
332 | struct cs4215 mm; /* mmcodec special info */ | ||
333 | /* per stream (playback/record) info */ | ||
334 | struct dbri_streaminfo stream_info[DBRI_NO_STREAMS]; | ||
335 | |||
336 | struct snd_dbri *next; | ||
337 | } snd_dbri_t; | ||
338 | |||
339 | /* Needed for the ALSA macros to work */ | ||
340 | #define chip_t snd_dbri_t | ||
341 | |||
342 | #define DBRI_MAX_VOLUME 63 /* Output volume */ | ||
343 | #define DBRI_MAX_GAIN 15 /* Input gain */ | ||
344 | #define DBRI_RIGHT_BALANCE 255 | ||
345 | #define DBRI_MID_BALANCE (DBRI_RIGHT_BALANCE >> 1) | ||
346 | |||
347 | /* DBRI Reg0 - Status Control Register - defines. (Page 17) */ | ||
348 | #define D_P (1<<15) /* Program command & queue pointer valid */ | ||
349 | #define D_G (1<<14) /* Allow 4-Word SBus Burst */ | ||
350 | #define D_S (1<<13) /* Allow 16-Word SBus Burst */ | ||
351 | #define D_E (1<<12) /* Allow 8-Word SBus Burst */ | ||
352 | #define D_X (1<<7) /* Sanity Timer Disable */ | ||
353 | #define D_T (1<<6) /* Permit activation of the TE interface */ | ||
354 | #define D_N (1<<5) /* Permit activation of the NT interface */ | ||
355 | #define D_C (1<<4) /* Permit activation of the CHI interface */ | ||
356 | #define D_F (1<<3) /* Force Sanity Timer Time-Out */ | ||
357 | #define D_D (1<<2) /* Disable Master Mode */ | ||
358 | #define D_H (1<<1) /* Halt for Analysis */ | ||
359 | #define D_R (1<<0) /* Soft Reset */ | ||
360 | |||
361 | /* DBRI Reg1 - Mode and Interrupt Register - defines. (Page 18) */ | ||
362 | #define D_LITTLE_END (1<<8) /* Byte Order */ | ||
363 | #define D_BIG_END (0<<8) /* Byte Order */ | ||
364 | #define D_MRR (1<<4) /* Multiple Error Ack on SBus (readonly) */ | ||
365 | #define D_MLE (1<<3) /* Multiple Late Error on SBus (readonly) */ | ||
366 | #define D_LBG (1<<2) /* Lost Bus Grant on SBus (readonly) */ | ||
367 | #define D_MBE (1<<1) /* Burst Error on SBus (readonly) */ | ||
368 | #define D_IR (1<<0) /* Interrupt Indicator (readonly) */ | ||
369 | |||
370 | /* DBRI Reg2 - Parallel IO Register - defines. (Page 18) */ | ||
371 | #define D_ENPIO3 (1<<7) /* Enable Pin 3 */ | ||
372 | #define D_ENPIO2 (1<<6) /* Enable Pin 2 */ | ||
373 | #define D_ENPIO1 (1<<5) /* Enable Pin 1 */ | ||
374 | #define D_ENPIO0 (1<<4) /* Enable Pin 0 */ | ||
375 | #define D_ENPIO (0xf0) /* Enable all the pins */ | ||
376 | #define D_PIO3 (1<<3) /* Pin 3: 1: Data mode, 0: Ctrl mode */ | ||
377 | #define D_PIO2 (1<<2) /* Pin 2: 1: Onboard PDN */ | ||
378 | #define D_PIO1 (1<<1) /* Pin 1: 0: Reset */ | ||
379 | #define D_PIO0 (1<<0) /* Pin 0: 1: Speakerbox PDN */ | ||
380 | |||
381 | /* DBRI Commands (Page 20) */ | ||
382 | #define D_WAIT 0x0 /* Stop execution */ | ||
383 | #define D_PAUSE 0x1 /* Flush long pipes */ | ||
384 | #define D_JUMP 0x2 /* New command queue */ | ||
385 | #define D_IIQ 0x3 /* Initialize Interrupt Queue */ | ||
386 | #define D_REX 0x4 /* Report command execution via interrupt */ | ||
387 | #define D_SDP 0x5 /* Setup Data Pipe */ | ||
388 | #define D_CDP 0x6 /* Continue Data Pipe (reread NULL Pointer) */ | ||
389 | #define D_DTS 0x7 /* Define Time Slot */ | ||
390 | #define D_SSP 0x8 /* Set short Data Pipe */ | ||
391 | #define D_CHI 0x9 /* Set CHI Global Mode */ | ||
392 | #define D_NT 0xa /* NT Command */ | ||
393 | #define D_TE 0xb /* TE Command */ | ||
394 | #define D_CDEC 0xc /* Codec setup */ | ||
395 | #define D_TEST 0xd /* No comment */ | ||
396 | #define D_CDM 0xe /* CHI Data mode command */ | ||
397 | |||
398 | /* Special bits for some commands */ | ||
399 | #define D_PIPE(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */ | ||
400 | |||
401 | /* Setup Data Pipe */ | ||
402 | /* IRM */ | ||
403 | #define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value rcvd */ | ||
404 | #define D_SDP_CHANGE (2<<18) /* Report any changes */ | ||
405 | #define D_SDP_EVERY (3<<18) /* Report any changes */ | ||
406 | #define D_SDP_EOL (1<<17) /* EOL interrupt enable */ | ||
407 | #define D_SDP_IDLE (1<<16) /* HDLC idle interrupt enable */ | ||
408 | |||
409 | /* Pipe data MODE */ | ||
410 | #define D_SDP_MEM (0<<13) /* To/from memory */ | ||
411 | #define D_SDP_HDLC (2<<13) | ||
412 | #define D_SDP_HDLC_D (3<<13) /* D Channel (prio control) */ | ||
413 | #define D_SDP_SER (4<<13) /* Serial to serial */ | ||
414 | #define D_SDP_FIXED (6<<13) /* Short only */ | ||
415 | #define D_SDP_MODE(v) ((v)&(7<<13)) | ||
416 | |||
417 | #define D_SDP_TO_SER (1<<12) /* Direction */ | ||
418 | #define D_SDP_FROM_SER (0<<12) /* Direction */ | ||
419 | #define D_SDP_MSB (1<<11) /* Bit order within Byte */ | ||
420 | #define D_SDP_LSB (0<<11) /* Bit order within Byte */ | ||
421 | #define D_SDP_P (1<<10) /* Pointer Valid */ | ||
422 | #define D_SDP_A (1<<8) /* Abort */ | ||
423 | #define D_SDP_C (1<<7) /* Clear */ | ||
424 | |||
425 | /* Define Time Slot */ | ||
426 | #define D_DTS_VI (1<<17) /* Valid Input Time-Slot Descriptor */ | ||
427 | #define D_DTS_VO (1<<16) /* Valid Output Time-Slot Descriptor */ | ||
428 | #define D_DTS_INS (1<<15) /* Insert Time Slot */ | ||
429 | #define D_DTS_DEL (0<<15) /* Delete Time Slot */ | ||
430 | #define D_DTS_PRVIN(v) ((v)<<10) /* Previous In Pipe */ | ||
431 | #define D_DTS_PRVOUT(v) ((v)<<5) /* Previous Out Pipe */ | ||
432 | |||
433 | /* Time Slot defines */ | ||
434 | #define D_TS_LEN(v) ((v)<<24) /* Number of bits in this time slot */ | ||
435 | #define D_TS_CYCLE(v) ((v)<<14) /* Bit Count at start of TS */ | ||
436 | #define D_TS_DI (1<<13) /* Data Invert */ | ||
437 | #define D_TS_1CHANNEL (0<<10) /* Single Channel / Normal mode */ | ||
438 | #define D_TS_MONITOR (2<<10) /* Monitor pipe */ | ||
439 | #define D_TS_NONCONTIG (3<<10) /* Non contiguous mode */ | ||
440 | #define D_TS_ANCHOR (7<<10) /* Starting short pipes */ | ||
441 | #define D_TS_MON(v) ((v)<<5) /* Monitor Pipe */ | ||
442 | #define D_TS_NEXT(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */ | ||
443 | |||
444 | /* Concentration Highway Interface Modes */ | ||
445 | #define D_CHI_CHICM(v) ((v)<<16) /* Clock mode */ | ||
446 | #define D_CHI_IR (1<<15) /* Immediate Interrupt Report */ | ||
447 | #define D_CHI_EN (1<<14) /* CHIL Interrupt enabled */ | ||
448 | #define D_CHI_OD (1<<13) /* Open Drain Enable */ | ||
449 | #define D_CHI_FE (1<<12) /* Sample CHIFS on Rising Frame Edge */ | ||
450 | #define D_CHI_FD (1<<11) /* Frame Drive */ | ||
451 | #define D_CHI_BPF(v) ((v)<<0) /* Bits per Frame */ | ||
452 | |||
453 | /* NT: These are here for completeness */ | ||
454 | #define D_NT_FBIT (1<<17) /* Frame Bit */ | ||
455 | #define D_NT_NBF (1<<16) /* Number of bad frames to loose framing */ | ||
456 | #define D_NT_IRM_IMM (1<<15) /* Interrupt Report & Mask: Immediate */ | ||
457 | #define D_NT_IRM_EN (1<<14) /* Interrupt Report & Mask: Enable */ | ||
458 | #define D_NT_ISNT (1<<13) /* Configfure interface as NT */ | ||
459 | #define D_NT_FT (1<<12) /* Fixed Timing */ | ||
460 | #define D_NT_EZ (1<<11) /* Echo Channel is Zeros */ | ||
461 | #define D_NT_IFA (1<<10) /* Inhibit Final Activation */ | ||
462 | #define D_NT_ACT (1<<9) /* Activate Interface */ | ||
463 | #define D_NT_MFE (1<<8) /* Multiframe Enable */ | ||
464 | #define D_NT_RLB(v) ((v)<<5) /* Remote Loopback */ | ||
465 | #define D_NT_LLB(v) ((v)<<2) /* Local Loopback */ | ||
466 | #define D_NT_FACT (1<<1) /* Force Activation */ | ||
467 | #define D_NT_ABV (1<<0) /* Activate Bipolar Violation */ | ||
468 | |||
469 | /* Codec Setup */ | ||
470 | #define D_CDEC_CK(v) ((v)<<24) /* Clock Select */ | ||
471 | #define D_CDEC_FED(v) ((v)<<12) /* FSCOD Falling Edge Delay */ | ||
472 | #define D_CDEC_RED(v) ((v)<<0) /* FSCOD Rising Edge Delay */ | ||
473 | |||
474 | /* Test */ | ||
475 | #define D_TEST_RAM(v) ((v)<<16) /* RAM Pointer */ | ||
476 | #define D_TEST_SIZE(v) ((v)<<11) /* */ | ||
477 | #define D_TEST_ROMONOFF 0x5 /* Toggle ROM opcode monitor on/off */ | ||
478 | #define D_TEST_PROC 0x6 /* MicroProcessor test */ | ||
479 | #define D_TEST_SER 0x7 /* Serial-Controller test */ | ||
480 | #define D_TEST_RAMREAD 0x8 /* Copy from Ram to system memory */ | ||
481 | #define D_TEST_RAMWRITE 0x9 /* Copy into Ram from system memory */ | ||
482 | #define D_TEST_RAMBIST 0xa /* RAM Built-In Self Test */ | ||
483 | #define D_TEST_MCBIST 0xb /* Microcontroller Built-In Self Test */ | ||
484 | #define D_TEST_DUMP 0xe /* ROM Dump */ | ||
485 | |||
486 | /* CHI Data Mode */ | ||
487 | #define D_CDM_THI (1<<8) /* Transmit Data on CHIDR Pin */ | ||
488 | #define D_CDM_RHI (1<<7) /* Receive Data on CHIDX Pin */ | ||
489 | #define D_CDM_RCE (1<<6) /* Receive on Rising Edge of CHICK */ | ||
490 | #define D_CDM_XCE (1<<2) /* Transmit Data on Rising Edge of CHICK */ | ||
491 | #define D_CDM_XEN (1<<1) /* Transmit Highway Enable */ | ||
492 | #define D_CDM_REN (1<<0) /* Receive Highway Enable */ | ||
493 | |||
494 | /* The Interrupts */ | ||
495 | #define D_INTR_BRDY 1 /* Buffer Ready for processing */ | ||
496 | #define D_INTR_MINT 2 /* Marked Interrupt in RD/TD */ | ||
497 | #define D_INTR_IBEG 3 /* Flag to idle transition detected (HDLC) */ | ||
498 | #define D_INTR_IEND 4 /* Idle to flag transition detected (HDLC) */ | ||
499 | #define D_INTR_EOL 5 /* End of List */ | ||
500 | #define D_INTR_CMDI 6 /* Command has bean read */ | ||
501 | #define D_INTR_XCMP 8 /* Transmission of frame complete */ | ||
502 | #define D_INTR_SBRI 9 /* BRI status change info */ | ||
503 | #define D_INTR_FXDT 10 /* Fixed data change */ | ||
504 | #define D_INTR_CHIL 11 /* CHI lost frame sync (channel 36 only) */ | ||
505 | #define D_INTR_COLL 11 /* Unrecoverable D-Channel collision */ | ||
506 | #define D_INTR_DBYT 12 /* Dropped by frame slip */ | ||
507 | #define D_INTR_RBYT 13 /* Repeated by frame slip */ | ||
508 | #define D_INTR_LINT 14 /* Lost Interrupt */ | ||
509 | #define D_INTR_UNDR 15 /* DMA underrun */ | ||
510 | |||
511 | #define D_INTR_TE 32 | ||
512 | #define D_INTR_NT 34 | ||
513 | #define D_INTR_CHI 36 | ||
514 | #define D_INTR_CMD 38 | ||
515 | |||
516 | #define D_INTR_GETCHAN(v) (((v)>>24) & 0x3f) | ||
517 | #define D_INTR_GETCODE(v) (((v)>>20) & 0xf) | ||
518 | #define D_INTR_GETCMD(v) (((v)>>16) & 0xf) | ||
519 | #define D_INTR_GETVAL(v) ((v) & 0xffff) | ||
520 | #define D_INTR_GETRVAL(v) ((v) & 0xfffff) | ||
521 | |||
522 | #define D_P_0 0 /* TE receive anchor */ | ||
523 | #define D_P_1 1 /* TE transmit anchor */ | ||
524 | #define D_P_2 2 /* NT transmit anchor */ | ||
525 | #define D_P_3 3 /* NT receive anchor */ | ||
526 | #define D_P_4 4 /* CHI send data */ | ||
527 | #define D_P_5 5 /* CHI receive data */ | ||
528 | #define D_P_6 6 /* */ | ||
529 | #define D_P_7 7 /* */ | ||
530 | #define D_P_8 8 /* */ | ||
531 | #define D_P_9 9 /* */ | ||
532 | #define D_P_10 10 /* */ | ||
533 | #define D_P_11 11 /* */ | ||
534 | #define D_P_12 12 /* */ | ||
535 | #define D_P_13 13 /* */ | ||
536 | #define D_P_14 14 /* */ | ||
537 | #define D_P_15 15 /* */ | ||
538 | #define D_P_16 16 /* CHI anchor pipe */ | ||
539 | #define D_P_17 17 /* CHI send */ | ||
540 | #define D_P_18 18 /* CHI receive */ | ||
541 | #define D_P_19 19 /* CHI receive */ | ||
542 | #define D_P_20 20 /* CHI receive */ | ||
543 | #define D_P_21 21 /* */ | ||
544 | #define D_P_22 22 /* */ | ||
545 | #define D_P_23 23 /* */ | ||
546 | #define D_P_24 24 /* */ | ||
547 | #define D_P_25 25 /* */ | ||
548 | #define D_P_26 26 /* */ | ||
549 | #define D_P_27 27 /* */ | ||
550 | #define D_P_28 28 /* */ | ||
551 | #define D_P_29 29 /* */ | ||
552 | #define D_P_30 30 /* */ | ||
553 | #define D_P_31 31 /* */ | ||
554 | |||
555 | /* Transmit descriptor defines */ | ||
556 | #define DBRI_TD_F (1<<31) /* End of Frame */ | ||
557 | #define DBRI_TD_D (1<<30) /* Do not append CRC */ | ||
558 | #define DBRI_TD_CNT(v) ((v)<<16) /* Number of valid bytes in the buffer */ | ||
559 | #define DBRI_TD_B (1<<15) /* Final interrupt */ | ||
560 | #define DBRI_TD_M (1<<14) /* Marker interrupt */ | ||
561 | #define DBRI_TD_I (1<<13) /* Transmit Idle Characters */ | ||
562 | #define DBRI_TD_FCNT(v) (v) /* Flag Count */ | ||
563 | #define DBRI_TD_UNR (1<<3) /* Underrun: transmitter is out of data */ | ||
564 | #define DBRI_TD_ABT (1<<2) /* Abort: frame aborted */ | ||
565 | #define DBRI_TD_TBC (1<<0) /* Transmit buffer Complete */ | ||
566 | #define DBRI_TD_STATUS(v) ((v)&0xff) /* Transmit status */ | ||
567 | /* Maximum buffer size per TD: almost 8Kb */ | ||
568 | #define DBRI_TD_MAXCNT ((1 << 13) - 1) | ||
569 | |||
570 | /* Receive descriptor defines */ | ||
571 | #define DBRI_RD_F (1<<31) /* End of Frame */ | ||
572 | #define DBRI_RD_C (1<<30) /* Completed buffer */ | ||
573 | #define DBRI_RD_B (1<<15) /* Final interrupt */ | ||
574 | #define DBRI_RD_M (1<<14) /* Marker interrupt */ | ||
575 | #define DBRI_RD_BCNT(v) (v) /* Buffer size */ | ||
576 | #define DBRI_RD_CRC (1<<7) /* 0: CRC is correct */ | ||
577 | #define DBRI_RD_BBC (1<<6) /* 1: Bad Byte received */ | ||
578 | #define DBRI_RD_ABT (1<<5) /* Abort: frame aborted */ | ||
579 | #define DBRI_RD_OVRN (1<<3) /* Overrun: data lost */ | ||
580 | #define DBRI_RD_STATUS(v) ((v)&0xff) /* Receive status */ | ||
581 | #define DBRI_RD_CNT(v) (((v)>>16)&0x1fff) /* Valid bytes in the buffer */ | ||
582 | |||
583 | /* stream_info[] access */ | ||
584 | /* Translate the ALSA direction into the array index */ | ||
585 | #define DBRI_STREAMNO(substream) \ | ||
586 | (substream->stream == \ | ||
587 | SNDRV_PCM_STREAM_PLAYBACK? DBRI_PLAY: DBRI_REC) | ||
588 | |||
589 | /* Return a pointer to dbri_streaminfo */ | ||
590 | #define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)] | ||
591 | |||
592 | static snd_dbri_t *dbri_list = NULL; /* All DBRI devices */ | ||
593 | |||
594 | /* | ||
595 | * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. | ||
596 | * So we have to reverse the bits. Note: not all bit lengths are supported | ||
597 | */ | ||
598 | static __u32 reverse_bytes(__u32 b, int len) | ||
599 | { | ||
600 | switch (len) { | ||
601 | case 32: | ||
602 | b = ((b & 0xffff0000) >> 16) | ((b & 0x0000ffff) << 16); | ||
603 | case 16: | ||
604 | b = ((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8); | ||
605 | case 8: | ||
606 | b = ((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4); | ||
607 | case 4: | ||
608 | b = ((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2); | ||
609 | case 2: | ||
610 | b = ((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1); | ||
611 | case 1: | ||
612 | case 0: | ||
613 | break; | ||
614 | default: | ||
615 | printk(KERN_ERR "DBRI reverse_bytes: unsupported length\n"); | ||
616 | }; | ||
617 | |||
618 | return b; | ||
619 | } | ||
620 | |||
621 | /* | ||
622 | **************************************************************************** | ||
623 | ************** DBRI initialization and command synchronization ************* | ||
624 | **************************************************************************** | ||
625 | |||
626 | Commands are sent to the DBRI by building a list of them in memory, | ||
627 | then writing the address of the first list item to DBRI register 8. | ||
628 | The list is terminated with a WAIT command, which can generate a | ||
629 | CPU interrupt if required. | ||
630 | |||
631 | Since the DBRI can run in parallel with the CPU, several means of | ||
632 | synchronization present themselves. The original scheme (Rudolf's) | ||
633 | was to set a flag when we "cmdlock"ed the DBRI, clear the flag when | ||
634 | an interrupt signaled completion, and wait on a wait_queue if a routine | ||
635 | attempted to cmdlock while the flag was set. The problems arose when | ||
636 | we tried to cmdlock from inside an interrupt handler, which might | ||
637 | cause scheduling in an interrupt (if we waited), etc, etc | ||
638 | |||
639 | A more sophisticated scheme might involve a circular command buffer | ||
640 | or an array of command buffers. A routine could fill one with | ||
641 | commands and link it onto a list. When a interrupt signaled | ||
642 | completion of the current command buffer, look on the list for | ||
643 | the next one. | ||
644 | |||
645 | I've decided to implement something much simpler - after each command, | ||
646 | the CPU waits for the DBRI to finish the command by polling the P bit | ||
647 | in DBRI register 0. I've tried to implement this in such a way | ||
648 | that might make implementing a more sophisticated scheme easier. | ||
649 | |||
650 | Every time a routine wants to write commands to the DBRI, it must | ||
651 | first call dbri_cmdlock() and get an initial pointer into dbri->dma->cmd | ||
652 | in return. After the commands have been writen, dbri_cmdsend() is | ||
653 | called with the final pointer value. | ||
654 | |||
655 | */ | ||
656 | |||
657 | enum dbri_lock_t { NoGetLock, GetLock }; | ||
658 | |||
659 | static volatile s32 *dbri_cmdlock(snd_dbri_t * dbri, enum dbri_lock_t get) | ||
660 | { | ||
661 | #ifndef SMP | ||
662 | if ((get == GetLock) && spin_is_locked(&dbri->lock)) { | ||
663 | printk(KERN_ERR "DBRI: cmdlock called while in spinlock."); | ||
664 | } | ||
665 | #endif | ||
666 | |||
667 | /*if (get == GetLock) spin_lock(&dbri->lock); */ | ||
668 | return &dbri->dma->cmd[0]; | ||
669 | } | ||
670 | |||
671 | static void dbri_process_interrupt_buffer(snd_dbri_t *); | ||
672 | |||
673 | static void dbri_cmdsend(snd_dbri_t * dbri, volatile s32 * cmd) | ||
674 | { | ||
675 | int MAXLOOPS = 1000000; | ||
676 | int maxloops = MAXLOOPS; | ||
677 | volatile s32 *ptr; | ||
678 | |||
679 | for (ptr = &dbri->dma->cmd[0]; ptr < cmd; ptr++) { | ||
680 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); | ||
681 | } | ||
682 | |||
683 | if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS - 1) { | ||
684 | printk("DBRI: Command buffer overflow! (bug in driver)\n"); | ||
685 | /* Ignore the last part. */ | ||
686 | cmd = &dbri->dma->cmd[DBRI_NO_CMDS - 3]; | ||
687 | } | ||
688 | |||
689 | *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); | ||
690 | *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); | ||
691 | dbri->wait_seen = 0; | ||
692 | sbus_writel(dbri->dma_dvma, dbri->regs + REG8); | ||
693 | while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P)) | ||
694 | barrier(); | ||
695 | if (maxloops == 0) { | ||
696 | printk(KERN_ERR "DBRI: Chip never completed command buffer\n"); | ||
697 | dprintk(D_CMD, "DBRI: Chip never completed command buffer\n"); | ||
698 | } else { | ||
699 | while ((--maxloops) > 0 && (!dbri->wait_seen)) | ||
700 | dbri_process_interrupt_buffer(dbri); | ||
701 | if (maxloops == 0) { | ||
702 | printk(KERN_ERR "DBRI: Chip never acked WAIT\n"); | ||
703 | dprintk(D_CMD, "DBRI: Chip never acked WAIT\n"); | ||
704 | } else { | ||
705 | dprintk(D_CMD, "Chip completed command " | ||
706 | "buffer (%d)\n", MAXLOOPS - maxloops); | ||
707 | } | ||
708 | } | ||
709 | |||
710 | /*spin_unlock(&dbri->lock); */ | ||
711 | } | ||
712 | |||
713 | /* Lock must be held when calling this */ | ||
714 | static void dbri_reset(snd_dbri_t * dbri) | ||
715 | { | ||
716 | int i; | ||
717 | |||
718 | dprintk(D_GEN, "reset 0:%x 2:%x 8:%x 9:%x\n", | ||
719 | sbus_readl(dbri->regs + REG0), | ||
720 | sbus_readl(dbri->regs + REG2), | ||
721 | sbus_readl(dbri->regs + REG8), sbus_readl(dbri->regs + REG9)); | ||
722 | |||
723 | sbus_writel(D_R, dbri->regs + REG0); /* Soft Reset */ | ||
724 | for (i = 0; (sbus_readl(dbri->regs + REG0) & D_R) && i < 64; i++) | ||
725 | udelay(10); | ||
726 | } | ||
727 | |||
728 | /* Lock must not be held before calling this */ | ||
729 | static void dbri_initialize(snd_dbri_t * dbri) | ||
730 | { | ||
731 | volatile s32 *cmd; | ||
732 | u32 dma_addr, tmp; | ||
733 | unsigned long flags; | ||
734 | int n; | ||
735 | |||
736 | spin_lock_irqsave(&dbri->lock, flags); | ||
737 | |||
738 | dbri_reset(dbri); | ||
739 | |||
740 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
741 | dprintk(D_GEN, "init: cmd: %p, int: %p\n", | ||
742 | &dbri->dma->cmd[0], &dbri->dma->intr[0]); | ||
743 | |||
744 | /* | ||
745 | * Initialize the interrupt ringbuffer. | ||
746 | */ | ||
747 | for (n = 0; n < DBRI_NO_INTS - 1; n++) { | ||
748 | dma_addr = dbri->dma_dvma; | ||
749 | dma_addr += dbri_dma_off(intr, ((n + 1) & DBRI_INT_BLK)); | ||
750 | dbri->dma->intr[n * DBRI_INT_BLK] = dma_addr; | ||
751 | } | ||
752 | dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); | ||
753 | dbri->dma->intr[n * DBRI_INT_BLK] = dma_addr; | ||
754 | dbri->dbri_irqp = 1; | ||
755 | |||
756 | /* Initialize pipes */ | ||
757 | for (n = 0; n < DBRI_NO_PIPES; n++) | ||
758 | dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1; | ||
759 | |||
760 | /* We should query the openprom to see what burst sizes this | ||
761 | * SBus supports. For now, just disable all SBus bursts */ | ||
762 | tmp = sbus_readl(dbri->regs + REG0); | ||
763 | tmp &= ~(D_G | D_S | D_E); | ||
764 | sbus_writel(tmp, dbri->regs + REG0); | ||
765 | |||
766 | /* | ||
767 | * Set up the interrupt queue | ||
768 | */ | ||
769 | dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); | ||
770 | *(cmd++) = DBRI_CMD(D_IIQ, 0, 0); | ||
771 | *(cmd++) = dma_addr; | ||
772 | |||
773 | dbri_cmdsend(dbri, cmd); | ||
774 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
775 | } | ||
776 | |||
777 | /* | ||
778 | **************************************************************************** | ||
779 | ************************** DBRI data pipe management *********************** | ||
780 | **************************************************************************** | ||
781 | |||
782 | While DBRI control functions use the command and interrupt buffers, the | ||
783 | main data path takes the form of data pipes, which can be short (command | ||
784 | and interrupt driven), or long (attached to DMA buffers). These functions | ||
785 | provide a rudimentary means of setting up and managing the DBRI's pipes, | ||
786 | but the calling functions have to make sure they respect the pipes' linked | ||
787 | list ordering, among other things. The transmit and receive functions | ||
788 | here interface closely with the transmit and receive interrupt code. | ||
789 | |||
790 | */ | ||
791 | static int pipe_active(snd_dbri_t * dbri, int pipe) | ||
792 | { | ||
793 | return ((pipe >= 0) && (dbri->pipes[pipe].desc != -1)); | ||
794 | } | ||
795 | |||
796 | /* reset_pipe(dbri, pipe) | ||
797 | * | ||
798 | * Called on an in-use pipe to clear anything being transmitted or received | ||
799 | * Lock must be held before calling this. | ||
800 | */ | ||
801 | static void reset_pipe(snd_dbri_t * dbri, int pipe) | ||
802 | { | ||
803 | int sdp; | ||
804 | int desc; | ||
805 | volatile int *cmd; | ||
806 | |||
807 | if (pipe < 0 || pipe > 31) { | ||
808 | printk("DBRI: reset_pipe called with illegal pipe number\n"); | ||
809 | return; | ||
810 | } | ||
811 | |||
812 | sdp = dbri->pipes[pipe].sdp; | ||
813 | if (sdp == 0) { | ||
814 | printk("DBRI: reset_pipe called on uninitialized pipe\n"); | ||
815 | return; | ||
816 | } | ||
817 | |||
818 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
819 | *(cmd++) = DBRI_CMD(D_SDP, 0, sdp | D_SDP_C | D_SDP_P); | ||
820 | *(cmd++) = 0; | ||
821 | dbri_cmdsend(dbri, cmd); | ||
822 | |||
823 | desc = dbri->pipes[pipe].first_desc; | ||
824 | while (desc != -1) { | ||
825 | dbri->descs[desc].inuse = 0; | ||
826 | desc = dbri->descs[desc].next; | ||
827 | } | ||
828 | |||
829 | dbri->pipes[pipe].desc = -1; | ||
830 | dbri->pipes[pipe].first_desc = -1; | ||
831 | } | ||
832 | |||
833 | /* FIXME: direction as an argument? */ | ||
834 | static void setup_pipe(snd_dbri_t * dbri, int pipe, int sdp) | ||
835 | { | ||
836 | if (pipe < 0 || pipe > 31) { | ||
837 | printk("DBRI: setup_pipe called with illegal pipe number\n"); | ||
838 | return; | ||
839 | } | ||
840 | |||
841 | if ((sdp & 0xf800) != sdp) { | ||
842 | printk("DBRI: setup_pipe called with strange SDP value\n"); | ||
843 | /* sdp &= 0xf800; */ | ||
844 | } | ||
845 | |||
846 | /* If this is a fixed receive pipe, arrange for an interrupt | ||
847 | * every time its data changes | ||
848 | */ | ||
849 | if (D_SDP_MODE(sdp) == D_SDP_FIXED && !(sdp & D_SDP_TO_SER)) | ||
850 | sdp |= D_SDP_CHANGE; | ||
851 | |||
852 | sdp |= D_PIPE(pipe); | ||
853 | dbri->pipes[pipe].sdp = sdp; | ||
854 | dbri->pipes[pipe].desc = -1; | ||
855 | dbri->pipes[pipe].first_desc = -1; | ||
856 | if (sdp & D_SDP_TO_SER) | ||
857 | dbri->pipes[pipe].direction = PIPEoutput; | ||
858 | else | ||
859 | dbri->pipes[pipe].direction = PIPEinput; | ||
860 | |||
861 | reset_pipe(dbri, pipe); | ||
862 | } | ||
863 | |||
864 | /* FIXME: direction not needed */ | ||
865 | static void link_time_slot(snd_dbri_t * dbri, int pipe, | ||
866 | enum in_or_out direction, int basepipe, | ||
867 | int length, int cycle) | ||
868 | { | ||
869 | volatile s32 *cmd; | ||
870 | int val; | ||
871 | int prevpipe; | ||
872 | int nextpipe; | ||
873 | |||
874 | if (pipe < 0 || pipe > 31 || basepipe < 0 || basepipe > 31) { | ||
875 | printk | ||
876 | ("DBRI: link_time_slot called with illegal pipe number\n"); | ||
877 | return; | ||
878 | } | ||
879 | |||
880 | if (dbri->pipes[pipe].sdp == 0 || dbri->pipes[basepipe].sdp == 0) { | ||
881 | printk("DBRI: link_time_slot called on uninitialized pipe\n"); | ||
882 | return; | ||
883 | } | ||
884 | |||
885 | /* Deal with CHI special case: | ||
886 | * "If transmission on edges 0 or 1 is desired, then cycle n | ||
887 | * (where n = # of bit times per frame...) must be used." | ||
888 | * - DBRI data sheet, page 11 | ||
889 | */ | ||
890 | if (basepipe == 16 && direction == PIPEoutput && cycle == 0) | ||
891 | cycle = dbri->chi_bpf; | ||
892 | |||
893 | if (basepipe == pipe) { | ||
894 | prevpipe = pipe; | ||
895 | nextpipe = pipe; | ||
896 | } else { | ||
897 | /* We're not initializing a new linked list (basepipe != pipe), | ||
898 | * so run through the linked list and find where this pipe | ||
899 | * should be sloted in, based on its cycle. CHI confuses | ||
900 | * things a bit, since it has a single anchor for both its | ||
901 | * transmit and receive lists. | ||
902 | */ | ||
903 | if (basepipe == 16) { | ||
904 | if (direction == PIPEinput) { | ||
905 | prevpipe = dbri->chi_in_pipe; | ||
906 | } else { | ||
907 | prevpipe = dbri->chi_out_pipe; | ||
908 | } | ||
909 | } else { | ||
910 | prevpipe = basepipe; | ||
911 | } | ||
912 | |||
913 | nextpipe = dbri->pipes[prevpipe].nextpipe; | ||
914 | |||
915 | while (dbri->pipes[nextpipe].cycle < cycle | ||
916 | && dbri->pipes[nextpipe].nextpipe != basepipe) { | ||
917 | prevpipe = nextpipe; | ||
918 | nextpipe = dbri->pipes[nextpipe].nextpipe; | ||
919 | } | ||
920 | } | ||
921 | |||
922 | if (prevpipe == 16) { | ||
923 | if (direction == PIPEinput) { | ||
924 | dbri->chi_in_pipe = pipe; | ||
925 | } else { | ||
926 | dbri->chi_out_pipe = pipe; | ||
927 | } | ||
928 | } else { | ||
929 | dbri->pipes[prevpipe].nextpipe = pipe; | ||
930 | } | ||
931 | |||
932 | dbri->pipes[pipe].nextpipe = nextpipe; | ||
933 | dbri->pipes[pipe].cycle = cycle; | ||
934 | dbri->pipes[pipe].length = length; | ||
935 | |||
936 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
937 | |||
938 | if (direction == PIPEinput) { | ||
939 | val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(prevpipe) | pipe; | ||
940 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
941 | *(cmd++) = | ||
942 | D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe); | ||
943 | *(cmd++) = 0; | ||
944 | } else { | ||
945 | val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(prevpipe) | pipe; | ||
946 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
947 | *(cmd++) = 0; | ||
948 | *(cmd++) = | ||
949 | D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe); | ||
950 | } | ||
951 | |||
952 | dbri_cmdsend(dbri, cmd); | ||
953 | } | ||
954 | |||
955 | static void unlink_time_slot(snd_dbri_t * dbri, int pipe, | ||
956 | enum in_or_out direction, int prevpipe, | ||
957 | int nextpipe) | ||
958 | { | ||
959 | volatile s32 *cmd; | ||
960 | int val; | ||
961 | |||
962 | if (pipe < 0 || pipe > 31 || prevpipe < 0 || prevpipe > 31) { | ||
963 | printk | ||
964 | ("DBRI: unlink_time_slot called with illegal pipe number\n"); | ||
965 | return; | ||
966 | } | ||
967 | |||
968 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
969 | |||
970 | if (direction == PIPEinput) { | ||
971 | val = D_DTS_VI | D_DTS_DEL | D_DTS_PRVIN(prevpipe) | pipe; | ||
972 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
973 | *(cmd++) = D_TS_NEXT(nextpipe); | ||
974 | *(cmd++) = 0; | ||
975 | } else { | ||
976 | val = D_DTS_VO | D_DTS_DEL | D_DTS_PRVOUT(prevpipe) | pipe; | ||
977 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
978 | *(cmd++) = 0; | ||
979 | *(cmd++) = D_TS_NEXT(nextpipe); | ||
980 | } | ||
981 | |||
982 | dbri_cmdsend(dbri, cmd); | ||
983 | } | ||
984 | |||
985 | /* xmit_fixed() / recv_fixed() | ||
986 | * | ||
987 | * Transmit/receive data on a "fixed" pipe - i.e, one whose contents are not | ||
988 | * expected to change much, and which we don't need to buffer. | ||
989 | * The DBRI only interrupts us when the data changes (receive pipes), | ||
990 | * or only changes the data when this function is called (transmit pipes). | ||
991 | * Only short pipes (numbers 16-31) can be used in fixed data mode. | ||
992 | * | ||
993 | * These function operate on a 32-bit field, no matter how large | ||
994 | * the actual time slot is. The interrupt handler takes care of bit | ||
995 | * ordering and alignment. An 8-bit time slot will always end up | ||
996 | * in the low-order 8 bits, filled either MSB-first or LSB-first, | ||
997 | * depending on the settings passed to setup_pipe() | ||
998 | */ | ||
999 | static void xmit_fixed(snd_dbri_t * dbri, int pipe, unsigned int data) | ||
1000 | { | ||
1001 | volatile s32 *cmd; | ||
1002 | |||
1003 | if (pipe < 16 || pipe > 31) { | ||
1004 | printk("DBRI: xmit_fixed: Illegal pipe number\n"); | ||
1005 | return; | ||
1006 | } | ||
1007 | |||
1008 | if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) { | ||
1009 | printk("DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe); | ||
1010 | return; | ||
1011 | } | ||
1012 | |||
1013 | if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) { | ||
1014 | printk("DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe); | ||
1015 | return; | ||
1016 | } | ||
1017 | |||
1018 | if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) { | ||
1019 | printk("DBRI: xmit_fixed: Called on receive pipe %d\n", pipe); | ||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | /* DBRI short pipes always transmit LSB first */ | ||
1024 | |||
1025 | if (dbri->pipes[pipe].sdp & D_SDP_MSB) | ||
1026 | data = reverse_bytes(data, dbri->pipes[pipe].length); | ||
1027 | |||
1028 | cmd = dbri_cmdlock(dbri, GetLock); | ||
1029 | |||
1030 | *(cmd++) = DBRI_CMD(D_SSP, 0, pipe); | ||
1031 | *(cmd++) = data; | ||
1032 | |||
1033 | dbri_cmdsend(dbri, cmd); | ||
1034 | } | ||
1035 | |||
1036 | static void recv_fixed(snd_dbri_t * dbri, int pipe, volatile __u32 * ptr) | ||
1037 | { | ||
1038 | if (pipe < 16 || pipe > 31) { | ||
1039 | printk("DBRI: recv_fixed called with illegal pipe number\n"); | ||
1040 | return; | ||
1041 | } | ||
1042 | |||
1043 | if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) { | ||
1044 | printk("DBRI: recv_fixed called on non-fixed pipe %d\n", pipe); | ||
1045 | return; | ||
1046 | } | ||
1047 | |||
1048 | if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) { | ||
1049 | printk("DBRI: recv_fixed called on transmit pipe %d\n", pipe); | ||
1050 | return; | ||
1051 | } | ||
1052 | |||
1053 | dbri->pipes[pipe].recv_fixed_ptr = ptr; | ||
1054 | } | ||
1055 | |||
1056 | /* setup_descs() | ||
1057 | * | ||
1058 | * Setup transmit/receive data on a "long" pipe - i.e, one associated | ||
1059 | * with a DMA buffer. | ||
1060 | * | ||
1061 | * Only pipe numbers 0-15 can be used in this mode. | ||
1062 | * | ||
1063 | * This function takes a stream number pointing to a data buffer, | ||
1064 | * and work by building chains of descriptors which identify the | ||
1065 | * data buffers. Buffers too large for a single descriptor will | ||
1066 | * be spread across multiple descriptors. | ||
1067 | */ | ||
1068 | static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period) | ||
1069 | { | ||
1070 | dbri_streaminfo_t *info = &dbri->stream_info[streamno]; | ||
1071 | __u32 dvma_buffer; | ||
1072 | int desc = 0; | ||
1073 | int len; | ||
1074 | int first_desc = -1; | ||
1075 | int last_desc = -1; | ||
1076 | |||
1077 | if (info->pipe < 0 || info->pipe > 15) { | ||
1078 | printk("DBRI: setup_descs: Illegal pipe number\n"); | ||
1079 | return -2; | ||
1080 | } | ||
1081 | |||
1082 | if (dbri->pipes[info->pipe].sdp == 0) { | ||
1083 | printk("DBRI: setup_descs: Uninitialized pipe %d\n", | ||
1084 | info->pipe); | ||
1085 | return -2; | ||
1086 | } | ||
1087 | |||
1088 | dvma_buffer = info->dvma_buffer; | ||
1089 | len = info->size; | ||
1090 | |||
1091 | if (streamno == DBRI_PLAY) { | ||
1092 | if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) { | ||
1093 | printk("DBRI: setup_descs: Called on receive pipe %d\n", | ||
1094 | info->pipe); | ||
1095 | return -2; | ||
1096 | } | ||
1097 | } else { | ||
1098 | if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) { | ||
1099 | printk | ||
1100 | ("DBRI: setup_descs: Called on transmit pipe %d\n", | ||
1101 | info->pipe); | ||
1102 | return -2; | ||
1103 | } | ||
1104 | /* Should be able to queue multiple buffers to receive on a pipe */ | ||
1105 | if (pipe_active(dbri, info->pipe)) { | ||
1106 | printk("DBRI: recv_on_pipe: Called on active pipe %d\n", | ||
1107 | info->pipe); | ||
1108 | return -2; | ||
1109 | } | ||
1110 | |||
1111 | /* Make sure buffer size is multiple of four */ | ||
1112 | len &= ~3; | ||
1113 | } | ||
1114 | |||
1115 | while (len > 0) { | ||
1116 | int mylen; | ||
1117 | |||
1118 | for (; desc < DBRI_NO_DESCS; desc++) { | ||
1119 | if (!dbri->descs[desc].inuse) | ||
1120 | break; | ||
1121 | } | ||
1122 | if (desc == DBRI_NO_DESCS) { | ||
1123 | printk("DBRI: setup_descs: No descriptors\n"); | ||
1124 | return -1; | ||
1125 | } | ||
1126 | |||
1127 | if (len > DBRI_TD_MAXCNT) { | ||
1128 | mylen = DBRI_TD_MAXCNT; /* 8KB - 1 */ | ||
1129 | } else { | ||
1130 | mylen = len; | ||
1131 | } | ||
1132 | if (mylen > period) { | ||
1133 | mylen = period; | ||
1134 | } | ||
1135 | |||
1136 | dbri->descs[desc].inuse = 1; | ||
1137 | dbri->descs[desc].next = -1; | ||
1138 | dbri->dma->desc[desc].ba = dvma_buffer; | ||
1139 | dbri->dma->desc[desc].nda = 0; | ||
1140 | |||
1141 | if (streamno == DBRI_PLAY) { | ||
1142 | dbri->descs[desc].len = mylen; | ||
1143 | dbri->dma->desc[desc].word1 = DBRI_TD_CNT(mylen); | ||
1144 | dbri->dma->desc[desc].word4 = 0; | ||
1145 | if (first_desc != -1) | ||
1146 | dbri->dma->desc[desc].word1 |= DBRI_TD_M; | ||
1147 | } else { | ||
1148 | dbri->descs[desc].len = 0; | ||
1149 | dbri->dma->desc[desc].word1 = 0; | ||
1150 | dbri->dma->desc[desc].word4 = | ||
1151 | DBRI_RD_B | DBRI_RD_BCNT(mylen); | ||
1152 | } | ||
1153 | |||
1154 | if (first_desc == -1) { | ||
1155 | first_desc = desc; | ||
1156 | } else { | ||
1157 | dbri->descs[last_desc].next = desc; | ||
1158 | dbri->dma->desc[last_desc].nda = | ||
1159 | dbri->dma_dvma + dbri_dma_off(desc, desc); | ||
1160 | } | ||
1161 | |||
1162 | last_desc = desc; | ||
1163 | dvma_buffer += mylen; | ||
1164 | len -= mylen; | ||
1165 | } | ||
1166 | |||
1167 | if (first_desc == -1 || last_desc == -1) { | ||
1168 | printk("DBRI: setup_descs: Not enough descriptors available\n"); | ||
1169 | return -1; | ||
1170 | } | ||
1171 | |||
1172 | dbri->dma->desc[last_desc].word1 &= ~DBRI_TD_M; | ||
1173 | if (streamno == DBRI_PLAY) { | ||
1174 | dbri->dma->desc[last_desc].word1 |= | ||
1175 | DBRI_TD_I | DBRI_TD_F | DBRI_TD_B; | ||
1176 | } | ||
1177 | dbri->pipes[info->pipe].first_desc = first_desc; | ||
1178 | dbri->pipes[info->pipe].desc = first_desc; | ||
1179 | |||
1180 | for (desc = first_desc; desc != -1; desc = dbri->descs[desc].next) { | ||
1181 | dprintk(D_DESC, "DESC %d: %08x %08x %08x %08x\n", | ||
1182 | desc, | ||
1183 | dbri->dma->desc[desc].word1, | ||
1184 | dbri->dma->desc[desc].ba, | ||
1185 | dbri->dma->desc[desc].nda, dbri->dma->desc[desc].word4); | ||
1186 | } | ||
1187 | return 0; | ||
1188 | } | ||
1189 | |||
1190 | /* | ||
1191 | **************************************************************************** | ||
1192 | ************************** DBRI - CHI interface **************************** | ||
1193 | **************************************************************************** | ||
1194 | |||
1195 | The CHI is a four-wire (clock, frame sync, data in, data out) time-division | ||
1196 | multiplexed serial interface which the DBRI can operate in either master | ||
1197 | (give clock/frame sync) or slave (take clock/frame sync) mode. | ||
1198 | |||
1199 | */ | ||
1200 | |||
1201 | enum master_or_slave { CHImaster, CHIslave }; | ||
1202 | |||
1203 | static void reset_chi(snd_dbri_t * dbri, enum master_or_slave master_or_slave, | ||
1204 | int bits_per_frame) | ||
1205 | { | ||
1206 | volatile s32 *cmd; | ||
1207 | int val; | ||
1208 | static int chi_initialized = 0; /* FIXME: mutex? */ | ||
1209 | |||
1210 | if (!chi_initialized) { | ||
1211 | |||
1212 | cmd = dbri_cmdlock(dbri, GetLock); | ||
1213 | |||
1214 | /* Set CHI Anchor: Pipe 16 */ | ||
1215 | |||
1216 | val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(16) | D_PIPE(16); | ||
1217 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
1218 | *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); | ||
1219 | *(cmd++) = 0; | ||
1220 | |||
1221 | val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(16) | D_PIPE(16); | ||
1222 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
1223 | *(cmd++) = 0; | ||
1224 | *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); | ||
1225 | |||
1226 | dbri->pipes[16].sdp = 1; | ||
1227 | dbri->pipes[16].nextpipe = 16; | ||
1228 | dbri->chi_in_pipe = 16; | ||
1229 | dbri->chi_out_pipe = 16; | ||
1230 | |||
1231 | #if 0 | ||
1232 | chi_initialized++; | ||
1233 | #endif | ||
1234 | } else { | ||
1235 | int pipe; | ||
1236 | |||
1237 | for (pipe = dbri->chi_in_pipe; | ||
1238 | pipe != 16; pipe = dbri->pipes[pipe].nextpipe) { | ||
1239 | unlink_time_slot(dbri, pipe, PIPEinput, | ||
1240 | 16, dbri->pipes[pipe].nextpipe); | ||
1241 | } | ||
1242 | for (pipe = dbri->chi_out_pipe; | ||
1243 | pipe != 16; pipe = dbri->pipes[pipe].nextpipe) { | ||
1244 | unlink_time_slot(dbri, pipe, PIPEoutput, | ||
1245 | 16, dbri->pipes[pipe].nextpipe); | ||
1246 | } | ||
1247 | |||
1248 | dbri->chi_in_pipe = 16; | ||
1249 | dbri->chi_out_pipe = 16; | ||
1250 | |||
1251 | cmd = dbri_cmdlock(dbri, GetLock); | ||
1252 | } | ||
1253 | |||
1254 | if (master_or_slave == CHIslave) { | ||
1255 | /* Setup DBRI for CHI Slave - receive clock, frame sync (FS) | ||
1256 | * | ||
1257 | * CHICM = 0 (slave mode, 8 kHz frame rate) | ||
1258 | * IR = give immediate CHI status interrupt | ||
1259 | * EN = give CHI status interrupt upon change | ||
1260 | */ | ||
1261 | *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(0)); | ||
1262 | } else { | ||
1263 | /* Setup DBRI for CHI Master - generate clock, FS | ||
1264 | * | ||
1265 | * BPF = bits per 8 kHz frame | ||
1266 | * 12.288 MHz / CHICM_divisor = clock rate | ||
1267 | * FD = 1 - drive CHIFS on rising edge of CHICK | ||
1268 | */ | ||
1269 | int clockrate = bits_per_frame * 8; | ||
1270 | int divisor = 12288 / clockrate; | ||
1271 | |||
1272 | if (divisor > 255 || divisor * clockrate != 12288) | ||
1273 | printk("DBRI: illegal bits_per_frame in setup_chi\n"); | ||
1274 | |||
1275 | *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD | ||
1276 | | D_CHI_BPF(bits_per_frame)); | ||
1277 | } | ||
1278 | |||
1279 | dbri->chi_bpf = bits_per_frame; | ||
1280 | |||
1281 | /* CHI Data Mode | ||
1282 | * | ||
1283 | * RCE = 0 - receive on falling edge of CHICK | ||
1284 | * XCE = 1 - transmit on rising edge of CHICK | ||
1285 | * XEN = 1 - enable transmitter | ||
1286 | * REN = 1 - enable receiver | ||
1287 | */ | ||
1288 | |||
1289 | *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); | ||
1290 | *(cmd++) = DBRI_CMD(D_CDM, 0, D_CDM_XCE | D_CDM_XEN | D_CDM_REN); | ||
1291 | |||
1292 | dbri_cmdsend(dbri, cmd); | ||
1293 | } | ||
1294 | |||
1295 | /* | ||
1296 | **************************************************************************** | ||
1297 | *********************** CS4215 audio codec management ********************** | ||
1298 | **************************************************************************** | ||
1299 | |||
1300 | In the standard SPARC audio configuration, the CS4215 codec is attached | ||
1301 | to the DBRI via the CHI interface and few of the DBRI's PIO pins. | ||
1302 | |||
1303 | */ | ||
1304 | static void cs4215_setup_pipes(snd_dbri_t * dbri) | ||
1305 | { | ||
1306 | /* | ||
1307 | * Data mode: | ||
1308 | * Pipe 4: Send timeslots 1-4 (audio data) | ||
1309 | * Pipe 20: Send timeslots 5-8 (part of ctrl data) | ||
1310 | * Pipe 6: Receive timeslots 1-4 (audio data) | ||
1311 | * Pipe 21: Receive timeslots 6-7. We can only receive 20 bits via | ||
1312 | * interrupt, and the rest of the data (slot 5 and 8) is | ||
1313 | * not relevant for us (only for doublechecking). | ||
1314 | * | ||
1315 | * Control mode: | ||
1316 | * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly) | ||
1317 | * Pipe 18: Receive timeslot 1 (clb). | ||
1318 | * Pipe 19: Receive timeslot 7 (version). | ||
1319 | */ | ||
1320 | |||
1321 | setup_pipe(dbri, 4, D_SDP_MEM | D_SDP_TO_SER | D_SDP_MSB); | ||
1322 | setup_pipe(dbri, 20, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); | ||
1323 | setup_pipe(dbri, 6, D_SDP_MEM | D_SDP_FROM_SER | D_SDP_MSB); | ||
1324 | setup_pipe(dbri, 21, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); | ||
1325 | |||
1326 | setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); | ||
1327 | setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); | ||
1328 | setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); | ||
1329 | } | ||
1330 | |||
1331 | static int cs4215_init_data(struct cs4215 *mm) | ||
1332 | { | ||
1333 | /* | ||
1334 | * No action, memory resetting only. | ||
1335 | * | ||
1336 | * Data Time Slot 5-8 | ||
1337 | * Speaker,Line and Headphone enable. Gain set to the half. | ||
1338 | * Input is mike. | ||
1339 | */ | ||
1340 | mm->data[0] = CS4215_LO(0x20) | CS4215_HE | CS4215_LE; | ||
1341 | mm->data[1] = CS4215_RO(0x20) | CS4215_SE; | ||
1342 | mm->data[2] = CS4215_LG(0x8) | CS4215_IS | CS4215_PIO0 | CS4215_PIO1; | ||
1343 | mm->data[3] = CS4215_RG(0x8) | CS4215_MA(0xf); | ||
1344 | |||
1345 | /* | ||
1346 | * Control Time Slot 1-4 | ||
1347 | * 0: Default I/O voltage scale | ||
1348 | * 1: 8 bit ulaw, 8kHz, mono, high pass filter disabled | ||
1349 | * 2: Serial enable, CHI master, 128 bits per frame, clock 1 | ||
1350 | * 3: Tests disabled | ||
1351 | */ | ||
1352 | mm->ctrl[0] = CS4215_RSRVD_1 | CS4215_MLB; | ||
1353 | mm->ctrl[1] = CS4215_DFR_ULAW | CS4215_FREQ[0].csval; | ||
1354 | mm->ctrl[2] = CS4215_XCLK | CS4215_BSEL_128 | CS4215_FREQ[0].xtal; | ||
1355 | mm->ctrl[3] = 0; | ||
1356 | |||
1357 | mm->status = 0; | ||
1358 | mm->version = 0xff; | ||
1359 | mm->precision = 8; /* For ULAW */ | ||
1360 | mm->channels = 2; | ||
1361 | |||
1362 | return 0; | ||
1363 | } | ||
1364 | |||
1365 | static void cs4215_setdata(snd_dbri_t * dbri, int muted) | ||
1366 | { | ||
1367 | if (muted) { | ||
1368 | dbri->mm.data[0] |= 63; | ||
1369 | dbri->mm.data[1] |= 63; | ||
1370 | dbri->mm.data[2] &= ~15; | ||
1371 | dbri->mm.data[3] &= ~15; | ||
1372 | } else { | ||
1373 | /* Start by setting the playback attenuation. */ | ||
1374 | dbri_streaminfo_t *info = &dbri->stream_info[DBRI_PLAY]; | ||
1375 | int left_gain = info->left_gain % 64; | ||
1376 | int right_gain = info->right_gain % 64; | ||
1377 | |||
1378 | if (info->balance < DBRI_MID_BALANCE) { | ||
1379 | right_gain *= info->balance; | ||
1380 | right_gain /= DBRI_MID_BALANCE; | ||
1381 | } else { | ||
1382 | left_gain *= DBRI_RIGHT_BALANCE - info->balance; | ||
1383 | left_gain /= DBRI_MID_BALANCE; | ||
1384 | } | ||
1385 | |||
1386 | dbri->mm.data[0] &= ~0x3f; /* Reset the volume bits */ | ||
1387 | dbri->mm.data[1] &= ~0x3f; | ||
1388 | dbri->mm.data[0] |= (DBRI_MAX_VOLUME - left_gain); | ||
1389 | dbri->mm.data[1] |= (DBRI_MAX_VOLUME - right_gain); | ||
1390 | |||
1391 | /* Now set the recording gain. */ | ||
1392 | info = &dbri->stream_info[DBRI_REC]; | ||
1393 | left_gain = info->left_gain % 16; | ||
1394 | right_gain = info->right_gain % 16; | ||
1395 | dbri->mm.data[2] |= CS4215_LG(left_gain); | ||
1396 | dbri->mm.data[3] |= CS4215_RG(right_gain); | ||
1397 | } | ||
1398 | |||
1399 | xmit_fixed(dbri, 20, *(int *)dbri->mm.data); | ||
1400 | } | ||
1401 | |||
1402 | /* | ||
1403 | * Set the CS4215 to data mode. | ||
1404 | */ | ||
1405 | static void cs4215_open(snd_dbri_t * dbri) | ||
1406 | { | ||
1407 | int data_width; | ||
1408 | u32 tmp; | ||
1409 | |||
1410 | dprintk(D_MM, "cs4215_open: %d channels, %d bits\n", | ||
1411 | dbri->mm.channels, dbri->mm.precision); | ||
1412 | |||
1413 | /* Temporarily mute outputs, and wait 1/8000 sec (125 us) | ||
1414 | * to make sure this takes. This avoids clicking noises. | ||
1415 | */ | ||
1416 | |||
1417 | cs4215_setdata(dbri, 1); | ||
1418 | udelay(125); | ||
1419 | |||
1420 | /* | ||
1421 | * Data mode: | ||
1422 | * Pipe 4: Send timeslots 1-4 (audio data) | ||
1423 | * Pipe 20: Send timeslots 5-8 (part of ctrl data) | ||
1424 | * Pipe 6: Receive timeslots 1-4 (audio data) | ||
1425 | * Pipe 21: Receive timeslots 6-7. We can only receive 20 bits via | ||
1426 | * interrupt, and the rest of the data (slot 5 and 8) is | ||
1427 | * not relevant for us (only for doublechecking). | ||
1428 | * | ||
1429 | * Just like in control mode, the time slots are all offset by eight | ||
1430 | * bits. The CS4215, it seems, observes TSIN (the delayed signal) | ||
1431 | * even if it's the CHI master. Don't ask me... | ||
1432 | */ | ||
1433 | tmp = sbus_readl(dbri->regs + REG0); | ||
1434 | tmp &= ~(D_C); /* Disable CHI */ | ||
1435 | sbus_writel(tmp, dbri->regs + REG0); | ||
1436 | |||
1437 | /* Switch CS4215 to data mode - set PIO3 to 1 */ | ||
1438 | sbus_writel(D_ENPIO | D_PIO1 | D_PIO3 | | ||
1439 | (dbri->mm.onboard ? D_PIO0 : D_PIO2), dbri->regs + REG2); | ||
1440 | |||
1441 | reset_chi(dbri, CHIslave, 128); | ||
1442 | |||
1443 | /* Note: this next doesn't work for 8-bit stereo, because the two | ||
1444 | * channels would be on timeslots 1 and 3, with 2 and 4 idle. | ||
1445 | * (See CS4215 datasheet Fig 15) | ||
1446 | * | ||
1447 | * DBRI non-contiguous mode would be required to make this work. | ||
1448 | */ | ||
1449 | data_width = dbri->mm.channels * dbri->mm.precision; | ||
1450 | |||
1451 | link_time_slot(dbri, 20, PIPEoutput, 16, 32, dbri->mm.offset + 32); | ||
1452 | link_time_slot(dbri, 4, PIPEoutput, 16, data_width, dbri->mm.offset); | ||
1453 | link_time_slot(dbri, 6, PIPEinput, 16, data_width, dbri->mm.offset); | ||
1454 | link_time_slot(dbri, 21, PIPEinput, 16, 16, dbri->mm.offset + 40); | ||
1455 | |||
1456 | /* FIXME: enable CHI after _setdata? */ | ||
1457 | tmp = sbus_readl(dbri->regs + REG0); | ||
1458 | tmp |= D_C; /* Enable CHI */ | ||
1459 | sbus_writel(tmp, dbri->regs + REG0); | ||
1460 | |||
1461 | cs4215_setdata(dbri, 0); | ||
1462 | } | ||
1463 | |||
1464 | /* | ||
1465 | * Send the control information (i.e. audio format) | ||
1466 | */ | ||
1467 | static int cs4215_setctrl(snd_dbri_t * dbri) | ||
1468 | { | ||
1469 | int i, val; | ||
1470 | u32 tmp; | ||
1471 | |||
1472 | /* FIXME - let the CPU do something useful during these delays */ | ||
1473 | |||
1474 | /* Temporarily mute outputs, and wait 1/8000 sec (125 us) | ||
1475 | * to make sure this takes. This avoids clicking noises. | ||
1476 | */ | ||
1477 | |||
1478 | cs4215_setdata(dbri, 1); | ||
1479 | udelay(125); | ||
1480 | |||
1481 | /* | ||
1482 | * Enable Control mode: Set DBRI's PIO3 (4215's D/~C) to 0, then wait | ||
1483 | * 12 cycles <= 12/(5512.5*64) sec = 34.01 usec | ||
1484 | */ | ||
1485 | val = D_ENPIO | D_PIO1 | (dbri->mm.onboard ? D_PIO0 : D_PIO2); | ||
1486 | sbus_writel(val, dbri->regs + REG2); | ||
1487 | dprintk(D_MM, "cs4215_setctrl: reg2=0x%x\n", val); | ||
1488 | udelay(34); | ||
1489 | |||
1490 | /* In Control mode, the CS4215 is a slave device, so the DBRI must | ||
1491 | * operate as CHI master, supplying clocking and frame synchronization. | ||
1492 | * | ||
1493 | * In Data mode, however, the CS4215 must be CHI master to insure | ||
1494 | * that its data stream is synchronous with its codec. | ||
1495 | * | ||
1496 | * The upshot of all this? We start by putting the DBRI into master | ||
1497 | * mode, program the CS4215 in Control mode, then switch the CS4215 | ||
1498 | * into Data mode and put the DBRI into slave mode. Various timing | ||
1499 | * requirements must be observed along the way. | ||
1500 | * | ||
1501 | * Oh, and one more thing, on a SPARCStation 20 (and maybe | ||
1502 | * others?), the addressing of the CS4215's time slots is | ||
1503 | * offset by eight bits, so we add eight to all the "cycle" | ||
1504 | * values in the Define Time Slot (DTS) commands. This is | ||
1505 | * done in hardware by a TI 248 that delays the DBRI->4215 | ||
1506 | * frame sync signal by eight clock cycles. Anybody know why? | ||
1507 | */ | ||
1508 | tmp = sbus_readl(dbri->regs + REG0); | ||
1509 | tmp &= ~D_C; /* Disable CHI */ | ||
1510 | sbus_writel(tmp, dbri->regs + REG0); | ||
1511 | |||
1512 | reset_chi(dbri, CHImaster, 128); | ||
1513 | |||
1514 | /* | ||
1515 | * Control mode: | ||
1516 | * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly) | ||
1517 | * Pipe 18: Receive timeslot 1 (clb). | ||
1518 | * Pipe 19: Receive timeslot 7 (version). | ||
1519 | */ | ||
1520 | |||
1521 | link_time_slot(dbri, 17, PIPEoutput, 16, 32, dbri->mm.offset); | ||
1522 | link_time_slot(dbri, 18, PIPEinput, 16, 8, dbri->mm.offset); | ||
1523 | link_time_slot(dbri, 19, PIPEinput, 16, 8, dbri->mm.offset + 48); | ||
1524 | |||
1525 | /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */ | ||
1526 | dbri->mm.ctrl[0] &= ~CS4215_CLB; | ||
1527 | xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); | ||
1528 | |||
1529 | tmp = sbus_readl(dbri->regs + REG0); | ||
1530 | tmp |= D_C; /* Enable CHI */ | ||
1531 | sbus_writel(tmp, dbri->regs + REG0); | ||
1532 | |||
1533 | for (i = 64; ((dbri->mm.status & 0xe4) != 0x20); --i) { | ||
1534 | udelay(125); | ||
1535 | } | ||
1536 | if (i == 0) { | ||
1537 | dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n", | ||
1538 | dbri->mm.status); | ||
1539 | return -1; | ||
1540 | } | ||
1541 | |||
1542 | /* Disable changes to our copy of the version number, as we are about | ||
1543 | * to leave control mode. | ||
1544 | */ | ||
1545 | recv_fixed(dbri, 19, NULL); | ||
1546 | |||
1547 | /* Terminate CS4215 control mode - data sheet says | ||
1548 | * "Set CLB=1 and send two more frames of valid control info" | ||
1549 | */ | ||
1550 | dbri->mm.ctrl[0] |= CS4215_CLB; | ||
1551 | xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); | ||
1552 | |||
1553 | /* Two frames of control info @ 8kHz frame rate = 250 us delay */ | ||
1554 | udelay(250); | ||
1555 | |||
1556 | cs4215_setdata(dbri, 0); | ||
1557 | |||
1558 | return 0; | ||
1559 | } | ||
1560 | |||
1561 | /* | ||
1562 | * Setup the codec with the sampling rate, audio format and number of | ||
1563 | * channels. | ||
1564 | * As part of the process we resend the settings for the data | ||
1565 | * timeslots as well. | ||
1566 | */ | ||
1567 | static int cs4215_prepare(snd_dbri_t * dbri, unsigned int rate, | ||
1568 | snd_pcm_format_t format, unsigned int channels) | ||
1569 | { | ||
1570 | int freq_idx; | ||
1571 | int ret = 0; | ||
1572 | |||
1573 | /* Lookup index for this rate */ | ||
1574 | for (freq_idx = 0; CS4215_FREQ[freq_idx].freq != 0; freq_idx++) { | ||
1575 | if (CS4215_FREQ[freq_idx].freq == rate) | ||
1576 | break; | ||
1577 | } | ||
1578 | if (CS4215_FREQ[freq_idx].freq != rate) { | ||
1579 | printk(KERN_WARNING "DBRI: Unsupported rate %d Hz\n", rate); | ||
1580 | return -1; | ||
1581 | } | ||
1582 | |||
1583 | switch (format) { | ||
1584 | case SNDRV_PCM_FORMAT_MU_LAW: | ||
1585 | dbri->mm.ctrl[1] = CS4215_DFR_ULAW; | ||
1586 | dbri->mm.precision = 8; | ||
1587 | break; | ||
1588 | case SNDRV_PCM_FORMAT_A_LAW: | ||
1589 | dbri->mm.ctrl[1] = CS4215_DFR_ALAW; | ||
1590 | dbri->mm.precision = 8; | ||
1591 | break; | ||
1592 | case SNDRV_PCM_FORMAT_U8: | ||
1593 | dbri->mm.ctrl[1] = CS4215_DFR_LINEAR8; | ||
1594 | dbri->mm.precision = 8; | ||
1595 | break; | ||
1596 | case SNDRV_PCM_FORMAT_S16_BE: | ||
1597 | dbri->mm.ctrl[1] = CS4215_DFR_LINEAR16; | ||
1598 | dbri->mm.precision = 16; | ||
1599 | break; | ||
1600 | default: | ||
1601 | printk(KERN_WARNING "DBRI: Unsupported format %d\n", format); | ||
1602 | return -1; | ||
1603 | } | ||
1604 | |||
1605 | /* Add rate parameters */ | ||
1606 | dbri->mm.ctrl[1] |= CS4215_FREQ[freq_idx].csval; | ||
1607 | dbri->mm.ctrl[2] = CS4215_XCLK | | ||
1608 | CS4215_BSEL_128 | CS4215_FREQ[freq_idx].xtal; | ||
1609 | |||
1610 | dbri->mm.channels = channels; | ||
1611 | /* Stereo bit: 8 bit stereo not working yet. */ | ||
1612 | if ((channels > 1) && (dbri->mm.precision == 16)) | ||
1613 | dbri->mm.ctrl[1] |= CS4215_DFR_STEREO; | ||
1614 | |||
1615 | ret = cs4215_setctrl(dbri); | ||
1616 | if (ret == 0) | ||
1617 | cs4215_open(dbri); /* set codec to data mode */ | ||
1618 | |||
1619 | return ret; | ||
1620 | } | ||
1621 | |||
1622 | /* | ||
1623 | * | ||
1624 | */ | ||
1625 | static int cs4215_init(snd_dbri_t * dbri) | ||
1626 | { | ||
1627 | u32 reg2 = sbus_readl(dbri->regs + REG2); | ||
1628 | dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2); | ||
1629 | |||
1630 | /* Look for the cs4215 chips */ | ||
1631 | if (reg2 & D_PIO2) { | ||
1632 | dprintk(D_MM, "Onboard CS4215 detected\n"); | ||
1633 | dbri->mm.onboard = 1; | ||
1634 | } | ||
1635 | if (reg2 & D_PIO0) { | ||
1636 | dprintk(D_MM, "Speakerbox detected\n"); | ||
1637 | dbri->mm.onboard = 0; | ||
1638 | |||
1639 | if (reg2 & D_PIO2) { | ||
1640 | printk(KERN_INFO "DBRI: Using speakerbox / " | ||
1641 | "ignoring onboard mmcodec.\n"); | ||
1642 | sbus_writel(D_ENPIO2, dbri->regs + REG2); | ||
1643 | } | ||
1644 | } | ||
1645 | |||
1646 | if (!(reg2 & (D_PIO0 | D_PIO2))) { | ||
1647 | printk(KERN_ERR "DBRI: no mmcodec found.\n"); | ||
1648 | return -EIO; | ||
1649 | } | ||
1650 | |||
1651 | cs4215_setup_pipes(dbri); | ||
1652 | |||
1653 | cs4215_init_data(&dbri->mm); | ||
1654 | |||
1655 | /* Enable capture of the status & version timeslots. */ | ||
1656 | recv_fixed(dbri, 18, &dbri->mm.status); | ||
1657 | recv_fixed(dbri, 19, &dbri->mm.version); | ||
1658 | |||
1659 | dbri->mm.offset = dbri->mm.onboard ? 0 : 8; | ||
1660 | if (cs4215_setctrl(dbri) == -1 || dbri->mm.version == 0xff) { | ||
1661 | dprintk(D_MM, "CS4215 failed probe at offset %d\n", | ||
1662 | dbri->mm.offset); | ||
1663 | return -EIO; | ||
1664 | } | ||
1665 | dprintk(D_MM, "Found CS4215 at offset %d\n", dbri->mm.offset); | ||
1666 | |||
1667 | return 0; | ||
1668 | } | ||
1669 | |||
1670 | /* | ||
1671 | **************************************************************************** | ||
1672 | *************************** DBRI interrupt handler ************************* | ||
1673 | **************************************************************************** | ||
1674 | |||
1675 | The DBRI communicates with the CPU mainly via a circular interrupt | ||
1676 | buffer. When an interrupt is signaled, the CPU walks through the | ||
1677 | buffer and calls dbri_process_one_interrupt() for each interrupt word. | ||
1678 | Complicated interrupts are handled by dedicated functions (which | ||
1679 | appear first in this file). Any pending interrupts can be serviced by | ||
1680 | calling dbri_process_interrupt_buffer(), which works even if the CPU's | ||
1681 | interrupts are disabled. This function is used by dbri_cmdsend() | ||
1682 | to make sure we're synced up with the chip after each command sequence, | ||
1683 | even if we're running cli'ed. | ||
1684 | |||
1685 | */ | ||
1686 | |||
1687 | /* xmit_descs() | ||
1688 | * | ||
1689 | * Transmit the current TD's for recording/playing, if needed. | ||
1690 | * For playback, ALSA has filled the DMA memory with new data (we hope). | ||
1691 | */ | ||
1692 | static void xmit_descs(unsigned long data) | ||
1693 | { | ||
1694 | snd_dbri_t *dbri = (snd_dbri_t *) data; | ||
1695 | dbri_streaminfo_t *info; | ||
1696 | volatile s32 *cmd; | ||
1697 | unsigned long flags; | ||
1698 | int first_td; | ||
1699 | |||
1700 | if (dbri == NULL) | ||
1701 | return; /* Disabled */ | ||
1702 | |||
1703 | /* First check the recording stream for buffer overflow */ | ||
1704 | info = &dbri->stream_info[DBRI_REC]; | ||
1705 | spin_lock_irqsave(&dbri->lock, flags); | ||
1706 | |||
1707 | if ((info->left >= info->size) && (info->pipe >= 0)) { | ||
1708 | first_td = dbri->pipes[info->pipe].first_desc; | ||
1709 | |||
1710 | dprintk(D_DESC, "xmit_descs rec @ TD %d\n", first_td); | ||
1711 | |||
1712 | /* Stream could be closed by the time we run. */ | ||
1713 | if (first_td < 0) { | ||
1714 | goto play; | ||
1715 | } | ||
1716 | |||
1717 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
1718 | *(cmd++) = DBRI_CMD(D_SDP, 0, | ||
1719 | dbri->pipes[info->pipe].sdp | ||
1720 | | D_SDP_P | D_SDP_EVERY | D_SDP_C); | ||
1721 | *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); | ||
1722 | dbri_cmdsend(dbri, cmd); | ||
1723 | |||
1724 | /* Reset our admin of the pipe & bytes read. */ | ||
1725 | dbri->pipes[info->pipe].desc = first_td; | ||
1726 | info->left = 0; | ||
1727 | } | ||
1728 | |||
1729 | play: | ||
1730 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1731 | |||
1732 | /* Now check the playback stream for buffer underflow */ | ||
1733 | info = &dbri->stream_info[DBRI_PLAY]; | ||
1734 | spin_lock_irqsave(&dbri->lock, flags); | ||
1735 | |||
1736 | if ((info->left <= 0) && (info->pipe >= 0)) { | ||
1737 | first_td = dbri->pipes[info->pipe].first_desc; | ||
1738 | |||
1739 | dprintk(D_DESC, "xmit_descs play @ TD %d\n", first_td); | ||
1740 | |||
1741 | /* Stream could be closed by the time we run. */ | ||
1742 | if (first_td < 0) { | ||
1743 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1744 | return; | ||
1745 | } | ||
1746 | |||
1747 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
1748 | *(cmd++) = DBRI_CMD(D_SDP, 0, | ||
1749 | dbri->pipes[info->pipe].sdp | ||
1750 | | D_SDP_P | D_SDP_EVERY | D_SDP_C); | ||
1751 | *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); | ||
1752 | dbri_cmdsend(dbri, cmd); | ||
1753 | |||
1754 | /* Reset our admin of the pipe & bytes written. */ | ||
1755 | dbri->pipes[info->pipe].desc = first_td; | ||
1756 | info->left = info->size; | ||
1757 | } | ||
1758 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1759 | } | ||
1760 | |||
1761 | DECLARE_TASKLET(xmit_descs_task, xmit_descs, 0); | ||
1762 | |||
1763 | /* transmission_complete_intr() | ||
1764 | * | ||
1765 | * Called by main interrupt handler when DBRI signals transmission complete | ||
1766 | * on a pipe (interrupt triggered by the B bit in a transmit descriptor). | ||
1767 | * | ||
1768 | * Walks through the pipe's list of transmit buffer descriptors, releasing | ||
1769 | * each one's DMA buffer (if present), flagging the descriptor available, | ||
1770 | * and signaling its callback routine (if present), before proceeding | ||
1771 | * to the next one. Stops when the first descriptor is found without | ||
1772 | * TBC (Transmit Buffer Complete) set, or we've run through them all. | ||
1773 | */ | ||
1774 | |||
1775 | static void transmission_complete_intr(snd_dbri_t * dbri, int pipe) | ||
1776 | { | ||
1777 | dbri_streaminfo_t *info; | ||
1778 | int td; | ||
1779 | int status; | ||
1780 | |||
1781 | info = &dbri->stream_info[DBRI_PLAY]; | ||
1782 | |||
1783 | td = dbri->pipes[pipe].desc; | ||
1784 | while (td >= 0) { | ||
1785 | if (td >= DBRI_NO_DESCS) { | ||
1786 | printk(KERN_ERR "DBRI: invalid td on pipe %d\n", pipe); | ||
1787 | return; | ||
1788 | } | ||
1789 | |||
1790 | status = DBRI_TD_STATUS(dbri->dma->desc[td].word4); | ||
1791 | if (!(status & DBRI_TD_TBC)) { | ||
1792 | break; | ||
1793 | } | ||
1794 | |||
1795 | dprintk(D_INT, "TD %d, status 0x%02x\n", td, status); | ||
1796 | |||
1797 | dbri->dma->desc[td].word4 = 0; /* Reset it for next time. */ | ||
1798 | info->offset += dbri->descs[td].len; | ||
1799 | info->left -= dbri->descs[td].len; | ||
1800 | |||
1801 | /* On the last TD, transmit them all again. */ | ||
1802 | if (dbri->descs[td].next == -1) { | ||
1803 | if (info->left > 0) { | ||
1804 | printk(KERN_WARNING | ||
1805 | "%d bytes left after last transfer.\n", | ||
1806 | info->left); | ||
1807 | info->left = 0; | ||
1808 | } | ||
1809 | tasklet_schedule(&xmit_descs_task); | ||
1810 | } | ||
1811 | |||
1812 | td = dbri->descs[td].next; | ||
1813 | dbri->pipes[pipe].desc = td; | ||
1814 | } | ||
1815 | |||
1816 | /* Notify ALSA */ | ||
1817 | if (spin_is_locked(&dbri->lock)) { | ||
1818 | spin_unlock(&dbri->lock); | ||
1819 | snd_pcm_period_elapsed(info->substream); | ||
1820 | spin_lock(&dbri->lock); | ||
1821 | } else | ||
1822 | snd_pcm_period_elapsed(info->substream); | ||
1823 | } | ||
1824 | |||
1825 | static void reception_complete_intr(snd_dbri_t * dbri, int pipe) | ||
1826 | { | ||
1827 | dbri_streaminfo_t *info; | ||
1828 | int rd = dbri->pipes[pipe].desc; | ||
1829 | s32 status; | ||
1830 | |||
1831 | if (rd < 0 || rd >= DBRI_NO_DESCS) { | ||
1832 | printk(KERN_ERR "DBRI: invalid rd on pipe %d\n", pipe); | ||
1833 | return; | ||
1834 | } | ||
1835 | |||
1836 | dbri->descs[rd].inuse = 0; | ||
1837 | dbri->pipes[pipe].desc = dbri->descs[rd].next; | ||
1838 | status = dbri->dma->desc[rd].word1; | ||
1839 | dbri->dma->desc[rd].word1 = 0; /* Reset it for next time. */ | ||
1840 | |||
1841 | info = &dbri->stream_info[DBRI_REC]; | ||
1842 | info->offset += DBRI_RD_CNT(status); | ||
1843 | info->left += DBRI_RD_CNT(status); | ||
1844 | |||
1845 | /* FIXME: Check status */ | ||
1846 | |||
1847 | dprintk(D_INT, "Recv RD %d, status 0x%02x, len %d\n", | ||
1848 | rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status)); | ||
1849 | |||
1850 | /* On the last TD, transmit them all again. */ | ||
1851 | if (dbri->descs[rd].next == -1) { | ||
1852 | if (info->left > info->size) { | ||
1853 | printk(KERN_WARNING | ||
1854 | "%d bytes recorded in %d size buffer.\n", | ||
1855 | info->left, info->size); | ||
1856 | } | ||
1857 | tasklet_schedule(&xmit_descs_task); | ||
1858 | } | ||
1859 | |||
1860 | /* Notify ALSA */ | ||
1861 | if (spin_is_locked(&dbri->lock)) { | ||
1862 | spin_unlock(&dbri->lock); | ||
1863 | snd_pcm_period_elapsed(info->substream); | ||
1864 | spin_lock(&dbri->lock); | ||
1865 | } else | ||
1866 | snd_pcm_period_elapsed(info->substream); | ||
1867 | } | ||
1868 | |||
1869 | static void dbri_process_one_interrupt(snd_dbri_t * dbri, int x) | ||
1870 | { | ||
1871 | int val = D_INTR_GETVAL(x); | ||
1872 | int channel = D_INTR_GETCHAN(x); | ||
1873 | int command = D_INTR_GETCMD(x); | ||
1874 | int code = D_INTR_GETCODE(x); | ||
1875 | #ifdef DBRI_DEBUG | ||
1876 | int rval = D_INTR_GETRVAL(x); | ||
1877 | #endif | ||
1878 | |||
1879 | if (channel == D_INTR_CMD) { | ||
1880 | dprintk(D_CMD, "INTR: Command: %-5s Value:%d\n", | ||
1881 | cmds[command], val); | ||
1882 | } else { | ||
1883 | dprintk(D_INT, "INTR: Chan:%d Code:%d Val:%#x\n", | ||
1884 | channel, code, rval); | ||
1885 | } | ||
1886 | |||
1887 | if (channel == D_INTR_CMD && command == D_WAIT) { | ||
1888 | dbri->wait_seen++; | ||
1889 | return; | ||
1890 | } | ||
1891 | |||
1892 | switch (code) { | ||
1893 | case D_INTR_BRDY: | ||
1894 | reception_complete_intr(dbri, channel); | ||
1895 | break; | ||
1896 | case D_INTR_XCMP: | ||
1897 | case D_INTR_MINT: | ||
1898 | transmission_complete_intr(dbri, channel); | ||
1899 | break; | ||
1900 | case D_INTR_UNDR: | ||
1901 | /* UNDR - Transmission underrun | ||
1902 | * resend SDP command with clear pipe bit (C) set | ||
1903 | */ | ||
1904 | { | ||
1905 | volatile s32 *cmd; | ||
1906 | |||
1907 | int pipe = channel; | ||
1908 | int td = dbri->pipes[pipe].desc; | ||
1909 | |||
1910 | dbri->dma->desc[td].word4 = 0; | ||
1911 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
1912 | *(cmd++) = DBRI_CMD(D_SDP, 0, | ||
1913 | dbri->pipes[pipe].sdp | ||
1914 | | D_SDP_P | D_SDP_C | D_SDP_2SAME); | ||
1915 | *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, td); | ||
1916 | dbri_cmdsend(dbri, cmd); | ||
1917 | } | ||
1918 | break; | ||
1919 | case D_INTR_FXDT: | ||
1920 | /* FXDT - Fixed data change */ | ||
1921 | if (dbri->pipes[channel].sdp & D_SDP_MSB) | ||
1922 | val = reverse_bytes(val, dbri->pipes[channel].length); | ||
1923 | |||
1924 | if (dbri->pipes[channel].recv_fixed_ptr) | ||
1925 | *(dbri->pipes[channel].recv_fixed_ptr) = val; | ||
1926 | break; | ||
1927 | default: | ||
1928 | if (channel != D_INTR_CMD) | ||
1929 | printk(KERN_WARNING | ||
1930 | "DBRI: Ignored Interrupt: %d (0x%x)\n", code, x); | ||
1931 | } | ||
1932 | } | ||
1933 | |||
1934 | /* dbri_process_interrupt_buffer advances through the DBRI's interrupt | ||
1935 | * buffer until it finds a zero word (indicating nothing more to do | ||
1936 | * right now). Non-zero words require processing and are handed off | ||
1937 | * to dbri_process_one_interrupt AFTER advancing the pointer. This | ||
1938 | * order is important since we might recurse back into this function | ||
1939 | * and need to make sure the pointer has been advanced first. | ||
1940 | */ | ||
1941 | static void dbri_process_interrupt_buffer(snd_dbri_t * dbri) | ||
1942 | { | ||
1943 | s32 x; | ||
1944 | |||
1945 | while ((x = dbri->dma->intr[dbri->dbri_irqp]) != 0) { | ||
1946 | dbri->dma->intr[dbri->dbri_irqp] = 0; | ||
1947 | dbri->dbri_irqp++; | ||
1948 | if (dbri->dbri_irqp == (DBRI_NO_INTS * DBRI_INT_BLK)) | ||
1949 | dbri->dbri_irqp = 1; | ||
1950 | else if ((dbri->dbri_irqp & (DBRI_INT_BLK - 1)) == 0) | ||
1951 | dbri->dbri_irqp++; | ||
1952 | |||
1953 | dbri_process_one_interrupt(dbri, x); | ||
1954 | } | ||
1955 | } | ||
1956 | |||
1957 | static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id, | ||
1958 | struct pt_regs *regs) | ||
1959 | { | ||
1960 | snd_dbri_t *dbri = dev_id; | ||
1961 | static int errcnt = 0; | ||
1962 | int x; | ||
1963 | |||
1964 | if (dbri == NULL) | ||
1965 | return IRQ_NONE; | ||
1966 | spin_lock(&dbri->lock); | ||
1967 | |||
1968 | /* | ||
1969 | * Read it, so the interrupt goes away. | ||
1970 | */ | ||
1971 | x = sbus_readl(dbri->regs + REG1); | ||
1972 | |||
1973 | if (x & (D_MRR | D_MLE | D_LBG | D_MBE)) { | ||
1974 | u32 tmp; | ||
1975 | |||
1976 | if (x & D_MRR) | ||
1977 | printk(KERN_ERR | ||
1978 | "DBRI: Multiple Error Ack on SBus reg1=0x%x\n", | ||
1979 | x); | ||
1980 | if (x & D_MLE) | ||
1981 | printk(KERN_ERR | ||
1982 | "DBRI: Multiple Late Error on SBus reg1=0x%x\n", | ||
1983 | x); | ||
1984 | if (x & D_LBG) | ||
1985 | printk(KERN_ERR | ||
1986 | "DBRI: Lost Bus Grant on SBus reg1=0x%x\n", x); | ||
1987 | if (x & D_MBE) | ||
1988 | printk(KERN_ERR | ||
1989 | "DBRI: Burst Error on SBus reg1=0x%x\n", x); | ||
1990 | |||
1991 | /* Some of these SBus errors cause the chip's SBus circuitry | ||
1992 | * to be disabled, so just re-enable and try to keep going. | ||
1993 | * | ||
1994 | * The only one I've seen is MRR, which will be triggered | ||
1995 | * if you let a transmit pipe underrun, then try to CDP it. | ||
1996 | * | ||
1997 | * If these things persist, we should probably reset | ||
1998 | * and re-init the chip. | ||
1999 | */ | ||
2000 | if ((++errcnt) % 10 == 0) { | ||
2001 | dprintk(D_INT, "Interrupt errors exceeded.\n"); | ||
2002 | dbri_reset(dbri); | ||
2003 | } else { | ||
2004 | tmp = sbus_readl(dbri->regs + REG0); | ||
2005 | tmp &= ~(D_D); | ||
2006 | sbus_writel(tmp, dbri->regs + REG0); | ||
2007 | } | ||
2008 | } | ||
2009 | |||
2010 | dbri_process_interrupt_buffer(dbri); | ||
2011 | |||
2012 | /* FIXME: Write 0 into regs to ACK interrupt */ | ||
2013 | |||
2014 | spin_unlock(&dbri->lock); | ||
2015 | |||
2016 | return IRQ_HANDLED; | ||
2017 | } | ||
2018 | |||
2019 | /**************************************************************************** | ||
2020 | PCM Interface | ||
2021 | ****************************************************************************/ | ||
2022 | static snd_pcm_hardware_t snd_dbri_pcm_hw = { | ||
2023 | .info = (SNDRV_PCM_INFO_MMAP | | ||
2024 | SNDRV_PCM_INFO_INTERLEAVED | | ||
2025 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
2026 | SNDRV_PCM_INFO_MMAP_VALID), | ||
2027 | .formats = SNDRV_PCM_FMTBIT_MU_LAW | | ||
2028 | SNDRV_PCM_FMTBIT_A_LAW | | ||
2029 | SNDRV_PCM_FMTBIT_U8 | | ||
2030 | SNDRV_PCM_FMTBIT_S16_BE, | ||
2031 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
2032 | .rate_min = 8000, | ||
2033 | .rate_max = 48000, | ||
2034 | .channels_min = 1, | ||
2035 | .channels_max = 2, | ||
2036 | .buffer_bytes_max = (64 * 1024), | ||
2037 | .period_bytes_min = 1, | ||
2038 | .period_bytes_max = DBRI_TD_MAXCNT, | ||
2039 | .periods_min = 1, | ||
2040 | .periods_max = 1024, | ||
2041 | }; | ||
2042 | |||
2043 | static int snd_dbri_open(snd_pcm_substream_t * substream) | ||
2044 | { | ||
2045 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2046 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
2047 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2048 | unsigned long flags; | ||
2049 | |||
2050 | dprintk(D_USR, "open audio output.\n"); | ||
2051 | runtime->hw = snd_dbri_pcm_hw; | ||
2052 | |||
2053 | spin_lock_irqsave(&dbri->lock, flags); | ||
2054 | info->substream = substream; | ||
2055 | info->left = 0; | ||
2056 | info->offset = 0; | ||
2057 | info->dvma_buffer = 0; | ||
2058 | info->pipe = -1; | ||
2059 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
2060 | |||
2061 | cs4215_open(dbri); | ||
2062 | |||
2063 | return 0; | ||
2064 | } | ||
2065 | |||
2066 | static int snd_dbri_close(snd_pcm_substream_t * substream) | ||
2067 | { | ||
2068 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2069 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2070 | |||
2071 | dprintk(D_USR, "close audio output.\n"); | ||
2072 | info->substream = NULL; | ||
2073 | info->left = 0; | ||
2074 | info->offset = 0; | ||
2075 | |||
2076 | return 0; | ||
2077 | } | ||
2078 | |||
2079 | static int snd_dbri_hw_params(snd_pcm_substream_t * substream, | ||
2080 | snd_pcm_hw_params_t * hw_params) | ||
2081 | { | ||
2082 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
2083 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2084 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2085 | int direction; | ||
2086 | int ret; | ||
2087 | |||
2088 | /* set sampling rate, audio format and number of channels */ | ||
2089 | ret = cs4215_prepare(dbri, params_rate(hw_params), | ||
2090 | params_format(hw_params), | ||
2091 | params_channels(hw_params)); | ||
2092 | if (ret != 0) | ||
2093 | return ret; | ||
2094 | |||
2095 | if ((ret = snd_pcm_lib_malloc_pages(substream, | ||
2096 | params_buffer_bytes(hw_params))) < 0) { | ||
2097 | snd_printk(KERN_ERR "malloc_pages failed with %d\n", ret); | ||
2098 | return ret; | ||
2099 | } | ||
2100 | |||
2101 | /* hw_params can get called multiple times. Only map the DMA once. | ||
2102 | */ | ||
2103 | if (info->dvma_buffer == 0) { | ||
2104 | if (DBRI_STREAMNO(substream) == DBRI_PLAY) | ||
2105 | direction = SBUS_DMA_TODEVICE; | ||
2106 | else | ||
2107 | direction = SBUS_DMA_FROMDEVICE; | ||
2108 | |||
2109 | info->dvma_buffer = sbus_map_single(dbri->sdev, | ||
2110 | runtime->dma_area, | ||
2111 | params_buffer_bytes(hw_params), | ||
2112 | direction); | ||
2113 | } | ||
2114 | |||
2115 | direction = params_buffer_bytes(hw_params); | ||
2116 | dprintk(D_USR, "hw_params: %d bytes, dvma=%x\n", | ||
2117 | direction, info->dvma_buffer); | ||
2118 | return 0; | ||
2119 | } | ||
2120 | |||
2121 | static int snd_dbri_hw_free(snd_pcm_substream_t * substream) | ||
2122 | { | ||
2123 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2124 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2125 | int direction; | ||
2126 | dprintk(D_USR, "hw_free.\n"); | ||
2127 | |||
2128 | /* hw_free can get called multiple times. Only unmap the DMA once. | ||
2129 | */ | ||
2130 | if (info->dvma_buffer) { | ||
2131 | if (DBRI_STREAMNO(substream) == DBRI_PLAY) | ||
2132 | direction = SBUS_DMA_TODEVICE; | ||
2133 | else | ||
2134 | direction = SBUS_DMA_FROMDEVICE; | ||
2135 | |||
2136 | sbus_unmap_single(dbri->sdev, info->dvma_buffer, | ||
2137 | substream->runtime->buffer_size, direction); | ||
2138 | info->dvma_buffer = 0; | ||
2139 | } | ||
2140 | info->pipe = -1; | ||
2141 | |||
2142 | return snd_pcm_lib_free_pages(substream); | ||
2143 | } | ||
2144 | |||
2145 | static int snd_dbri_prepare(snd_pcm_substream_t * substream) | ||
2146 | { | ||
2147 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2148 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2149 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
2150 | int ret; | ||
2151 | |||
2152 | info->size = snd_pcm_lib_buffer_bytes(substream); | ||
2153 | if (DBRI_STREAMNO(substream) == DBRI_PLAY) | ||
2154 | info->pipe = 4; /* Send pipe */ | ||
2155 | else { | ||
2156 | info->pipe = 6; /* Receive pipe */ | ||
2157 | info->left = info->size; /* To trigger submittal */ | ||
2158 | } | ||
2159 | |||
2160 | spin_lock_irq(&dbri->lock); | ||
2161 | |||
2162 | /* Setup the all the transmit/receive desciptors to cover the | ||
2163 | * whole DMA buffer. | ||
2164 | */ | ||
2165 | ret = setup_descs(dbri, DBRI_STREAMNO(substream), | ||
2166 | snd_pcm_lib_period_bytes(substream)); | ||
2167 | |||
2168 | runtime->stop_threshold = DBRI_TD_MAXCNT / runtime->channels; | ||
2169 | |||
2170 | spin_unlock_irq(&dbri->lock); | ||
2171 | |||
2172 | dprintk(D_USR, "prepare audio output. %d bytes\n", info->size); | ||
2173 | return ret; | ||
2174 | } | ||
2175 | |||
2176 | static int snd_dbri_trigger(snd_pcm_substream_t * substream, int cmd) | ||
2177 | { | ||
2178 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2179 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2180 | int ret = 0; | ||
2181 | |||
2182 | switch (cmd) { | ||
2183 | case SNDRV_PCM_TRIGGER_START: | ||
2184 | dprintk(D_USR, "start audio, period is %d bytes\n", | ||
2185 | (int)snd_pcm_lib_period_bytes(substream)); | ||
2186 | /* Enable & schedule the tasklet that re-submits the TDs. */ | ||
2187 | xmit_descs_task.data = (unsigned long)dbri; | ||
2188 | tasklet_schedule(&xmit_descs_task); | ||
2189 | break; | ||
2190 | case SNDRV_PCM_TRIGGER_STOP: | ||
2191 | dprintk(D_USR, "stop audio.\n"); | ||
2192 | /* Make the tasklet bail out immediately. */ | ||
2193 | xmit_descs_task.data = 0; | ||
2194 | reset_pipe(dbri, info->pipe); | ||
2195 | break; | ||
2196 | default: | ||
2197 | ret = -EINVAL; | ||
2198 | } | ||
2199 | |||
2200 | return ret; | ||
2201 | } | ||
2202 | |||
2203 | static snd_pcm_uframes_t snd_dbri_pointer(snd_pcm_substream_t * substream) | ||
2204 | { | ||
2205 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2206 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2207 | snd_pcm_uframes_t ret; | ||
2208 | |||
2209 | ret = bytes_to_frames(substream->runtime, info->offset) | ||
2210 | % substream->runtime->buffer_size; | ||
2211 | dprintk(D_USR, "I/O pointer: %ld frames, %d bytes left.\n", | ||
2212 | ret, info->left); | ||
2213 | return ret; | ||
2214 | } | ||
2215 | |||
2216 | static snd_pcm_ops_t snd_dbri_ops = { | ||
2217 | .open = snd_dbri_open, | ||
2218 | .close = snd_dbri_close, | ||
2219 | .ioctl = snd_pcm_lib_ioctl, | ||
2220 | .hw_params = snd_dbri_hw_params, | ||
2221 | .hw_free = snd_dbri_hw_free, | ||
2222 | .prepare = snd_dbri_prepare, | ||
2223 | .trigger = snd_dbri_trigger, | ||
2224 | .pointer = snd_dbri_pointer, | ||
2225 | }; | ||
2226 | |||
2227 | static int __devinit snd_dbri_pcm(snd_dbri_t * dbri) | ||
2228 | { | ||
2229 | snd_pcm_t *pcm; | ||
2230 | int err; | ||
2231 | |||
2232 | if ((err = snd_pcm_new(dbri->card, | ||
2233 | /* ID */ "sun_dbri", | ||
2234 | /* device */ 0, | ||
2235 | /* playback count */ 1, | ||
2236 | /* capture count */ 1, &pcm)) < 0) | ||
2237 | return err; | ||
2238 | snd_assert(pcm != NULL, return -EINVAL); | ||
2239 | |||
2240 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops); | ||
2241 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops); | ||
2242 | |||
2243 | pcm->private_data = dbri; | ||
2244 | pcm->info_flags = 0; | ||
2245 | strcpy(pcm->name, dbri->card->shortname); | ||
2246 | dbri->pcm = pcm; | ||
2247 | |||
2248 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
2249 | SNDRV_DMA_TYPE_CONTINUOUS, | ||
2250 | snd_dma_continuous_data(GFP_KERNEL), | ||
2251 | 64 * 1024, 64 * 1024)) < 0) { | ||
2252 | return err; | ||
2253 | } | ||
2254 | |||
2255 | return 0; | ||
2256 | } | ||
2257 | |||
2258 | /***************************************************************************** | ||
2259 | Mixer interface | ||
2260 | *****************************************************************************/ | ||
2261 | |||
2262 | static int snd_cs4215_info_volume(snd_kcontrol_t * kcontrol, | ||
2263 | snd_ctl_elem_info_t * uinfo) | ||
2264 | { | ||
2265 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2266 | uinfo->count = 2; | ||
2267 | uinfo->value.integer.min = 0; | ||
2268 | if (kcontrol->private_value == DBRI_PLAY) { | ||
2269 | uinfo->value.integer.max = DBRI_MAX_VOLUME; | ||
2270 | } else { | ||
2271 | uinfo->value.integer.max = DBRI_MAX_GAIN; | ||
2272 | } | ||
2273 | return 0; | ||
2274 | } | ||
2275 | |||
2276 | static int snd_cs4215_get_volume(snd_kcontrol_t * kcontrol, | ||
2277 | snd_ctl_elem_value_t * ucontrol) | ||
2278 | { | ||
2279 | snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol); | ||
2280 | dbri_streaminfo_t *info; | ||
2281 | snd_assert(dbri != NULL, return -EINVAL); | ||
2282 | info = &dbri->stream_info[kcontrol->private_value]; | ||
2283 | snd_assert(info != NULL, return -EINVAL); | ||
2284 | |||
2285 | ucontrol->value.integer.value[0] = info->left_gain; | ||
2286 | ucontrol->value.integer.value[1] = info->right_gain; | ||
2287 | return 0; | ||
2288 | } | ||
2289 | |||
2290 | static int snd_cs4215_put_volume(snd_kcontrol_t * kcontrol, | ||
2291 | snd_ctl_elem_value_t * ucontrol) | ||
2292 | { | ||
2293 | snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol); | ||
2294 | dbri_streaminfo_t *info = &dbri->stream_info[kcontrol->private_value]; | ||
2295 | unsigned long flags; | ||
2296 | int changed = 0; | ||
2297 | |||
2298 | if (info->left_gain != ucontrol->value.integer.value[0]) { | ||
2299 | info->left_gain = ucontrol->value.integer.value[0]; | ||
2300 | changed = 1; | ||
2301 | } | ||
2302 | if (info->right_gain != ucontrol->value.integer.value[1]) { | ||
2303 | info->right_gain = ucontrol->value.integer.value[1]; | ||
2304 | changed = 1; | ||
2305 | } | ||
2306 | if (changed == 1) { | ||
2307 | /* First mute outputs, and wait 1/8000 sec (125 us) | ||
2308 | * to make sure this takes. This avoids clicking noises. | ||
2309 | */ | ||
2310 | spin_lock_irqsave(&dbri->lock, flags); | ||
2311 | |||
2312 | cs4215_setdata(dbri, 1); | ||
2313 | udelay(125); | ||
2314 | cs4215_setdata(dbri, 0); | ||
2315 | |||
2316 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
2317 | } | ||
2318 | return changed; | ||
2319 | } | ||
2320 | |||
2321 | static int snd_cs4215_info_single(snd_kcontrol_t * kcontrol, | ||
2322 | snd_ctl_elem_info_t * uinfo) | ||
2323 | { | ||
2324 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
2325 | |||
2326 | uinfo->type = (mask == 1) ? | ||
2327 | SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2328 | uinfo->count = 1; | ||
2329 | uinfo->value.integer.min = 0; | ||
2330 | uinfo->value.integer.max = mask; | ||
2331 | return 0; | ||
2332 | } | ||
2333 | |||
2334 | static int snd_cs4215_get_single(snd_kcontrol_t * kcontrol, | ||
2335 | snd_ctl_elem_value_t * ucontrol) | ||
2336 | { | ||
2337 | snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol); | ||
2338 | int elem = kcontrol->private_value & 0xff; | ||
2339 | int shift = (kcontrol->private_value >> 8) & 0xff; | ||
2340 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
2341 | int invert = (kcontrol->private_value >> 24) & 1; | ||
2342 | snd_assert(dbri != NULL, return -EINVAL); | ||
2343 | |||
2344 | if (elem < 4) { | ||
2345 | ucontrol->value.integer.value[0] = | ||
2346 | (dbri->mm.data[elem] >> shift) & mask; | ||
2347 | } else { | ||
2348 | ucontrol->value.integer.value[0] = | ||
2349 | (dbri->mm.ctrl[elem - 4] >> shift) & mask; | ||
2350 | } | ||
2351 | |||
2352 | if (invert == 1) { | ||
2353 | ucontrol->value.integer.value[0] = | ||
2354 | mask - ucontrol->value.integer.value[0]; | ||
2355 | } | ||
2356 | return 0; | ||
2357 | } | ||
2358 | |||
2359 | static int snd_cs4215_put_single(snd_kcontrol_t * kcontrol, | ||
2360 | snd_ctl_elem_value_t * ucontrol) | ||
2361 | { | ||
2362 | snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol); | ||
2363 | unsigned long flags; | ||
2364 | int elem = kcontrol->private_value & 0xff; | ||
2365 | int shift = (kcontrol->private_value >> 8) & 0xff; | ||
2366 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
2367 | int invert = (kcontrol->private_value >> 24) & 1; | ||
2368 | int changed = 0; | ||
2369 | unsigned short val; | ||
2370 | snd_assert(dbri != NULL, return -EINVAL); | ||
2371 | |||
2372 | val = (ucontrol->value.integer.value[0] & mask); | ||
2373 | if (invert == 1) | ||
2374 | val = mask - val; | ||
2375 | val <<= shift; | ||
2376 | |||
2377 | if (elem < 4) { | ||
2378 | dbri->mm.data[elem] = (dbri->mm.data[elem] & | ||
2379 | ~(mask << shift)) | val; | ||
2380 | changed = (val != dbri->mm.data[elem]); | ||
2381 | } else { | ||
2382 | dbri->mm.ctrl[elem - 4] = (dbri->mm.ctrl[elem - 4] & | ||
2383 | ~(mask << shift)) | val; | ||
2384 | changed = (val != dbri->mm.ctrl[elem - 4]); | ||
2385 | } | ||
2386 | |||
2387 | dprintk(D_GEN, "put_single: mask=0x%x, changed=%d, " | ||
2388 | "mixer-value=%ld, mm-value=0x%x\n", | ||
2389 | mask, changed, ucontrol->value.integer.value[0], | ||
2390 | dbri->mm.data[elem & 3]); | ||
2391 | |||
2392 | if (changed) { | ||
2393 | /* First mute outputs, and wait 1/8000 sec (125 us) | ||
2394 | * to make sure this takes. This avoids clicking noises. | ||
2395 | */ | ||
2396 | spin_lock_irqsave(&dbri->lock, flags); | ||
2397 | |||
2398 | cs4215_setdata(dbri, 1); | ||
2399 | udelay(125); | ||
2400 | cs4215_setdata(dbri, 0); | ||
2401 | |||
2402 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
2403 | } | ||
2404 | return changed; | ||
2405 | } | ||
2406 | |||
2407 | /* Entries 0-3 map to the 4 data timeslots, entries 4-7 map to the 4 control | ||
2408 | timeslots. Shift is the bit offset in the timeslot, mask defines the | ||
2409 | number of bits. invert is a boolean for use with attenuation. | ||
2410 | */ | ||
2411 | #define CS4215_SINGLE(xname, entry, shift, mask, invert) \ | ||
2412 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
2413 | .info = snd_cs4215_info_single, \ | ||
2414 | .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \ | ||
2415 | .private_value = entry | (shift << 8) | (mask << 16) | (invert << 24) }, | ||
2416 | |||
2417 | static snd_kcontrol_new_t dbri_controls[] __devinitdata = { | ||
2418 | { | ||
2419 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2420 | .name = "Playback Volume", | ||
2421 | .info = snd_cs4215_info_volume, | ||
2422 | .get = snd_cs4215_get_volume, | ||
2423 | .put = snd_cs4215_put_volume, | ||
2424 | .private_value = DBRI_PLAY, | ||
2425 | }, | ||
2426 | CS4215_SINGLE("Headphone switch", 0, 7, 1, 0) | ||
2427 | CS4215_SINGLE("Line out switch", 0, 6, 1, 0) | ||
2428 | CS4215_SINGLE("Speaker switch", 1, 6, 1, 0) | ||
2429 | { | ||
2430 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2431 | .name = "Capture Volume", | ||
2432 | .info = snd_cs4215_info_volume, | ||
2433 | .get = snd_cs4215_get_volume, | ||
2434 | .put = snd_cs4215_put_volume, | ||
2435 | .private_value = DBRI_REC, | ||
2436 | }, | ||
2437 | /* FIXME: mic/line switch */ | ||
2438 | CS4215_SINGLE("Line in switch", 2, 4, 1, 0) | ||
2439 | CS4215_SINGLE("High Pass Filter switch", 5, 7, 1, 0) | ||
2440 | CS4215_SINGLE("Monitor Volume", 3, 4, 0xf, 1) | ||
2441 | CS4215_SINGLE("Mic boost", 4, 4, 1, 1) | ||
2442 | }; | ||
2443 | |||
2444 | #define NUM_CS4215_CONTROLS (sizeof(dbri_controls)/sizeof(snd_kcontrol_new_t)) | ||
2445 | |||
2446 | static int __init snd_dbri_mixer(snd_dbri_t * dbri) | ||
2447 | { | ||
2448 | snd_card_t *card; | ||
2449 | int idx, err; | ||
2450 | |||
2451 | snd_assert(dbri != NULL && dbri->card != NULL, return -EINVAL); | ||
2452 | |||
2453 | card = dbri->card; | ||
2454 | strcpy(card->mixername, card->shortname); | ||
2455 | |||
2456 | for (idx = 0; idx < NUM_CS4215_CONTROLS; idx++) { | ||
2457 | if ((err = snd_ctl_add(card, | ||
2458 | snd_ctl_new1(&dbri_controls[idx], | ||
2459 | dbri))) < 0) | ||
2460 | return err; | ||
2461 | } | ||
2462 | |||
2463 | for (idx = DBRI_REC; idx < DBRI_NO_STREAMS; idx++) { | ||
2464 | dbri->stream_info[idx].left_gain = 0; | ||
2465 | dbri->stream_info[idx].right_gain = 0; | ||
2466 | dbri->stream_info[idx].balance = DBRI_MID_BALANCE; | ||
2467 | } | ||
2468 | |||
2469 | return 0; | ||
2470 | } | ||
2471 | |||
2472 | /**************************************************************************** | ||
2473 | /proc interface | ||
2474 | ****************************************************************************/ | ||
2475 | static void dbri_regs_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer) | ||
2476 | { | ||
2477 | snd_dbri_t *dbri = entry->private_data; | ||
2478 | |||
2479 | snd_iprintf(buffer, "REG0: 0x%x\n", sbus_readl(dbri->regs + REG0)); | ||
2480 | snd_iprintf(buffer, "REG2: 0x%x\n", sbus_readl(dbri->regs + REG2)); | ||
2481 | snd_iprintf(buffer, "REG8: 0x%x\n", sbus_readl(dbri->regs + REG8)); | ||
2482 | snd_iprintf(buffer, "REG9: 0x%x\n", sbus_readl(dbri->regs + REG9)); | ||
2483 | } | ||
2484 | |||
2485 | #ifdef DBRI_DEBUG | ||
2486 | static void dbri_debug_read(snd_info_entry_t * entry, | ||
2487 | snd_info_buffer_t * buffer) | ||
2488 | { | ||
2489 | snd_dbri_t *dbri = entry->private_data; | ||
2490 | int pipe; | ||
2491 | snd_iprintf(buffer, "debug=%d\n", dbri_debug); | ||
2492 | |||
2493 | snd_iprintf(buffer, "CHI pipe in=%d, out=%d\n", | ||
2494 | dbri->chi_in_pipe, dbri->chi_out_pipe); | ||
2495 | for (pipe = 0; pipe < 32; pipe++) { | ||
2496 | if (pipe_active(dbri, pipe)) { | ||
2497 | struct dbri_pipe *pptr = &dbri->pipes[pipe]; | ||
2498 | snd_iprintf(buffer, | ||
2499 | "Pipe %d: %s SDP=0x%x desc=%d, " | ||
2500 | "len=%d @ %d prev: %d next %d\n", | ||
2501 | pipe, | ||
2502 | (pptr->direction == | ||
2503 | PIPEinput ? "input" : "output"), pptr->sdp, | ||
2504 | pptr->desc, pptr->length, pptr->cycle, | ||
2505 | pptr->prevpipe, pptr->nextpipe); | ||
2506 | } | ||
2507 | } | ||
2508 | } | ||
2509 | |||
2510 | static void dbri_debug_write(snd_info_entry_t * entry, | ||
2511 | snd_info_buffer_t * buffer) | ||
2512 | { | ||
2513 | char line[80]; | ||
2514 | int i; | ||
2515 | |||
2516 | if (snd_info_get_line(buffer, line, 80) == 0) { | ||
2517 | sscanf(line, "%d\n", &i); | ||
2518 | dbri_debug = i & 0x3f; | ||
2519 | } | ||
2520 | } | ||
2521 | #endif | ||
2522 | |||
2523 | void snd_dbri_proc(snd_dbri_t * dbri) | ||
2524 | { | ||
2525 | snd_info_entry_t *entry; | ||
2526 | int err; | ||
2527 | |||
2528 | err = snd_card_proc_new(dbri->card, "regs", &entry); | ||
2529 | snd_info_set_text_ops(entry, dbri, 1024, dbri_regs_read); | ||
2530 | |||
2531 | #ifdef DBRI_DEBUG | ||
2532 | err = snd_card_proc_new(dbri->card, "debug", &entry); | ||
2533 | snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read); | ||
2534 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; /* Writable for root */ | ||
2535 | entry->c.text.write_size = 256; | ||
2536 | entry->c.text.write = dbri_debug_write; | ||
2537 | #endif | ||
2538 | } | ||
2539 | |||
2540 | /* | ||
2541 | **************************************************************************** | ||
2542 | **************************** Initialization ******************************** | ||
2543 | **************************************************************************** | ||
2544 | */ | ||
2545 | static void snd_dbri_free(snd_dbri_t * dbri); | ||
2546 | |||
2547 | static int __init snd_dbri_create(snd_card_t * card, | ||
2548 | struct sbus_dev *sdev, | ||
2549 | struct linux_prom_irqs *irq, int dev) | ||
2550 | { | ||
2551 | snd_dbri_t *dbri = card->private_data; | ||
2552 | int err; | ||
2553 | |||
2554 | spin_lock_init(&dbri->lock); | ||
2555 | dbri->card = card; | ||
2556 | dbri->sdev = sdev; | ||
2557 | dbri->irq = irq->pri; | ||
2558 | dbri->dbri_version = sdev->prom_name[9]; | ||
2559 | |||
2560 | dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), | ||
2561 | &dbri->dma_dvma); | ||
2562 | memset((void *)dbri->dma, 0, sizeof(struct dbri_dma)); | ||
2563 | |||
2564 | dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n", | ||
2565 | dbri->dma, dbri->dma_dvma); | ||
2566 | |||
2567 | /* Map the registers into memory. */ | ||
2568 | dbri->regs_size = sdev->reg_addrs[0].reg_size; | ||
2569 | dbri->regs = sbus_ioremap(&sdev->resource[0], 0, | ||
2570 | dbri->regs_size, "DBRI Registers"); | ||
2571 | if (!dbri->regs) { | ||
2572 | printk(KERN_ERR "DBRI: could not allocate registers\n"); | ||
2573 | sbus_free_consistent(sdev, sizeof(struct dbri_dma), | ||
2574 | (void *)dbri->dma, dbri->dma_dvma); | ||
2575 | return -EIO; | ||
2576 | } | ||
2577 | |||
2578 | err = request_irq(dbri->irq, snd_dbri_interrupt, SA_SHIRQ, | ||
2579 | "DBRI audio", dbri); | ||
2580 | if (err) { | ||
2581 | printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq); | ||
2582 | sbus_iounmap(dbri->regs, dbri->regs_size); | ||
2583 | sbus_free_consistent(sdev, sizeof(struct dbri_dma), | ||
2584 | (void *)dbri->dma, dbri->dma_dvma); | ||
2585 | return err; | ||
2586 | } | ||
2587 | |||
2588 | /* Do low level initialization of the DBRI and CS4215 chips */ | ||
2589 | dbri_initialize(dbri); | ||
2590 | err = cs4215_init(dbri); | ||
2591 | if (err) { | ||
2592 | snd_dbri_free(dbri); | ||
2593 | return err; | ||
2594 | } | ||
2595 | |||
2596 | dbri->next = dbri_list; | ||
2597 | dbri_list = dbri; | ||
2598 | |||
2599 | return 0; | ||
2600 | } | ||
2601 | |||
2602 | static void snd_dbri_free(snd_dbri_t * dbri) | ||
2603 | { | ||
2604 | dprintk(D_GEN, "snd_dbri_free\n"); | ||
2605 | dbri_reset(dbri); | ||
2606 | |||
2607 | if (dbri->irq) | ||
2608 | free_irq(dbri->irq, dbri); | ||
2609 | |||
2610 | if (dbri->regs) | ||
2611 | sbus_iounmap(dbri->regs, dbri->regs_size); | ||
2612 | |||
2613 | if (dbri->dma) | ||
2614 | sbus_free_consistent(dbri->sdev, sizeof(struct dbri_dma), | ||
2615 | (void *)dbri->dma, dbri->dma_dvma); | ||
2616 | } | ||
2617 | |||
2618 | static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) | ||
2619 | { | ||
2620 | snd_dbri_t *dbri; | ||
2621 | struct linux_prom_irqs irq; | ||
2622 | struct resource *rp; | ||
2623 | snd_card_t *card; | ||
2624 | static int dev = 0; | ||
2625 | int err; | ||
2626 | |||
2627 | if (sdev->prom_name[9] < 'e') { | ||
2628 | printk(KERN_ERR "DBRI: unsupported chip version %c found.\n", | ||
2629 | sdev->prom_name[9]); | ||
2630 | return -EIO; | ||
2631 | } | ||
2632 | |||
2633 | if (dev >= SNDRV_CARDS) | ||
2634 | return -ENODEV; | ||
2635 | if (!enable[dev]) { | ||
2636 | dev++; | ||
2637 | return -ENOENT; | ||
2638 | } | ||
2639 | |||
2640 | prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq)); | ||
2641 | |||
2642 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | ||
2643 | sizeof(snd_dbri_t)); | ||
2644 | if (card == NULL) | ||
2645 | return -ENOMEM; | ||
2646 | |||
2647 | strcpy(card->driver, "DBRI"); | ||
2648 | strcpy(card->shortname, "Sun DBRI"); | ||
2649 | rp = &sdev->resource[0]; | ||
2650 | sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s", | ||
2651 | card->shortname, | ||
2652 | rp->flags & 0xffL, rp->start, __irq_itoa(irq.pri)); | ||
2653 | |||
2654 | if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) { | ||
2655 | snd_card_free(card); | ||
2656 | return err; | ||
2657 | } | ||
2658 | |||
2659 | dbri = (snd_dbri_t *) card->private_data; | ||
2660 | if ((err = snd_dbri_pcm(dbri)) < 0) { | ||
2661 | snd_dbri_free(dbri); | ||
2662 | snd_card_free(card); | ||
2663 | return err; | ||
2664 | } | ||
2665 | |||
2666 | if ((err = snd_dbri_mixer(dbri)) < 0) { | ||
2667 | snd_dbri_free(dbri); | ||
2668 | snd_card_free(card); | ||
2669 | return err; | ||
2670 | } | ||
2671 | |||
2672 | /* /proc file handling */ | ||
2673 | snd_dbri_proc(dbri); | ||
2674 | |||
2675 | if ((err = snd_card_register(card)) < 0) { | ||
2676 | snd_dbri_free(dbri); | ||
2677 | snd_card_free(card); | ||
2678 | return err; | ||
2679 | } | ||
2680 | |||
2681 | printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n", | ||
2682 | dev, dbri->regs, | ||
2683 | dbri->irq, dbri->dbri_version, dbri->mm.version); | ||
2684 | dev++; | ||
2685 | |||
2686 | return 0; | ||
2687 | } | ||
2688 | |||
2689 | /* Probe for the dbri chip and then attach the driver. */ | ||
2690 | static int __init dbri_init(void) | ||
2691 | { | ||
2692 | struct sbus_bus *sbus; | ||
2693 | struct sbus_dev *sdev; | ||
2694 | int found = 0; | ||
2695 | |||
2696 | /* Probe each SBUS for the DBRI chip(s). */ | ||
2697 | for_all_sbusdev(sdev, sbus) { | ||
2698 | /* | ||
2699 | * The version is coded in the last character | ||
2700 | */ | ||
2701 | if (!strncmp(sdev->prom_name, "SUNW,DBRI", 9)) { | ||
2702 | dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", | ||
2703 | sdev->prom_name, sdev->slot); | ||
2704 | |||
2705 | if (dbri_attach(sdev->prom_node, sdev) == 0) | ||
2706 | found++; | ||
2707 | } | ||
2708 | } | ||
2709 | |||
2710 | return (found > 0) ? 0 : -EIO; | ||
2711 | } | ||
2712 | |||
2713 | static void __exit dbri_exit(void) | ||
2714 | { | ||
2715 | snd_dbri_t *this = dbri_list; | ||
2716 | |||
2717 | while (this != NULL) { | ||
2718 | snd_dbri_t *next = this->next; | ||
2719 | snd_card_t *card = this->card; | ||
2720 | |||
2721 | snd_dbri_free(this); | ||
2722 | snd_card_free(card); | ||
2723 | this = next; | ||
2724 | } | ||
2725 | dbri_list = NULL; | ||
2726 | } | ||
2727 | |||
2728 | module_init(dbri_init); | ||
2729 | module_exit(dbri_exit); | ||
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index 16f3b461627a..60d0b2c66698 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/string.h> | ||
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <sound/emux_synth.h> | 27 | #include <sound/emux_synth.h> |
27 | #include <linux/init.h> | 28 | #include <linux/init.h> |
@@ -76,7 +77,7 @@ int snd_emux_register(snd_emux_t *emu, snd_card_t *card, int index, char *name) | |||
76 | snd_assert(name != NULL, return -EINVAL); | 77 | snd_assert(name != NULL, return -EINVAL); |
77 | 78 | ||
78 | emu->card = card; | 79 | emu->card = card; |
79 | emu->name = snd_kmalloc_strdup(name, GFP_KERNEL); | 80 | emu->name = kstrdup(name, GFP_KERNEL); |
80 | emu->voices = kcalloc(emu->max_voices, sizeof(snd_emux_voice_t), GFP_KERNEL); | 81 | emu->voices = kcalloc(emu->max_voices, sizeof(snd_emux_voice_t), GFP_KERNEL); |
81 | if (emu->voices == NULL) | 82 | if (emu->voices == NULL) |
82 | return -ENOMEM; | 83 | return -ENOMEM; |
diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c index ec3fc1ba7fca..4764940f11a0 100644 --- a/sound/synth/emux/emux_effect.c +++ b/sound/synth/emux/emux_effect.c | |||
@@ -291,10 +291,8 @@ snd_emux_create_effect(snd_emux_port_t *p) | |||
291 | void | 291 | void |
292 | snd_emux_delete_effect(snd_emux_port_t *p) | 292 | snd_emux_delete_effect(snd_emux_port_t *p) |
293 | { | 293 | { |
294 | if (p->effect) { | 294 | kfree(p->effect); |
295 | kfree(p->effect); | 295 | p->effect = NULL; |
296 | p->effect = NULL; | ||
297 | } | ||
298 | } | 296 | } |
299 | 297 | ||
300 | void | 298 | void |
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 9329e992c841..f05d02f5b69f 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -6,6 +6,7 @@ menu "USB devices" | |||
6 | config SND_USB_AUDIO | 6 | config SND_USB_AUDIO |
7 | tristate "USB Audio/MIDI driver" | 7 | tristate "USB Audio/MIDI driver" |
8 | depends on SND && USB | 8 | depends on SND && USB |
9 | select SND_HWDEP | ||
9 | select SND_RAWMIDI | 10 | select SND_RAWMIDI |
10 | select SND_PCM | 11 | select SND_PCM |
11 | help | 12 | help |
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 84b0bbddbd22..8298c462c291 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -98,7 +98,7 @@ MODULE_PARM_DESC(async_unlink, "Use async unlink mode."); | |||
98 | #define MAX_PACKS 10 | 98 | #define MAX_PACKS 10 |
99 | #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ | 99 | #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ |
100 | #define MAX_URBS 5 /* max. 20ms long packets */ | 100 | #define MAX_URBS 5 /* max. 20ms long packets */ |
101 | #define SYNC_URBS 2 /* always two urbs for sync */ | 101 | #define SYNC_URBS 4 /* always four urbs for sync */ |
102 | #define MIN_PACKS_URB 1 /* minimum 1 packet per urb */ | 102 | #define MIN_PACKS_URB 1 /* minimum 1 packet per urb */ |
103 | 103 | ||
104 | typedef struct snd_usb_substream snd_usb_substream_t; | 104 | typedef struct snd_usb_substream snd_usb_substream_t; |
@@ -153,6 +153,7 @@ struct snd_usb_substream { | |||
153 | unsigned int format; /* USB data format */ | 153 | unsigned int format; /* USB data format */ |
154 | unsigned int datapipe; /* the data i/o pipe */ | 154 | unsigned int datapipe; /* the data i/o pipe */ |
155 | unsigned int syncpipe; /* 1 - async out or adaptive in */ | 155 | unsigned int syncpipe; /* 1 - async out or adaptive in */ |
156 | unsigned int datainterval; /* log_2 of data packet interval */ | ||
156 | unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ | 157 | unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ |
157 | unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */ | 158 | unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */ |
158 | unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */ | 159 | unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */ |
@@ -177,7 +178,7 @@ struct snd_usb_substream { | |||
177 | unsigned int nurbs; /* # urbs */ | 178 | unsigned int nurbs; /* # urbs */ |
178 | snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */ | 179 | snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */ |
179 | snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */ | 180 | snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */ |
180 | char syncbuf[SYNC_URBS * MAX_PACKS * 4]; /* sync buffer; it's so small - let's get static */ | 181 | char syncbuf[SYNC_URBS * 4]; /* sync buffer; it's so small - let's get static */ |
181 | char *tmpbuf; /* temporary buffer for playback */ | 182 | char *tmpbuf; /* temporary buffer for playback */ |
182 | 183 | ||
183 | u64 formats; /* format bitmasks (all or'ed) */ | 184 | u64 formats; /* format bitmasks (all or'ed) */ |
@@ -212,7 +213,7 @@ static snd_usb_audio_t *usb_chip[SNDRV_CARDS]; | |||
212 | * convert a sampling rate into our full speed format (fs/1000 in Q16.16) | 213 | * convert a sampling rate into our full speed format (fs/1000 in Q16.16) |
213 | * this will overflow at approx 524 kHz | 214 | * this will overflow at approx 524 kHz |
214 | */ | 215 | */ |
215 | inline static unsigned get_usb_full_speed_rate(unsigned int rate) | 216 | static inline unsigned get_usb_full_speed_rate(unsigned int rate) |
216 | { | 217 | { |
217 | return ((rate << 13) + 62) / 125; | 218 | return ((rate << 13) + 62) / 125; |
218 | } | 219 | } |
@@ -221,19 +222,19 @@ inline static unsigned get_usb_full_speed_rate(unsigned int rate) | |||
221 | * convert a sampling rate into USB high speed format (fs/8000 in Q16.16) | 222 | * convert a sampling rate into USB high speed format (fs/8000 in Q16.16) |
222 | * this will overflow at approx 4 MHz | 223 | * this will overflow at approx 4 MHz |
223 | */ | 224 | */ |
224 | inline static unsigned get_usb_high_speed_rate(unsigned int rate) | 225 | static inline unsigned get_usb_high_speed_rate(unsigned int rate) |
225 | { | 226 | { |
226 | return ((rate << 10) + 62) / 125; | 227 | return ((rate << 10) + 62) / 125; |
227 | } | 228 | } |
228 | 229 | ||
229 | /* convert our full speed USB rate into sampling rate in Hz */ | 230 | /* convert our full speed USB rate into sampling rate in Hz */ |
230 | inline static unsigned get_full_speed_hz(unsigned int usb_rate) | 231 | static inline unsigned get_full_speed_hz(unsigned int usb_rate) |
231 | { | 232 | { |
232 | return (usb_rate * 125 + (1 << 12)) >> 13; | 233 | return (usb_rate * 125 + (1 << 12)) >> 13; |
233 | } | 234 | } |
234 | 235 | ||
235 | /* convert our high speed USB rate into sampling rate in Hz */ | 236 | /* convert our high speed USB rate into sampling rate in Hz */ |
236 | inline static unsigned get_high_speed_hz(unsigned int usb_rate) | 237 | static inline unsigned get_high_speed_hz(unsigned int usb_rate) |
237 | { | 238 | { |
238 | return (usb_rate * 125 + (1 << 9)) >> 10; | 239 | return (usb_rate * 125 + (1 << 9)) >> 10; |
239 | } | 240 | } |
@@ -251,17 +252,13 @@ static int prepare_capture_sync_urb(snd_usb_substream_t *subs, | |||
251 | { | 252 | { |
252 | unsigned char *cp = urb->transfer_buffer; | 253 | unsigned char *cp = urb->transfer_buffer; |
253 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | 254 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; |
254 | int i, offs; | ||
255 | 255 | ||
256 | urb->number_of_packets = ctx->packets; | ||
257 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 256 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
258 | for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) { | 257 | urb->iso_frame_desc[0].length = 3; |
259 | urb->iso_frame_desc[i].length = 3; | 258 | urb->iso_frame_desc[0].offset = 0; |
260 | urb->iso_frame_desc[i].offset = offs; | 259 | cp[0] = subs->freqn >> 2; |
261 | cp[0] = subs->freqn >> 2; | 260 | cp[1] = subs->freqn >> 10; |
262 | cp[1] = subs->freqn >> 10; | 261 | cp[2] = subs->freqn >> 18; |
263 | cp[2] = subs->freqn >> 18; | ||
264 | } | ||
265 | return 0; | 262 | return 0; |
266 | } | 263 | } |
267 | 264 | ||
@@ -277,18 +274,14 @@ static int prepare_capture_sync_urb_hs(snd_usb_substream_t *subs, | |||
277 | { | 274 | { |
278 | unsigned char *cp = urb->transfer_buffer; | 275 | unsigned char *cp = urb->transfer_buffer; |
279 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | 276 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; |
280 | int i, offs; | ||
281 | 277 | ||
282 | urb->number_of_packets = ctx->packets; | ||
283 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 278 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
284 | for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) { | 279 | urb->iso_frame_desc[0].length = 4; |
285 | urb->iso_frame_desc[i].length = 4; | 280 | urb->iso_frame_desc[0].offset = 0; |
286 | urb->iso_frame_desc[i].offset = offs; | 281 | cp[0] = subs->freqn; |
287 | cp[0] = subs->freqn; | 282 | cp[1] = subs->freqn >> 8; |
288 | cp[1] = subs->freqn >> 8; | 283 | cp[2] = subs->freqn >> 16; |
289 | cp[2] = subs->freqn >> 16; | 284 | cp[3] = subs->freqn >> 24; |
290 | cp[3] = subs->freqn >> 24; | ||
291 | } | ||
292 | return 0; | 285 | return 0; |
293 | } | 286 | } |
294 | 287 | ||
@@ -418,15 +411,11 @@ static int prepare_playback_sync_urb(snd_usb_substream_t *subs, | |||
418 | snd_pcm_runtime_t *runtime, | 411 | snd_pcm_runtime_t *runtime, |
419 | struct urb *urb) | 412 | struct urb *urb) |
420 | { | 413 | { |
421 | int i, offs; | ||
422 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | 414 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; |
423 | 415 | ||
424 | urb->number_of_packets = ctx->packets; | ||
425 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 416 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
426 | for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) { | 417 | urb->iso_frame_desc[0].length = 3; |
427 | urb->iso_frame_desc[i].length = 3; | 418 | urb->iso_frame_desc[0].offset = 0; |
428 | urb->iso_frame_desc[i].offset = offs; | ||
429 | } | ||
430 | return 0; | 419 | return 0; |
431 | } | 420 | } |
432 | 421 | ||
@@ -440,15 +429,11 @@ static int prepare_playback_sync_urb_hs(snd_usb_substream_t *subs, | |||
440 | snd_pcm_runtime_t *runtime, | 429 | snd_pcm_runtime_t *runtime, |
441 | struct urb *urb) | 430 | struct urb *urb) |
442 | { | 431 | { |
443 | int i, offs; | ||
444 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | 432 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; |
445 | 433 | ||
446 | urb->number_of_packets = ctx->packets; | ||
447 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 434 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ |
448 | for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) { | 435 | urb->iso_frame_desc[0].length = 4; |
449 | urb->iso_frame_desc[i].length = 4; | 436 | urb->iso_frame_desc[0].offset = 0; |
450 | urb->iso_frame_desc[i].offset = offs; | ||
451 | } | ||
452 | return 0; | 437 | return 0; |
453 | } | 438 | } |
454 | 439 | ||
@@ -462,31 +447,17 @@ static int retire_playback_sync_urb(snd_usb_substream_t *subs, | |||
462 | snd_pcm_runtime_t *runtime, | 447 | snd_pcm_runtime_t *runtime, |
463 | struct urb *urb) | 448 | struct urb *urb) |
464 | { | 449 | { |
465 | int i; | 450 | unsigned int f; |
466 | unsigned int f, found; | ||
467 | unsigned char *cp = urb->transfer_buffer; | ||
468 | unsigned long flags; | 451 | unsigned long flags; |
469 | 452 | ||
470 | found = 0; | 453 | if (urb->iso_frame_desc[0].status == 0 && |
471 | for (i = 0; i < urb->number_of_packets; i++, cp += 4) { | 454 | urb->iso_frame_desc[0].actual_length == 3) { |
472 | if (urb->iso_frame_desc[i].status || | 455 | f = combine_triple((u8*)urb->transfer_buffer) << 2; |
473 | urb->iso_frame_desc[i].actual_length < 3) | 456 | if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) { |
474 | continue; | 457 | spin_lock_irqsave(&subs->lock, flags); |
475 | f = combine_triple(cp) << 2; | 458 | subs->freqm = f; |
476 | #if 0 | 459 | spin_unlock_irqrestore(&subs->lock, flags); |
477 | if (f < subs->freqn - (subs->freqn>>3) || f > subs->freqmax) { | ||
478 | snd_printd(KERN_WARNING "requested frequency %d (%u,%03uHz) out of range (current nominal %d (%u,%03uHz))\n", | ||
479 | f, f >> 14, (f & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1), | ||
480 | subs->freqn, subs->freqn >> 14, (subs->freqn & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1)); | ||
481 | continue; | ||
482 | } | 460 | } |
483 | #endif | ||
484 | found = f; | ||
485 | } | ||
486 | if (found) { | ||
487 | spin_lock_irqsave(&subs->lock, flags); | ||
488 | subs->freqm = found; | ||
489 | spin_unlock_irqrestore(&subs->lock, flags); | ||
490 | } | 461 | } |
491 | 462 | ||
492 | return 0; | 463 | return 0; |
@@ -502,22 +473,17 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs, | |||
502 | snd_pcm_runtime_t *runtime, | 473 | snd_pcm_runtime_t *runtime, |
503 | struct urb *urb) | 474 | struct urb *urb) |
504 | { | 475 | { |
505 | int i; | 476 | unsigned int f; |
506 | unsigned int found; | ||
507 | unsigned char *cp = urb->transfer_buffer; | ||
508 | unsigned long flags; | 477 | unsigned long flags; |
509 | 478 | ||
510 | found = 0; | 479 | if (urb->iso_frame_desc[0].status == 0 && |
511 | for (i = 0; i < urb->number_of_packets; i++, cp += 4) { | 480 | urb->iso_frame_desc[0].actual_length == 4) { |
512 | if (urb->iso_frame_desc[i].status || | 481 | f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff; |
513 | urb->iso_frame_desc[i].actual_length < 4) | 482 | if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) { |
514 | continue; | 483 | spin_lock_irqsave(&subs->lock, flags); |
515 | found = combine_quad(cp) & 0x0fffffff; | 484 | subs->freqm = f; |
516 | } | 485 | spin_unlock_irqrestore(&subs->lock, flags); |
517 | if (found) { | 486 | } |
518 | spin_lock_irqsave(&subs->lock, flags); | ||
519 | subs->freqm = found; | ||
520 | spin_unlock_irqrestore(&subs->lock, flags); | ||
521 | } | 487 | } |
522 | 488 | ||
523 | return 0; | 489 | return 0; |
@@ -553,7 +519,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs, | |||
553 | if (subs->fill_max) | 519 | if (subs->fill_max) |
554 | counts = subs->maxframesize; /* fixed */ | 520 | counts = subs->maxframesize; /* fixed */ |
555 | else { | 521 | else { |
556 | subs->phase = (subs->phase & 0xffff) + subs->freqm; | 522 | subs->phase = (subs->phase & 0xffff) |
523 | + (subs->freqm << subs->datainterval); | ||
557 | counts = subs->phase >> 16; | 524 | counts = subs->phase >> 16; |
558 | if (counts > subs->maxframesize) | 525 | if (counts > subs->maxframesize) |
559 | counts = subs->maxframesize; | 526 | counts = subs->maxframesize; |
@@ -600,6 +567,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs, | |||
600 | /* set the buffer pointer */ | 567 | /* set the buffer pointer */ |
601 | urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride; | 568 | urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride; |
602 | subs->hwptr += offs; | 569 | subs->hwptr += offs; |
570 | if (subs->hwptr == runtime->buffer_size) | ||
571 | subs->hwptr = 0; | ||
603 | } | 572 | } |
604 | spin_unlock_irqrestore(&subs->lock, flags); | 573 | spin_unlock_irqrestore(&subs->lock, flags); |
605 | urb->transfer_buffer_length = offs * stride; | 574 | urb->transfer_buffer_length = offs * stride; |
@@ -823,7 +792,7 @@ static int start_urbs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime) | |||
823 | */ | 792 | */ |
824 | static int wait_clear_urbs(snd_usb_substream_t *subs) | 793 | static int wait_clear_urbs(snd_usb_substream_t *subs) |
825 | { | 794 | { |
826 | int timeout = HZ; | 795 | unsigned long end_time = jiffies + msecs_to_jiffies(1000); |
827 | unsigned int i; | 796 | unsigned int i; |
828 | int alive; | 797 | int alive; |
829 | 798 | ||
@@ -843,7 +812,7 @@ static int wait_clear_urbs(snd_usb_substream_t *subs) | |||
843 | break; | 812 | break; |
844 | set_current_state(TASK_UNINTERRUPTIBLE); | 813 | set_current_state(TASK_UNINTERRUPTIBLE); |
845 | schedule_timeout(1); | 814 | schedule_timeout(1); |
846 | } while (--timeout > 0); | 815 | } while (time_before(jiffies, end_time)); |
847 | if (alive) | 816 | if (alive) |
848 | snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); | 817 | snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); |
849 | return 0; | 818 | return 0; |
@@ -892,10 +861,8 @@ static void release_urb_ctx(snd_urb_ctx_t *u) | |||
892 | usb_free_urb(u->urb); | 861 | usb_free_urb(u->urb); |
893 | u->urb = NULL; | 862 | u->urb = NULL; |
894 | } | 863 | } |
895 | if (u->buf) { | 864 | kfree(u->buf); |
896 | kfree(u->buf); | 865 | u->buf = NULL; |
897 | u->buf = NULL; | ||
898 | } | ||
899 | } | 866 | } |
900 | 867 | ||
901 | /* | 868 | /* |
@@ -913,10 +880,8 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force) | |||
913 | release_urb_ctx(&subs->dataurb[i]); | 880 | release_urb_ctx(&subs->dataurb[i]); |
914 | for (i = 0; i < SYNC_URBS; i++) | 881 | for (i = 0; i < SYNC_URBS; i++) |
915 | release_urb_ctx(&subs->syncurb[i]); | 882 | release_urb_ctx(&subs->syncurb[i]); |
916 | if (subs->tmpbuf) { | 883 | kfree(subs->tmpbuf); |
917 | kfree(subs->tmpbuf); | 884 | subs->tmpbuf = NULL; |
918 | subs->tmpbuf = NULL; | ||
919 | } | ||
920 | subs->nurbs = 0; | 885 | subs->nurbs = 0; |
921 | } | 886 | } |
922 | 887 | ||
@@ -936,16 +901,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
936 | else | 901 | else |
937 | subs->freqn = get_usb_high_speed_rate(rate); | 902 | subs->freqn = get_usb_high_speed_rate(rate); |
938 | subs->freqm = subs->freqn; | 903 | subs->freqm = subs->freqn; |
939 | subs->freqmax = subs->freqn + (subs->freqn >> 2); /* max. allowed frequency */ | 904 | /* calculate max. frequency */ |
940 | subs->phase = 0; | 905 | if (subs->maxpacksize) { |
941 | 906 | /* whatever fits into a max. size packet */ | |
942 | /* calculate the max. size of packet */ | ||
943 | maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) >> 16; | ||
944 | if (subs->maxpacksize && maxsize > subs->maxpacksize) { | ||
945 | //snd_printd(KERN_DEBUG "maxsize %d is greater than defined size %d\n", | ||
946 | // maxsize, subs->maxpacksize); | ||
947 | maxsize = subs->maxpacksize; | 907 | maxsize = subs->maxpacksize; |
908 | subs->freqmax = (maxsize / (frame_bits >> 3)) | ||
909 | << (16 - subs->datainterval); | ||
910 | } else { | ||
911 | /* no max. packet size: just take 25% higher than nominal */ | ||
912 | subs->freqmax = subs->freqn + (subs->freqn >> 2); | ||
913 | maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) | ||
914 | >> (16 - subs->datainterval); | ||
948 | } | 915 | } |
916 | subs->phase = 0; | ||
949 | 917 | ||
950 | if (subs->fill_max) | 918 | if (subs->fill_max) |
951 | subs->curpacksize = subs->maxpacksize; | 919 | subs->curpacksize = subs->maxpacksize; |
@@ -955,7 +923,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
955 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 923 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) |
956 | urb_packs = nrpacks; | 924 | urb_packs = nrpacks; |
957 | else | 925 | else |
958 | urb_packs = nrpacks * 8; | 926 | urb_packs = (nrpacks * 8) >> subs->datainterval; |
959 | 927 | ||
960 | /* allocate a temporary buffer for playback */ | 928 | /* allocate a temporary buffer for playback */ |
961 | if (is_playback) { | 929 | if (is_playback) { |
@@ -1028,7 +996,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
1028 | u->urb->pipe = subs->datapipe; | 996 | u->urb->pipe = subs->datapipe; |
1029 | u->urb->transfer_flags = URB_ISO_ASAP; | 997 | u->urb->transfer_flags = URB_ISO_ASAP; |
1030 | u->urb->number_of_packets = u->packets; | 998 | u->urb->number_of_packets = u->packets; |
1031 | u->urb->interval = 1; | 999 | u->urb->interval = 1 << subs->datainterval; |
1032 | u->urb->context = u; | 1000 | u->urb->context = u; |
1033 | u->urb->complete = snd_usb_complete_callback(snd_complete_urb); | 1001 | u->urb->complete = snd_usb_complete_callback(snd_complete_urb); |
1034 | } | 1002 | } |
@@ -1039,22 +1007,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
1039 | snd_urb_ctx_t *u = &subs->syncurb[i]; | 1007 | snd_urb_ctx_t *u = &subs->syncurb[i]; |
1040 | u->index = i; | 1008 | u->index = i; |
1041 | u->subs = subs; | 1009 | u->subs = subs; |
1042 | u->packets = nrpacks; | 1010 | u->packets = 1; |
1043 | u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); | 1011 | u->urb = usb_alloc_urb(1, GFP_KERNEL); |
1044 | if (! u->urb) { | 1012 | if (! u->urb) { |
1045 | release_substream_urbs(subs, 0); | 1013 | release_substream_urbs(subs, 0); |
1046 | return -ENOMEM; | 1014 | return -ENOMEM; |
1047 | } | 1015 | } |
1048 | u->urb->transfer_buffer = subs->syncbuf + i * nrpacks * 4; | 1016 | u->urb->transfer_buffer = subs->syncbuf + i * 4; |
1049 | u->urb->transfer_buffer_length = nrpacks * 4; | 1017 | u->urb->transfer_buffer_length = 4; |
1050 | u->urb->dev = subs->dev; | 1018 | u->urb->dev = subs->dev; |
1051 | u->urb->pipe = subs->syncpipe; | 1019 | u->urb->pipe = subs->syncpipe; |
1052 | u->urb->transfer_flags = URB_ISO_ASAP; | 1020 | u->urb->transfer_flags = URB_ISO_ASAP; |
1053 | u->urb->number_of_packets = u->packets; | 1021 | u->urb->number_of_packets = 1; |
1054 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) | 1022 | u->urb->interval = 1 << subs->syncinterval; |
1055 | u->urb->interval = 8; | ||
1056 | else | ||
1057 | u->urb->interval = 1; | ||
1058 | u->urb->context = u; | 1023 | u->urb->context = u; |
1059 | u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb); | 1024 | u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb); |
1060 | } | 1025 | } |
@@ -1235,6 +1200,12 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt) | |||
1235 | subs->datapipe = usb_sndisocpipe(dev, ep); | 1200 | subs->datapipe = usb_sndisocpipe(dev, ep); |
1236 | else | 1201 | else |
1237 | subs->datapipe = usb_rcvisocpipe(dev, ep); | 1202 | subs->datapipe = usb_rcvisocpipe(dev, ep); |
1203 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH && | ||
1204 | get_endpoint(alts, 0)->bInterval >= 1 && | ||
1205 | get_endpoint(alts, 0)->bInterval <= 4) | ||
1206 | subs->datainterval = get_endpoint(alts, 0)->bInterval - 1; | ||
1207 | else | ||
1208 | subs->datainterval = 0; | ||
1238 | subs->syncpipe = subs->syncinterval = 0; | 1209 | subs->syncpipe = subs->syncinterval = 0; |
1239 | subs->maxpacksize = fmt->maxpacksize; | 1210 | subs->maxpacksize = fmt->maxpacksize; |
1240 | subs->fill_max = 0; | 1211 | subs->fill_max = 0; |
@@ -1272,7 +1243,17 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt) | |||
1272 | subs->syncpipe = usb_rcvisocpipe(dev, ep); | 1243 | subs->syncpipe = usb_rcvisocpipe(dev, ep); |
1273 | else | 1244 | else |
1274 | subs->syncpipe = usb_sndisocpipe(dev, ep); | 1245 | subs->syncpipe = usb_sndisocpipe(dev, ep); |
1275 | subs->syncinterval = get_endpoint(alts, 1)->bRefresh; | 1246 | if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && |
1247 | get_endpoint(alts, 1)->bRefresh >= 1 && | ||
1248 | get_endpoint(alts, 1)->bRefresh <= 9) | ||
1249 | subs->syncinterval = get_endpoint(alts, 1)->bRefresh; | ||
1250 | else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | ||
1251 | subs->syncinterval = 1; | ||
1252 | else if (get_endpoint(alts, 1)->bInterval >= 1 && | ||
1253 | get_endpoint(alts, 1)->bInterval <= 16) | ||
1254 | subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1; | ||
1255 | else | ||
1256 | subs->syncinterval = 3; | ||
1276 | } | 1257 | } |
1277 | 1258 | ||
1278 | /* always fill max packet size */ | 1259 | /* always fill max packet size */ |
@@ -1990,10 +1971,11 @@ static void proc_dump_substream_status(snd_usb_substream_t *subs, snd_info_buffe | |||
1990 | snd_iprintf(buffer, "%d ", subs->dataurb[i].packets); | 1971 | snd_iprintf(buffer, "%d ", subs->dataurb[i].packets); |
1991 | snd_iprintf(buffer, "]\n"); | 1972 | snd_iprintf(buffer, "]\n"); |
1992 | snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize); | 1973 | snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize); |
1993 | snd_iprintf(buffer, " Momentary freq = %u Hz\n", | 1974 | snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", |
1994 | snd_usb_get_speed(subs->dev) == USB_SPEED_FULL | 1975 | snd_usb_get_speed(subs->dev) == USB_SPEED_FULL |
1995 | ? get_full_speed_hz(subs->freqm) | 1976 | ? get_full_speed_hz(subs->freqm) |
1996 | : get_high_speed_hz(subs->freqm)); | 1977 | : get_high_speed_hz(subs->freqm), |
1978 | subs->freqm >> 16, subs->freqm & 0xffff); | ||
1997 | } else { | 1979 | } else { |
1998 | snd_iprintf(buffer, " Status: Stop\n"); | 1980 | snd_iprintf(buffer, " Status: Stop\n"); |
1999 | } | 1981 | } |
@@ -2183,17 +2165,15 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor | |||
2183 | /* | 2165 | /* |
2184 | * check if the device uses big-endian samples | 2166 | * check if the device uses big-endian samples |
2185 | */ | 2167 | */ |
2186 | static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp) | 2168 | static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp) |
2187 | { | 2169 | { |
2188 | /* M-Audio */ | 2170 | switch (chip->usb_id) { |
2189 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763) { | 2171 | case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */ |
2190 | /* Quattro: captured data only */ | 2172 | if (fp->endpoint & USB_DIR_IN) |
2191 | if (le16_to_cpu(dev->descriptor.idProduct) == 0x2001 && | ||
2192 | fp->endpoint & USB_DIR_IN) | ||
2193 | return 1; | ||
2194 | /* Audiophile USB */ | ||
2195 | if (le16_to_cpu(dev->descriptor.idProduct) == 0x2003) | ||
2196 | return 1; | 2173 | return 1; |
2174 | break; | ||
2175 | case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ | ||
2176 | return 1; | ||
2197 | } | 2177 | } |
2198 | return 0; | 2178 | return 0; |
2199 | } | 2179 | } |
@@ -2207,7 +2187,7 @@ static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp) | |||
2207 | * @format: the format tag (wFormatTag) | 2187 | * @format: the format tag (wFormatTag) |
2208 | * @fmt: the format type descriptor | 2188 | * @fmt: the format type descriptor |
2209 | */ | 2189 | */ |
2210 | static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat *fp, | 2190 | static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *fp, |
2211 | int format, unsigned char *fmt) | 2191 | int format, unsigned char *fmt) |
2212 | { | 2192 | { |
2213 | int pcm_format; | 2193 | int pcm_format; |
@@ -2220,12 +2200,12 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat | |||
2220 | switch (format) { | 2200 | switch (format) { |
2221 | case 0: /* some devices don't define this correctly... */ | 2201 | case 0: /* some devices don't define this correctly... */ |
2222 | snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n", | 2202 | snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n", |
2223 | dev->devnum, fp->iface, fp->altsetting); | 2203 | chip->dev->devnum, fp->iface, fp->altsetting); |
2224 | /* fall-through */ | 2204 | /* fall-through */ |
2225 | case USB_AUDIO_FORMAT_PCM: | 2205 | case USB_AUDIO_FORMAT_PCM: |
2226 | if (sample_width > sample_bytes * 8) { | 2206 | if (sample_width > sample_bytes * 8) { |
2227 | snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n", | 2207 | snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n", |
2228 | dev->devnum, fp->iface, fp->altsetting, | 2208 | chip->dev->devnum, fp->iface, fp->altsetting, |
2229 | sample_width, sample_bytes); | 2209 | sample_width, sample_bytes); |
2230 | } | 2210 | } |
2231 | /* check the format byte size */ | 2211 | /* check the format byte size */ |
@@ -2234,13 +2214,13 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat | |||
2234 | pcm_format = SNDRV_PCM_FORMAT_S8; | 2214 | pcm_format = SNDRV_PCM_FORMAT_S8; |
2235 | break; | 2215 | break; |
2236 | case 2: | 2216 | case 2: |
2237 | if (is_big_endian_format(dev, fp)) | 2217 | if (is_big_endian_format(chip, fp)) |
2238 | pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */ | 2218 | pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */ |
2239 | else | 2219 | else |
2240 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; | 2220 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; |
2241 | break; | 2221 | break; |
2242 | case 3: | 2222 | case 3: |
2243 | if (is_big_endian_format(dev, fp)) | 2223 | if (is_big_endian_format(chip, fp)) |
2244 | pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */ | 2224 | pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */ |
2245 | else | 2225 | else |
2246 | pcm_format = SNDRV_PCM_FORMAT_S24_3LE; | 2226 | pcm_format = SNDRV_PCM_FORMAT_S24_3LE; |
@@ -2250,14 +2230,14 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat | |||
2250 | break; | 2230 | break; |
2251 | default: | 2231 | default: |
2252 | snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n", | 2232 | snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n", |
2253 | dev->devnum, fp->iface, fp->altsetting, sample_width, sample_bytes); | 2233 | chip->dev->devnum, fp->iface, |
2234 | fp->altsetting, sample_width, sample_bytes); | ||
2254 | break; | 2235 | break; |
2255 | } | 2236 | } |
2256 | break; | 2237 | break; |
2257 | case USB_AUDIO_FORMAT_PCM8: | 2238 | case USB_AUDIO_FORMAT_PCM8: |
2258 | /* Dallas DS4201 workaround */ | 2239 | /* Dallas DS4201 workaround */ |
2259 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa && | 2240 | if (chip->usb_id == USB_ID(0x04fa, 0x4201)) |
2260 | le16_to_cpu(dev->descriptor.idProduct) == 0x4201) | ||
2261 | pcm_format = SNDRV_PCM_FORMAT_S8; | 2241 | pcm_format = SNDRV_PCM_FORMAT_S8; |
2262 | else | 2242 | else |
2263 | pcm_format = SNDRV_PCM_FORMAT_U8; | 2243 | pcm_format = SNDRV_PCM_FORMAT_U8; |
@@ -2273,7 +2253,7 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat | |||
2273 | break; | 2253 | break; |
2274 | default: | 2254 | default: |
2275 | snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n", | 2255 | snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n", |
2276 | dev->devnum, fp->iface, fp->altsetting, format); | 2256 | chip->dev->devnum, fp->iface, fp->altsetting, format); |
2277 | break; | 2257 | break; |
2278 | } | 2258 | } |
2279 | return pcm_format; | 2259 | return pcm_format; |
@@ -2290,13 +2270,13 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat | |||
2290 | * @offset: the start offset of descriptor pointing the rate type | 2270 | * @offset: the start offset of descriptor pointing the rate type |
2291 | * (7 for type I and II, 8 for type II) | 2271 | * (7 for type I and II, 8 for type II) |
2292 | */ | 2272 | */ |
2293 | static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *fp, | 2273 | static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *fp, |
2294 | unsigned char *fmt, int offset) | 2274 | unsigned char *fmt, int offset) |
2295 | { | 2275 | { |
2296 | int nr_rates = fmt[offset]; | 2276 | int nr_rates = fmt[offset]; |
2297 | if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { | 2277 | if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { |
2298 | snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", | 2278 | snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", |
2299 | dev->devnum, fp->iface, fp->altsetting); | 2279 | chip->dev->devnum, fp->iface, fp->altsetting); |
2300 | return -1; | 2280 | return -1; |
2301 | } | 2281 | } |
2302 | 2282 | ||
@@ -2343,7 +2323,7 @@ static int parse_audio_format_rates(struct usb_device *dev, struct audioformat * | |||
2343 | /* | 2323 | /* |
2344 | * parse the format type I and III descriptors | 2324 | * parse the format type I and III descriptors |
2345 | */ | 2325 | */ |
2346 | static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp, | 2326 | static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp, |
2347 | int format, unsigned char *fmt) | 2327 | int format, unsigned char *fmt) |
2348 | { | 2328 | { |
2349 | int pcm_format; | 2329 | int pcm_format; |
@@ -2355,7 +2335,7 @@ static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp, | |||
2355 | */ | 2335 | */ |
2356 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; | 2336 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; |
2357 | } else { | 2337 | } else { |
2358 | pcm_format = parse_audio_format_i_type(dev, fp, format, fmt); | 2338 | pcm_format = parse_audio_format_i_type(chip, fp, format, fmt); |
2359 | if (pcm_format < 0) | 2339 | if (pcm_format < 0) |
2360 | return -1; | 2340 | return -1; |
2361 | } | 2341 | } |
@@ -2363,16 +2343,16 @@ static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp, | |||
2363 | fp->channels = fmt[4]; | 2343 | fp->channels = fmt[4]; |
2364 | if (fp->channels < 1) { | 2344 | if (fp->channels < 1) { |
2365 | snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", | 2345 | snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", |
2366 | dev->devnum, fp->iface, fp->altsetting, fp->channels); | 2346 | chip->dev->devnum, fp->iface, fp->altsetting, fp->channels); |
2367 | return -1; | 2347 | return -1; |
2368 | } | 2348 | } |
2369 | return parse_audio_format_rates(dev, fp, fmt, 7); | 2349 | return parse_audio_format_rates(chip, fp, fmt, 7); |
2370 | } | 2350 | } |
2371 | 2351 | ||
2372 | /* | 2352 | /* |
2373 | * prase the format type II descriptor | 2353 | * prase the format type II descriptor |
2374 | */ | 2354 | */ |
2375 | static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp, | 2355 | static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp, |
2376 | int format, unsigned char *fmt) | 2356 | int format, unsigned char *fmt) |
2377 | { | 2357 | { |
2378 | int brate, framesize; | 2358 | int brate, framesize; |
@@ -2387,7 +2367,7 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp, | |||
2387 | break; | 2367 | break; |
2388 | default: | 2368 | default: |
2389 | snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected. processed as MPEG.\n", | 2369 | snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected. processed as MPEG.\n", |
2390 | dev->devnum, fp->iface, fp->altsetting, format); | 2370 | chip->dev->devnum, fp->iface, fp->altsetting, format); |
2391 | fp->format = SNDRV_PCM_FORMAT_MPEG; | 2371 | fp->format = SNDRV_PCM_FORMAT_MPEG; |
2392 | break; | 2372 | break; |
2393 | } | 2373 | } |
@@ -2396,10 +2376,10 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp, | |||
2396 | framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */ | 2376 | framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */ |
2397 | snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); | 2377 | snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); |
2398 | fp->frame_size = framesize; | 2378 | fp->frame_size = framesize; |
2399 | return parse_audio_format_rates(dev, fp, fmt, 8); /* fmt[8..] sample rates */ | 2379 | return parse_audio_format_rates(chip, fp, fmt, 8); /* fmt[8..] sample rates */ |
2400 | } | 2380 | } |
2401 | 2381 | ||
2402 | static int parse_audio_format(struct usb_device *dev, struct audioformat *fp, | 2382 | static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp, |
2403 | int format, unsigned char *fmt, int stream) | 2383 | int format, unsigned char *fmt, int stream) |
2404 | { | 2384 | { |
2405 | int err; | 2385 | int err; |
@@ -2407,30 +2387,30 @@ static int parse_audio_format(struct usb_device *dev, struct audioformat *fp, | |||
2407 | switch (fmt[3]) { | 2387 | switch (fmt[3]) { |
2408 | case USB_FORMAT_TYPE_I: | 2388 | case USB_FORMAT_TYPE_I: |
2409 | case USB_FORMAT_TYPE_III: | 2389 | case USB_FORMAT_TYPE_III: |
2410 | err = parse_audio_format_i(dev, fp, format, fmt); | 2390 | err = parse_audio_format_i(chip, fp, format, fmt); |
2411 | break; | 2391 | break; |
2412 | case USB_FORMAT_TYPE_II: | 2392 | case USB_FORMAT_TYPE_II: |
2413 | err = parse_audio_format_ii(dev, fp, format, fmt); | 2393 | err = parse_audio_format_ii(chip, fp, format, fmt); |
2414 | break; | 2394 | break; |
2415 | default: | 2395 | default: |
2416 | snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", | 2396 | snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", |
2417 | dev->devnum, fp->iface, fp->altsetting, fmt[3]); | 2397 | chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]); |
2418 | return -1; | 2398 | return -1; |
2419 | } | 2399 | } |
2420 | fp->fmt_type = fmt[3]; | 2400 | fp->fmt_type = fmt[3]; |
2421 | if (err < 0) | 2401 | if (err < 0) |
2422 | return err; | 2402 | return err; |
2423 | #if 1 | 2403 | #if 1 |
2424 | /* FIXME: temporary hack for extigy */ | 2404 | /* FIXME: temporary hack for extigy/audigy 2 nx */ |
2425 | /* extigy apparently supports sample rates other than 48k | 2405 | /* extigy apparently supports sample rates other than 48k |
2426 | * but not in ordinary way. so we enable only 48k atm. | 2406 | * but not in ordinary way. so we enable only 48k atm. |
2427 | */ | 2407 | */ |
2428 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && | 2408 | if (chip->usb_id == USB_ID(0x041e, 0x3000) || |
2429 | le16_to_cpu(dev->descriptor.idProduct) == 0x3000) { | 2409 | chip->usb_id == USB_ID(0x041e, 0x3020)) { |
2430 | if (fmt[3] == USB_FORMAT_TYPE_I && | 2410 | if (fmt[3] == USB_FORMAT_TYPE_I && |
2431 | stream == SNDRV_PCM_STREAM_PLAYBACK && | 2411 | fp->rates != SNDRV_PCM_RATE_48000 && |
2432 | fp->rates != SNDRV_PCM_RATE_48000) | 2412 | fp->rates != SNDRV_PCM_RATE_96000) |
2433 | return -1; /* use 48k only */ | 2413 | return -1; |
2434 | } | 2414 | } |
2435 | #endif | 2415 | #endif |
2436 | return 0; | 2416 | return 0; |
@@ -2522,46 +2502,43 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) | |||
2522 | fp->altset_idx = i; | 2502 | fp->altset_idx = i; |
2523 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; | 2503 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; |
2524 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; | 2504 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; |
2525 | /* FIXME: decode wMaxPacketSize of high bandwith endpoints */ | ||
2526 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); | 2505 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); |
2506 | if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) | ||
2507 | fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) | ||
2508 | * (fp->maxpacksize & 0x7ff); | ||
2527 | fp->attributes = csep[3]; | 2509 | fp->attributes = csep[3]; |
2528 | 2510 | ||
2529 | /* some quirks for attributes here */ | 2511 | /* some quirks for attributes here */ |
2530 | 2512 | ||
2531 | /* workaround for AudioTrak Optoplay */ | 2513 | switch (chip->usb_id) { |
2532 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x0a92 && | 2514 | case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */ |
2533 | le16_to_cpu(dev->descriptor.idProduct) == 0x0053) { | ||
2534 | /* Optoplay sets the sample rate attribute although | 2515 | /* Optoplay sets the sample rate attribute although |
2535 | * it seems not supporting it in fact. | 2516 | * it seems not supporting it in fact. |
2536 | */ | 2517 | */ |
2537 | fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE; | 2518 | fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE; |
2538 | } | 2519 | break; |
2539 | 2520 | case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */ | |
2540 | /* workaround for M-Audio Audiophile USB */ | 2521 | case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ |
2541 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763 && | ||
2542 | le16_to_cpu(dev->descriptor.idProduct) == 0x2003) { | ||
2543 | /* doesn't set the sample rate attribute, but supports it */ | 2522 | /* doesn't set the sample rate attribute, but supports it */ |
2544 | fp->attributes |= EP_CS_ATTR_SAMPLE_RATE; | 2523 | fp->attributes |= EP_CS_ATTR_SAMPLE_RATE; |
2545 | } | 2524 | break; |
2546 | 2525 | case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ | |
2526 | case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is | ||
2527 | an older model 77d:223) */ | ||
2547 | /* | 2528 | /* |
2548 | * plantronics headset and Griffin iMic have set adaptive-in | 2529 | * plantronics headset and Griffin iMic have set adaptive-in |
2549 | * although it's really not... | 2530 | * although it's really not... |
2550 | */ | 2531 | */ |
2551 | if ((le16_to_cpu(dev->descriptor.idVendor) == 0x047f && | ||
2552 | le16_to_cpu(dev->descriptor.idProduct) == 0x0ca1) || | ||
2553 | /* Griffin iMic (note that there is an older model 77d:223) */ | ||
2554 | (le16_to_cpu(dev->descriptor.idVendor) == 0x077d && | ||
2555 | le16_to_cpu(dev->descriptor.idProduct) == 0x07af)) { | ||
2556 | fp->ep_attr &= ~EP_ATTR_MASK; | 2532 | fp->ep_attr &= ~EP_ATTR_MASK; |
2557 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | 2533 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) |
2558 | fp->ep_attr |= EP_ATTR_ADAPTIVE; | 2534 | fp->ep_attr |= EP_ATTR_ADAPTIVE; |
2559 | else | 2535 | else |
2560 | fp->ep_attr |= EP_ATTR_SYNC; | 2536 | fp->ep_attr |= EP_ATTR_SYNC; |
2537 | break; | ||
2561 | } | 2538 | } |
2562 | 2539 | ||
2563 | /* ok, let's parse further... */ | 2540 | /* ok, let's parse further... */ |
2564 | if (parse_audio_format(dev, fp, format, fmt, stream) < 0) { | 2541 | if (parse_audio_format(chip, fp, format, fmt, stream) < 0) { |
2565 | kfree(fp->rate_table); | 2542 | kfree(fp->rate_table); |
2566 | kfree(fp); | 2543 | kfree(fp); |
2567 | continue; | 2544 | continue; |
@@ -2587,7 +2564,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) | |||
2587 | * disconnect streams | 2564 | * disconnect streams |
2588 | * called from snd_usb_audio_disconnect() | 2565 | * called from snd_usb_audio_disconnect() |
2589 | */ | 2566 | */ |
2590 | static void snd_usb_stream_disconnect(struct list_head *head, struct usb_driver *driver) | 2567 | static void snd_usb_stream_disconnect(struct list_head *head) |
2591 | { | 2568 | { |
2592 | int idx; | 2569 | int idx; |
2593 | snd_usb_stream_t *as; | 2570 | snd_usb_stream_t *as; |
@@ -2758,7 +2735,8 @@ static int create_standard_interface_quirk(snd_usb_audio_t *chip, | |||
2758 | * to detect the sample rate is by looking at wMaxPacketSize. | 2735 | * to detect the sample rate is by looking at wMaxPacketSize. |
2759 | */ | 2736 | */ |
2760 | static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, | 2737 | static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, |
2761 | struct usb_interface *iface) | 2738 | struct usb_interface *iface, |
2739 | const snd_usb_audio_quirk_t *quirk) | ||
2762 | { | 2740 | { |
2763 | static const struct audioformat ua_format = { | 2741 | static const struct audioformat ua_format = { |
2764 | .format = SNDRV_PCM_FORMAT_S24_3LE, | 2742 | .format = SNDRV_PCM_FORMAT_S24_3LE, |
@@ -2796,7 +2774,7 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, | |||
2796 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 2774 | .type = QUIRK_MIDI_FIXED_ENDPOINT, |
2797 | .data = &ua25_ep | 2775 | .data = &ua25_ep |
2798 | }; | 2776 | }; |
2799 | if (le16_to_cpu(chip->dev->descriptor.idProduct) == 0x002b) | 2777 | if (chip->usb_id == USB_ID(0x0582, 0x002b)) |
2800 | return snd_usb_create_midi_interface(chip, iface, | 2778 | return snd_usb_create_midi_interface(chip, iface, |
2801 | &ua700_quirk); | 2779 | &ua700_quirk); |
2802 | else | 2780 | else |
@@ -2849,7 +2827,9 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, | |||
2849 | /* | 2827 | /* |
2850 | * Create a stream for an Edirol UA-1000 interface. | 2828 | * Create a stream for an Edirol UA-1000 interface. |
2851 | */ | 2829 | */ |
2852 | static int create_ua1000_quirk(snd_usb_audio_t *chip, struct usb_interface *iface) | 2830 | static int create_ua1000_quirk(snd_usb_audio_t *chip, |
2831 | struct usb_interface *iface, | ||
2832 | const snd_usb_audio_quirk_t *quirk) | ||
2853 | { | 2833 | { |
2854 | static const struct audioformat ua1000_format = { | 2834 | static const struct audioformat ua1000_format = { |
2855 | .format = SNDRV_PCM_FORMAT_S32_LE, | 2835 | .format = SNDRV_PCM_FORMAT_S32_LE, |
@@ -2926,6 +2906,13 @@ static int create_composite_quirk(snd_usb_audio_t *chip, | |||
2926 | return 0; | 2906 | return 0; |
2927 | } | 2907 | } |
2928 | 2908 | ||
2909 | static int ignore_interface_quirk(snd_usb_audio_t *chip, | ||
2910 | struct usb_interface *iface, | ||
2911 | const snd_usb_audio_quirk_t *quirk) | ||
2912 | { | ||
2913 | return 0; | ||
2914 | } | ||
2915 | |||
2929 | 2916 | ||
2930 | /* | 2917 | /* |
2931 | * boot quirks | 2918 | * boot quirks |
@@ -2959,6 +2946,22 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac | |||
2959 | return 0; | 2946 | return 0; |
2960 | } | 2947 | } |
2961 | 2948 | ||
2949 | static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) | ||
2950 | { | ||
2951 | u8 buf = 1; | ||
2952 | |||
2953 | snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a, | ||
2954 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
2955 | 0, 0, &buf, 1, 1000); | ||
2956 | if (buf == 0) { | ||
2957 | snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29, | ||
2958 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
2959 | 1, 2000, NULL, 0, 1000); | ||
2960 | return -ENODEV; | ||
2961 | } | ||
2962 | return 0; | ||
2963 | } | ||
2964 | |||
2962 | 2965 | ||
2963 | /* | 2966 | /* |
2964 | * audio-interface quirks | 2967 | * audio-interface quirks |
@@ -2972,28 +2975,28 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip, | |||
2972 | struct usb_interface *iface, | 2975 | struct usb_interface *iface, |
2973 | const snd_usb_audio_quirk_t *quirk) | 2976 | const snd_usb_audio_quirk_t *quirk) |
2974 | { | 2977 | { |
2975 | switch (quirk->type) { | 2978 | typedef int (*quirk_func_t)(snd_usb_audio_t *, struct usb_interface *, |
2976 | case QUIRK_MIDI_FIXED_ENDPOINT: | 2979 | const snd_usb_audio_quirk_t *); |
2977 | case QUIRK_MIDI_YAMAHA: | 2980 | static const quirk_func_t quirk_funcs[] = { |
2978 | case QUIRK_MIDI_MIDIMAN: | 2981 | [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, |
2979 | case QUIRK_MIDI_NOVATION: | 2982 | [QUIRK_COMPOSITE] = create_composite_quirk, |
2980 | case QUIRK_MIDI_MOTU: | 2983 | [QUIRK_MIDI_STANDARD_INTERFACE] = snd_usb_create_midi_interface, |
2981 | case QUIRK_MIDI_EMAGIC: | 2984 | [QUIRK_MIDI_FIXED_ENDPOINT] = snd_usb_create_midi_interface, |
2982 | return snd_usb_create_midi_interface(chip, iface, quirk); | 2985 | [QUIRK_MIDI_YAMAHA] = snd_usb_create_midi_interface, |
2983 | case QUIRK_COMPOSITE: | 2986 | [QUIRK_MIDI_MIDIMAN] = snd_usb_create_midi_interface, |
2984 | return create_composite_quirk(chip, iface, quirk); | 2987 | [QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface, |
2985 | case QUIRK_AUDIO_FIXED_ENDPOINT: | 2988 | [QUIRK_MIDI_RAW] = snd_usb_create_midi_interface, |
2986 | return create_fixed_stream_quirk(chip, iface, quirk); | 2989 | [QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface, |
2987 | case QUIRK_AUDIO_STANDARD_INTERFACE: | 2990 | [QUIRK_MIDI_MIDITECH] = snd_usb_create_midi_interface, |
2988 | case QUIRK_MIDI_STANDARD_INTERFACE: | 2991 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_interface_quirk, |
2989 | return create_standard_interface_quirk(chip, iface, quirk); | 2992 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, |
2990 | case QUIRK_AUDIO_EDIROL_UA700_UA25: | 2993 | [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, |
2991 | return create_ua700_ua25_quirk(chip, iface); | 2994 | [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, |
2992 | case QUIRK_AUDIO_EDIROL_UA1000: | 2995 | }; |
2993 | return create_ua1000_quirk(chip, iface); | 2996 | |
2994 | case QUIRK_IGNORE_INTERFACE: | 2997 | if (quirk->type < QUIRK_TYPE_COUNT) { |
2995 | return 0; | 2998 | return quirk_funcs[quirk->type](chip, iface, quirk); |
2996 | default: | 2999 | } else { |
2997 | snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); | 3000 | snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); |
2998 | return -ENXIO; | 3001 | return -ENXIO; |
2999 | } | 3002 | } |
@@ -3015,8 +3018,8 @@ static void proc_audio_usbid_read(snd_info_entry_t *entry, snd_info_buffer_t *bu | |||
3015 | snd_usb_audio_t *chip = entry->private_data; | 3018 | snd_usb_audio_t *chip = entry->private_data; |
3016 | if (! chip->shutdown) | 3019 | if (! chip->shutdown) |
3017 | snd_iprintf(buffer, "%04x:%04x\n", | 3020 | snd_iprintf(buffer, "%04x:%04x\n", |
3018 | le16_to_cpu(chip->dev->descriptor.idVendor), | 3021 | USB_ID_VENDOR(chip->usb_id), |
3019 | le16_to_cpu(chip->dev->descriptor.idProduct)); | 3022 | USB_ID_PRODUCT(chip->usb_id)); |
3020 | } | 3023 | } |
3021 | 3024 | ||
3022 | static void snd_usb_audio_create_proc(snd_usb_audio_t *chip) | 3025 | static void snd_usb_audio_create_proc(snd_usb_audio_t *chip) |
@@ -3086,8 +3089,11 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3086 | chip->index = idx; | 3089 | chip->index = idx; |
3087 | chip->dev = dev; | 3090 | chip->dev = dev; |
3088 | chip->card = card; | 3091 | chip->card = card; |
3092 | chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), | ||
3093 | le16_to_cpu(dev->descriptor.idProduct)); | ||
3089 | INIT_LIST_HEAD(&chip->pcm_list); | 3094 | INIT_LIST_HEAD(&chip->pcm_list); |
3090 | INIT_LIST_HEAD(&chip->midi_list); | 3095 | INIT_LIST_HEAD(&chip->midi_list); |
3096 | INIT_LIST_HEAD(&chip->mixer_list); | ||
3091 | 3097 | ||
3092 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 3098 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { |
3093 | snd_usb_audio_free(chip); | 3099 | snd_usb_audio_free(chip); |
@@ -3097,8 +3103,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3097 | 3103 | ||
3098 | strcpy(card->driver, "USB-Audio"); | 3104 | strcpy(card->driver, "USB-Audio"); |
3099 | sprintf(component, "USB%04x:%04x", | 3105 | sprintf(component, "USB%04x:%04x", |
3100 | le16_to_cpu(dev->descriptor.idVendor), | 3106 | USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id)); |
3101 | le16_to_cpu(dev->descriptor.idProduct)); | ||
3102 | snd_component_add(card, component); | 3107 | snd_component_add(card, component); |
3103 | 3108 | ||
3104 | /* retrieve the device string as shortname */ | 3109 | /* retrieve the device string as shortname */ |
@@ -3110,8 +3115,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3110 | card->shortname, sizeof(card->shortname)) <= 0) { | 3115 | card->shortname, sizeof(card->shortname)) <= 0) { |
3111 | /* no name available from anywhere, so use ID */ | 3116 | /* no name available from anywhere, so use ID */ |
3112 | sprintf(card->shortname, "USB Device %#04x:%#04x", | 3117 | sprintf(card->shortname, "USB Device %#04x:%#04x", |
3113 | le16_to_cpu(dev->descriptor.idVendor), | 3118 | USB_ID_VENDOR(chip->usb_id), |
3114 | le16_to_cpu(dev->descriptor.idProduct)); | 3119 | USB_ID_PRODUCT(chip->usb_id)); |
3115 | } | 3120 | } |
3116 | } | 3121 | } |
3117 | 3122 | ||
@@ -3142,8 +3147,6 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3142 | 3147 | ||
3143 | snd_usb_audio_create_proc(chip); | 3148 | snd_usb_audio_create_proc(chip); |
3144 | 3149 | ||
3145 | snd_card_set_dev(card, &dev->dev); | ||
3146 | |||
3147 | *rchip = chip; | 3150 | *rchip = chip; |
3148 | return 0; | 3151 | return 0; |
3149 | } | 3152 | } |
@@ -3169,21 +3172,28 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
3169 | snd_usb_audio_t *chip; | 3172 | snd_usb_audio_t *chip; |
3170 | struct usb_host_interface *alts; | 3173 | struct usb_host_interface *alts; |
3171 | int ifnum; | 3174 | int ifnum; |
3175 | u32 id; | ||
3172 | 3176 | ||
3173 | alts = &intf->altsetting[0]; | 3177 | alts = &intf->altsetting[0]; |
3174 | ifnum = get_iface_desc(alts)->bInterfaceNumber; | 3178 | ifnum = get_iface_desc(alts)->bInterfaceNumber; |
3179 | id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), | ||
3180 | le16_to_cpu(dev->descriptor.idProduct)); | ||
3175 | 3181 | ||
3176 | if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) | 3182 | if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) |
3177 | goto __err_val; | 3183 | goto __err_val; |
3178 | 3184 | ||
3179 | /* SB Extigy needs special boot-up sequence */ | 3185 | /* SB Extigy needs special boot-up sequence */ |
3180 | /* if more models come, this will go to the quirk list. */ | 3186 | /* if more models come, this will go to the quirk list. */ |
3181 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && | 3187 | if (id == USB_ID(0x041e, 0x3000)) { |
3182 | le16_to_cpu(dev->descriptor.idProduct) == 0x3000) { | ||
3183 | if (snd_usb_extigy_boot_quirk(dev, intf) < 0) | 3188 | if (snd_usb_extigy_boot_quirk(dev, intf) < 0) |
3184 | goto __err_val; | 3189 | goto __err_val; |
3185 | config = dev->actconfig; | 3190 | config = dev->actconfig; |
3186 | } | 3191 | } |
3192 | /* SB Audigy 2 NX needs its own boot-up magic, too */ | ||
3193 | if (id == USB_ID(0x041e, 0x3020)) { | ||
3194 | if (snd_usb_audigy2nx_boot_quirk(dev) < 0) | ||
3195 | goto __err_val; | ||
3196 | } | ||
3187 | 3197 | ||
3188 | /* | 3198 | /* |
3189 | * found a config. now register to ALSA | 3199 | * found a config. now register to ALSA |
@@ -3213,11 +3223,12 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
3213 | } | 3223 | } |
3214 | for (i = 0; i < SNDRV_CARDS; i++) | 3224 | for (i = 0; i < SNDRV_CARDS; i++) |
3215 | if (enable[i] && ! usb_chip[i] && | 3225 | if (enable[i] && ! usb_chip[i] && |
3216 | (vid[i] == -1 || vid[i] == le16_to_cpu(dev->descriptor.idVendor)) && | 3226 | (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) && |
3217 | (pid[i] == -1 || pid[i] == le16_to_cpu(dev->descriptor.idProduct))) { | 3227 | (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) { |
3218 | if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) { | 3228 | if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) { |
3219 | goto __error; | 3229 | goto __error; |
3220 | } | 3230 | } |
3231 | snd_card_set_dev(chip->card, &intf->dev); | ||
3221 | break; | 3232 | break; |
3222 | } | 3233 | } |
3223 | if (! chip) { | 3234 | if (! chip) { |
@@ -3281,15 +3292,19 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) | |||
3281 | snd_card_disconnect(card); | 3292 | snd_card_disconnect(card); |
3282 | /* release the pcm resources */ | 3293 | /* release the pcm resources */ |
3283 | list_for_each(p, &chip->pcm_list) { | 3294 | list_for_each(p, &chip->pcm_list) { |
3284 | snd_usb_stream_disconnect(p, &usb_audio_driver); | 3295 | snd_usb_stream_disconnect(p); |
3285 | } | 3296 | } |
3286 | /* release the midi resources */ | 3297 | /* release the midi resources */ |
3287 | list_for_each(p, &chip->midi_list) { | 3298 | list_for_each(p, &chip->midi_list) { |
3288 | snd_usbmidi_disconnect(p, &usb_audio_driver); | 3299 | snd_usbmidi_disconnect(p); |
3300 | } | ||
3301 | /* release mixer resources */ | ||
3302 | list_for_each(p, &chip->mixer_list) { | ||
3303 | snd_usb_mixer_disconnect(p); | ||
3289 | } | 3304 | } |
3290 | usb_chip[chip->index] = NULL; | 3305 | usb_chip[chip->index] = NULL; |
3291 | up(®ister_mutex); | 3306 | up(®ister_mutex); |
3292 | snd_card_free_in_thread(card); | 3307 | snd_card_free(card); |
3293 | } else { | 3308 | } else { |
3294 | up(®ister_mutex); | 3309 | up(®ister_mutex); |
3295 | } | 3310 | } |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index eecbf19fcb6f..ad9eab211d8f 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -118,6 +118,11 @@ | |||
118 | /* maximum number of endpoints per interface */ | 118 | /* maximum number of endpoints per interface */ |
119 | #define MIDI_MAX_ENDPOINTS 2 | 119 | #define MIDI_MAX_ENDPOINTS 2 |
120 | 120 | ||
121 | /* handling of USB vendor/product ID pairs as 32-bit numbers */ | ||
122 | #define USB_ID(vendor, product) (((vendor) << 16) | (product)) | ||
123 | #define USB_ID_VENDOR(id) ((id) >> 16) | ||
124 | #define USB_ID_PRODUCT(id) ((u16)(id)) | ||
125 | |||
121 | /* | 126 | /* |
122 | */ | 127 | */ |
123 | 128 | ||
@@ -127,6 +132,7 @@ struct snd_usb_audio { | |||
127 | int index; | 132 | int index; |
128 | struct usb_device *dev; | 133 | struct usb_device *dev; |
129 | snd_card_t *card; | 134 | snd_card_t *card; |
135 | u32 usb_id; | ||
130 | int shutdown; | 136 | int shutdown; |
131 | int num_interfaces; | 137 | int num_interfaces; |
132 | 138 | ||
@@ -136,7 +142,7 @@ struct snd_usb_audio { | |||
136 | struct list_head midi_list; /* list of midi interfaces */ | 142 | struct list_head midi_list; /* list of midi interfaces */ |
137 | int next_midi_device; | 143 | int next_midi_device; |
138 | 144 | ||
139 | unsigned int ignore_ctl_error; /* for mixer */ | 145 | struct list_head mixer_list; /* list of mixer interfaces */ |
140 | }; | 146 | }; |
141 | 147 | ||
142 | /* | 148 | /* |
@@ -147,20 +153,24 @@ struct snd_usb_audio { | |||
147 | #define QUIRK_NO_INTERFACE -2 | 153 | #define QUIRK_NO_INTERFACE -2 |
148 | #define QUIRK_ANY_INTERFACE -1 | 154 | #define QUIRK_ANY_INTERFACE -1 |
149 | 155 | ||
150 | /* quirk type */ | 156 | enum quirk_type { |
151 | #define QUIRK_MIDI_FIXED_ENDPOINT 0 | 157 | QUIRK_IGNORE_INTERFACE, |
152 | #define QUIRK_MIDI_YAMAHA 1 | 158 | QUIRK_COMPOSITE, |
153 | #define QUIRK_MIDI_MIDIMAN 2 | 159 | QUIRK_MIDI_STANDARD_INTERFACE, |
154 | #define QUIRK_COMPOSITE 3 | 160 | QUIRK_MIDI_FIXED_ENDPOINT, |
155 | #define QUIRK_AUDIO_FIXED_ENDPOINT 4 | 161 | QUIRK_MIDI_YAMAHA, |
156 | #define QUIRK_AUDIO_STANDARD_INTERFACE 5 | 162 | QUIRK_MIDI_MIDIMAN, |
157 | #define QUIRK_MIDI_STANDARD_INTERFACE 6 | 163 | QUIRK_MIDI_NOVATION, |
158 | #define QUIRK_AUDIO_EDIROL_UA700_UA25 7 | 164 | QUIRK_MIDI_RAW, |
159 | #define QUIRK_AUDIO_EDIROL_UA1000 8 | 165 | QUIRK_MIDI_EMAGIC, |
160 | #define QUIRK_IGNORE_INTERFACE 9 | 166 | QUIRK_MIDI_MIDITECH, |
161 | #define QUIRK_MIDI_NOVATION 10 | 167 | QUIRK_AUDIO_STANDARD_INTERFACE, |
162 | #define QUIRK_MIDI_MOTU 11 | 168 | QUIRK_AUDIO_FIXED_ENDPOINT, |
163 | #define QUIRK_MIDI_EMAGIC 12 | 169 | QUIRK_AUDIO_EDIROL_UA700_UA25, |
170 | QUIRK_AUDIO_EDIROL_UA1000, | ||
171 | |||
172 | QUIRK_TYPE_COUNT | ||
173 | }; | ||
164 | 174 | ||
165 | typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t; | 175 | typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t; |
166 | typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t; | 176 | typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t; |
@@ -169,7 +179,7 @@ struct snd_usb_audio_quirk { | |||
169 | const char *vendor_name; | 179 | const char *vendor_name; |
170 | const char *product_name; | 180 | const char *product_name; |
171 | int16_t ifnum; | 181 | int16_t ifnum; |
172 | int16_t type; | 182 | uint16_t type; |
173 | const void *data; | 183 | const void *data; |
174 | }; | 184 | }; |
175 | 185 | ||
@@ -199,11 +209,13 @@ struct snd_usb_midi_endpoint_info { | |||
199 | 209 | ||
200 | /* for QUIRK_IGNORE_INTERFACE, data is NULL */ | 210 | /* for QUIRK_IGNORE_INTERFACE, data is NULL */ |
201 | 211 | ||
202 | /* for QUIRK_MIDI_NOVATION and _MOTU, data is NULL */ | 212 | /* for QUIRK_MIDI_NOVATION and _RAW, data is NULL */ |
203 | 213 | ||
204 | /* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info | 214 | /* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info |
205 | * structure (out_cables and in_cables only) */ | 215 | * structure (out_cables and in_cables only) */ |
206 | 216 | ||
217 | /* for QUIRK_MIDI_MIDITECH, data is NULL */ | ||
218 | |||
207 | /* | 219 | /* |
208 | */ | 220 | */ |
209 | 221 | ||
@@ -219,11 +231,12 @@ void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsub | |||
219 | int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout); | 231 | int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout); |
220 | 232 | ||
221 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif); | 233 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif); |
234 | void snd_usb_mixer_disconnect(struct list_head *p); | ||
222 | 235 | ||
223 | int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk); | 236 | int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk); |
224 | void snd_usbmidi_input_stop(struct list_head* p); | 237 | void snd_usbmidi_input_stop(struct list_head* p); |
225 | void snd_usbmidi_input_start(struct list_head* p); | 238 | void snd_usbmidi_input_start(struct list_head* p); |
226 | void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver); | 239 | void snd_usbmidi_disconnect(struct list_head *p); |
227 | 240 | ||
228 | /* | 241 | /* |
229 | * retrieve usb_interface descriptor from the host interface | 242 | * retrieve usb_interface descriptor from the host interface |
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 5d32857ff955..5778a9b725ec 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c | |||
@@ -524,16 +524,16 @@ static struct usb_protocol_ops snd_usbmidi_novation_ops = { | |||
524 | }; | 524 | }; |
525 | 525 | ||
526 | /* | 526 | /* |
527 | * Mark of the Unicorn USB MIDI protocol: raw MIDI. | 527 | * "raw" protocol: used by the MOTU FastLane. |
528 | */ | 528 | */ |
529 | 529 | ||
530 | static void snd_usbmidi_motu_input(snd_usb_midi_in_endpoint_t* ep, | 530 | static void snd_usbmidi_raw_input(snd_usb_midi_in_endpoint_t* ep, |
531 | uint8_t* buffer, int buffer_length) | 531 | uint8_t* buffer, int buffer_length) |
532 | { | 532 | { |
533 | snd_usbmidi_input_data(ep, 0, buffer, buffer_length); | 533 | snd_usbmidi_input_data(ep, 0, buffer, buffer_length); |
534 | } | 534 | } |
535 | 535 | ||
536 | static void snd_usbmidi_motu_output(snd_usb_midi_out_endpoint_t* ep) | 536 | static void snd_usbmidi_raw_output(snd_usb_midi_out_endpoint_t* ep) |
537 | { | 537 | { |
538 | int count; | 538 | int count; |
539 | 539 | ||
@@ -549,9 +549,9 @@ static void snd_usbmidi_motu_output(snd_usb_midi_out_endpoint_t* ep) | |||
549 | ep->urb->transfer_buffer_length = count; | 549 | ep->urb->transfer_buffer_length = count; |
550 | } | 550 | } |
551 | 551 | ||
552 | static struct usb_protocol_ops snd_usbmidi_motu_ops = { | 552 | static struct usb_protocol_ops snd_usbmidi_raw_ops = { |
553 | .input = snd_usbmidi_motu_input, | 553 | .input = snd_usbmidi_raw_input, |
554 | .output = snd_usbmidi_motu_output, | 554 | .output = snd_usbmidi_raw_output, |
555 | }; | 555 | }; |
556 | 556 | ||
557 | /* | 557 | /* |
@@ -912,7 +912,7 @@ static void snd_usbmidi_free(snd_usb_midi_t* umidi) | |||
912 | /* | 912 | /* |
913 | * Unlinks all URBs (must be done before the usb_device is deleted). | 913 | * Unlinks all URBs (must be done before the usb_device is deleted). |
914 | */ | 914 | */ |
915 | void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver) | 915 | void snd_usbmidi_disconnect(struct list_head* p) |
916 | { | 916 | { |
917 | snd_usb_midi_t* umidi; | 917 | snd_usb_midi_t* umidi; |
918 | int i; | 918 | int i; |
@@ -955,88 +955,87 @@ static snd_rawmidi_substream_t* snd_usbmidi_find_substream(snd_usb_midi_t* umidi | |||
955 | * such as internal control or synthesizer ports. | 955 | * such as internal control or synthesizer ports. |
956 | */ | 956 | */ |
957 | static struct { | 957 | static struct { |
958 | __u16 vendor; | 958 | u32 id; |
959 | __u16 product; | ||
960 | int port; | 959 | int port; |
961 | const char *name_format; | 960 | const char *name_format; |
962 | } snd_usbmidi_port_names[] = { | 961 | } snd_usbmidi_port_names[] = { |
963 | /* Roland UA-100 */ | 962 | /* Roland UA-100 */ |
964 | {0x0582, 0x0000, 2, "%s Control"}, | 963 | { USB_ID(0x0582, 0x0000), 2, "%s Control" }, |
965 | /* Roland SC-8850 */ | 964 | /* Roland SC-8850 */ |
966 | {0x0582, 0x0003, 0, "%s Part A"}, | 965 | { USB_ID(0x0582, 0x0003), 0, "%s Part A" }, |
967 | {0x0582, 0x0003, 1, "%s Part B"}, | 966 | { USB_ID(0x0582, 0x0003), 1, "%s Part B" }, |
968 | {0x0582, 0x0003, 2, "%s Part C"}, | 967 | { USB_ID(0x0582, 0x0003), 2, "%s Part C" }, |
969 | {0x0582, 0x0003, 3, "%s Part D"}, | 968 | { USB_ID(0x0582, 0x0003), 3, "%s Part D" }, |
970 | {0x0582, 0x0003, 4, "%s MIDI 1"}, | 969 | { USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" }, |
971 | {0x0582, 0x0003, 5, "%s MIDI 2"}, | 970 | { USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" }, |
972 | /* Roland U-8 */ | 971 | /* Roland U-8 */ |
973 | {0x0582, 0x0004, 0, "%s MIDI"}, | 972 | { USB_ID(0x0582, 0x0004), 0, "%s MIDI" }, |
974 | {0x0582, 0x0004, 1, "%s Control"}, | 973 | { USB_ID(0x0582, 0x0004), 1, "%s Control" }, |
975 | /* Roland SC-8820 */ | 974 | /* Roland SC-8820 */ |
976 | {0x0582, 0x0007, 0, "%s Part A"}, | 975 | { USB_ID(0x0582, 0x0007), 0, "%s Part A" }, |
977 | {0x0582, 0x0007, 1, "%s Part B"}, | 976 | { USB_ID(0x0582, 0x0007), 1, "%s Part B" }, |
978 | {0x0582, 0x0007, 2, "%s MIDI"}, | 977 | { USB_ID(0x0582, 0x0007), 2, "%s MIDI" }, |
979 | /* Roland SK-500 */ | 978 | /* Roland SK-500 */ |
980 | {0x0582, 0x000b, 0, "%s Part A"}, | 979 | { USB_ID(0x0582, 0x000b), 0, "%s Part A" }, |
981 | {0x0582, 0x000b, 1, "%s Part B"}, | 980 | { USB_ID(0x0582, 0x000b), 1, "%s Part B" }, |
982 | {0x0582, 0x000b, 2, "%s MIDI"}, | 981 | { USB_ID(0x0582, 0x000b), 2, "%s MIDI" }, |
983 | /* Roland SC-D70 */ | 982 | /* Roland SC-D70 */ |
984 | {0x0582, 0x000c, 0, "%s Part A"}, | 983 | { USB_ID(0x0582, 0x000c), 0, "%s Part A" }, |
985 | {0x0582, 0x000c, 1, "%s Part B"}, | 984 | { USB_ID(0x0582, 0x000c), 1, "%s Part B" }, |
986 | {0x0582, 0x000c, 2, "%s MIDI"}, | 985 | { USB_ID(0x0582, 0x000c), 2, "%s MIDI" }, |
987 | /* Edirol UM-880 */ | 986 | /* Edirol UM-880 */ |
988 | {0x0582, 0x0014, 8, "%s Control"}, | 987 | { USB_ID(0x0582, 0x0014), 8, "%s Control" }, |
989 | /* Edirol SD-90 */ | 988 | /* Edirol SD-90 */ |
990 | {0x0582, 0x0016, 0, "%s Part A"}, | 989 | { USB_ID(0x0582, 0x0016), 0, "%s Part A" }, |
991 | {0x0582, 0x0016, 1, "%s Part B"}, | 990 | { USB_ID(0x0582, 0x0016), 1, "%s Part B" }, |
992 | {0x0582, 0x0016, 2, "%s MIDI 1"}, | 991 | { USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" }, |
993 | {0x0582, 0x0016, 3, "%s MIDI 2"}, | 992 | { USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" }, |
994 | /* Edirol UM-550 */ | 993 | /* Edirol UM-550 */ |
995 | {0x0582, 0x0023, 5, "%s Control"}, | 994 | { USB_ID(0x0582, 0x0023), 5, "%s Control" }, |
996 | /* Edirol SD-20 */ | 995 | /* Edirol SD-20 */ |
997 | {0x0582, 0x0027, 0, "%s Part A"}, | 996 | { USB_ID(0x0582, 0x0027), 0, "%s Part A" }, |
998 | {0x0582, 0x0027, 1, "%s Part B"}, | 997 | { USB_ID(0x0582, 0x0027), 1, "%s Part B" }, |
999 | {0x0582, 0x0027, 2, "%s MIDI"}, | 998 | { USB_ID(0x0582, 0x0027), 2, "%s MIDI" }, |
1000 | /* Edirol SD-80 */ | 999 | /* Edirol SD-80 */ |
1001 | {0x0582, 0x0029, 0, "%s Part A"}, | 1000 | { USB_ID(0x0582, 0x0029), 0, "%s Part A" }, |
1002 | {0x0582, 0x0029, 1, "%s Part B"}, | 1001 | { USB_ID(0x0582, 0x0029), 1, "%s Part B" }, |
1003 | {0x0582, 0x0029, 2, "%s MIDI 1"}, | 1002 | { USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" }, |
1004 | {0x0582, 0x0029, 3, "%s MIDI 2"}, | 1003 | { USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" }, |
1005 | /* Edirol UA-700 */ | 1004 | /* Edirol UA-700 */ |
1006 | {0x0582, 0x002b, 0, "%s MIDI"}, | 1005 | { USB_ID(0x0582, 0x002b), 0, "%s MIDI" }, |
1007 | {0x0582, 0x002b, 1, "%s Control"}, | 1006 | { USB_ID(0x0582, 0x002b), 1, "%s Control" }, |
1008 | /* Roland VariOS */ | 1007 | /* Roland VariOS */ |
1009 | {0x0582, 0x002f, 0, "%s MIDI"}, | 1008 | { USB_ID(0x0582, 0x002f), 0, "%s MIDI" }, |
1010 | {0x0582, 0x002f, 1, "%s External MIDI"}, | 1009 | { USB_ID(0x0582, 0x002f), 1, "%s External MIDI" }, |
1011 | {0x0582, 0x002f, 2, "%s Sync"}, | 1010 | { USB_ID(0x0582, 0x002f), 2, "%s Sync" }, |
1012 | /* Edirol PCR */ | 1011 | /* Edirol PCR */ |
1013 | {0x0582, 0x0033, 0, "%s MIDI"}, | 1012 | { USB_ID(0x0582, 0x0033), 0, "%s MIDI" }, |
1014 | {0x0582, 0x0033, 1, "%s 1"}, | 1013 | { USB_ID(0x0582, 0x0033), 1, "%s 1" }, |
1015 | {0x0582, 0x0033, 2, "%s 2"}, | 1014 | { USB_ID(0x0582, 0x0033), 2, "%s 2" }, |
1016 | /* BOSS GS-10 */ | 1015 | /* BOSS GS-10 */ |
1017 | {0x0582, 0x003b, 0, "%s MIDI"}, | 1016 | { USB_ID(0x0582, 0x003b), 0, "%s MIDI" }, |
1018 | {0x0582, 0x003b, 1, "%s Control"}, | 1017 | { USB_ID(0x0582, 0x003b), 1, "%s Control" }, |
1019 | /* Edirol UA-1000 */ | 1018 | /* Edirol UA-1000 */ |
1020 | {0x0582, 0x0044, 0, "%s MIDI"}, | 1019 | { USB_ID(0x0582, 0x0044), 0, "%s MIDI" }, |
1021 | {0x0582, 0x0044, 1, "%s Control"}, | 1020 | { USB_ID(0x0582, 0x0044), 1, "%s Control" }, |
1022 | /* Edirol UR-80 */ | 1021 | /* Edirol UR-80 */ |
1023 | {0x0582, 0x0048, 0, "%s MIDI"}, | 1022 | { USB_ID(0x0582, 0x0048), 0, "%s MIDI" }, |
1024 | {0x0582, 0x0048, 1, "%s 1"}, | 1023 | { USB_ID(0x0582, 0x0048), 1, "%s 1" }, |
1025 | {0x0582, 0x0048, 2, "%s 2"}, | 1024 | { USB_ID(0x0582, 0x0048), 2, "%s 2" }, |
1026 | /* Edirol PCR-A */ | 1025 | /* Edirol PCR-A */ |
1027 | {0x0582, 0x004d, 0, "%s MIDI"}, | 1026 | { USB_ID(0x0582, 0x004d), 0, "%s MIDI" }, |
1028 | {0x0582, 0x004d, 1, "%s 1"}, | 1027 | { USB_ID(0x0582, 0x004d), 1, "%s 1" }, |
1029 | {0x0582, 0x004d, 2, "%s 2"}, | 1028 | { USB_ID(0x0582, 0x004d), 2, "%s 2" }, |
1030 | /* M-Audio MidiSport 8x8 */ | 1029 | /* M-Audio MidiSport 8x8 */ |
1031 | {0x0763, 0x1031, 8, "%s Control"}, | 1030 | { USB_ID(0x0763, 0x1031), 8, "%s Control" }, |
1032 | {0x0763, 0x1033, 8, "%s Control"}, | 1031 | { USB_ID(0x0763, 0x1033), 8, "%s Control" }, |
1033 | /* MOTU Fastlane */ | 1032 | /* MOTU Fastlane */ |
1034 | {0x07fd, 0x0001, 0, "%s MIDI A"}, | 1033 | { USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" }, |
1035 | {0x07fd, 0x0001, 1, "%s MIDI B"}, | 1034 | { USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" }, |
1036 | /* Emagic Unitor8/AMT8/MT4 */ | 1035 | /* Emagic Unitor8/AMT8/MT4 */ |
1037 | {0x086a, 0x0001, 8, "%s Broadcast"}, | 1036 | { USB_ID(0x086a, 0x0001), 8, "%s Broadcast" }, |
1038 | {0x086a, 0x0002, 8, "%s Broadcast"}, | 1037 | { USB_ID(0x086a, 0x0002), 8, "%s Broadcast" }, |
1039 | {0x086a, 0x0003, 4, "%s Broadcast"}, | 1038 | { USB_ID(0x086a, 0x0003), 4, "%s Broadcast" }, |
1040 | }; | 1039 | }; |
1041 | 1040 | ||
1042 | static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi, | 1041 | static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi, |
@@ -1044,7 +1043,6 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi, | |||
1044 | snd_rawmidi_substream_t** rsubstream) | 1043 | snd_rawmidi_substream_t** rsubstream) |
1045 | { | 1044 | { |
1046 | int i; | 1045 | int i; |
1047 | __u16 vendor, product; | ||
1048 | const char *name_format; | 1046 | const char *name_format; |
1049 | 1047 | ||
1050 | snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number); | 1048 | snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number); |
@@ -1055,11 +1053,8 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi, | |||
1055 | 1053 | ||
1056 | /* TODO: read port name from jack descriptor */ | 1054 | /* TODO: read port name from jack descriptor */ |
1057 | name_format = "%s MIDI %d"; | 1055 | name_format = "%s MIDI %d"; |
1058 | vendor = le16_to_cpu(umidi->chip->dev->descriptor.idVendor); | ||
1059 | product = le16_to_cpu(umidi->chip->dev->descriptor.idProduct); | ||
1060 | for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) { | 1056 | for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) { |
1061 | if (snd_usbmidi_port_names[i].vendor == vendor && | 1057 | if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id && |
1062 | snd_usbmidi_port_names[i].product == product && | ||
1063 | snd_usbmidi_port_names[i].port == number) { | 1058 | snd_usbmidi_port_names[i].port == number) { |
1064 | name_format = snd_usbmidi_port_names[i].name_format; | 1059 | name_format = snd_usbmidi_port_names[i].name_format; |
1065 | break; | 1060 | break; |
@@ -1226,9 +1221,12 @@ static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi, | |||
1226 | struct usb_endpoint_descriptor* epd; | 1221 | struct usb_endpoint_descriptor* epd; |
1227 | int i, out_eps = 0, in_eps = 0; | 1222 | int i, out_eps = 0, in_eps = 0; |
1228 | 1223 | ||
1229 | if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582) | 1224 | if (USB_ID_VENDOR(umidi->chip->usb_id) == 0x0582) |
1230 | snd_usbmidi_switch_roland_altsetting(umidi); | 1225 | snd_usbmidi_switch_roland_altsetting(umidi); |
1231 | 1226 | ||
1227 | if (endpoint[0].out_ep || endpoint[0].in_ep) | ||
1228 | return 0; | ||
1229 | |||
1232 | intf = umidi->iface; | 1230 | intf = umidi->iface; |
1233 | if (!intf || intf->num_altsetting < 1) | 1231 | if (!intf || intf->num_altsetting < 1) |
1234 | return -ENOENT; | 1232 | return -ENOENT; |
@@ -1507,8 +1505,8 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip, | |||
1507 | umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; | 1505 | umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; |
1508 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | 1506 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); |
1509 | break; | 1507 | break; |
1510 | case QUIRK_MIDI_MOTU: | 1508 | case QUIRK_MIDI_RAW: |
1511 | umidi->usb_protocol_ops = &snd_usbmidi_motu_ops; | 1509 | umidi->usb_protocol_ops = &snd_usbmidi_raw_ops; |
1512 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | 1510 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); |
1513 | break; | 1511 | break; |
1514 | case QUIRK_MIDI_EMAGIC: | 1512 | case QUIRK_MIDI_EMAGIC: |
@@ -1517,6 +1515,9 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip, | |||
1517 | sizeof(snd_usb_midi_endpoint_info_t)); | 1515 | sizeof(snd_usb_midi_endpoint_info_t)); |
1518 | err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); | 1516 | err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); |
1519 | break; | 1517 | break; |
1518 | case QUIRK_MIDI_MIDITECH: | ||
1519 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | ||
1520 | break; | ||
1520 | default: | 1521 | default: |
1521 | snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); | 1522 | snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); |
1522 | err = -ENXIO; | 1523 | err = -ENXIO; |
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 5f1906915aa6..fa7056f5caaf 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -35,10 +35,11 @@ | |||
35 | #include <linux/usb.h> | 35 | #include <linux/usb.h> |
36 | #include <sound/core.h> | 36 | #include <sound/core.h> |
37 | #include <sound/control.h> | 37 | #include <sound/control.h> |
38 | #include <sound/hwdep.h> | ||
39 | #include <sound/info.h> | ||
38 | 40 | ||
39 | #include "usbaudio.h" | 41 | #include "usbaudio.h" |
40 | 42 | ||
41 | |||
42 | /* | 43 | /* |
43 | */ | 44 | */ |
44 | 45 | ||
@@ -50,6 +51,31 @@ typedef struct usb_audio_term usb_audio_term_t; | |||
50 | typedef struct usb_mixer_elem_info usb_mixer_elem_info_t; | 51 | typedef struct usb_mixer_elem_info usb_mixer_elem_info_t; |
51 | 52 | ||
52 | 53 | ||
54 | struct usb_mixer_interface { | ||
55 | snd_usb_audio_t *chip; | ||
56 | unsigned int ctrlif; | ||
57 | struct list_head list; | ||
58 | unsigned int ignore_ctl_error; | ||
59 | struct urb *urb; | ||
60 | usb_mixer_elem_info_t **id_elems; /* array[256], indexed by unit id */ | ||
61 | |||
62 | /* Sound Blaster remote control stuff */ | ||
63 | enum { | ||
64 | RC_NONE, | ||
65 | RC_EXTIGY, | ||
66 | RC_AUDIGY2NX, | ||
67 | } rc_type; | ||
68 | unsigned long rc_hwdep_open; | ||
69 | u32 rc_code; | ||
70 | wait_queue_head_t rc_waitq; | ||
71 | struct urb *rc_urb; | ||
72 | struct usb_ctrlrequest *rc_setup_packet; | ||
73 | u8 rc_buffer[6]; | ||
74 | |||
75 | u8 audigy2nx_leds[3]; | ||
76 | }; | ||
77 | |||
78 | |||
53 | struct usb_audio_term { | 79 | struct usb_audio_term { |
54 | int id; | 80 | int id; |
55 | int type; | 81 | int type; |
@@ -62,26 +88,26 @@ struct usbmix_name_map; | |||
62 | 88 | ||
63 | struct usb_mixer_build { | 89 | struct usb_mixer_build { |
64 | snd_usb_audio_t *chip; | 90 | snd_usb_audio_t *chip; |
91 | struct usb_mixer_interface *mixer; | ||
65 | unsigned char *buffer; | 92 | unsigned char *buffer; |
66 | unsigned int buflen; | 93 | unsigned int buflen; |
67 | unsigned int ctrlif; | 94 | DECLARE_BITMAP(unitbitmap, 256); |
68 | unsigned short vendor; | ||
69 | unsigned short product; | ||
70 | DECLARE_BITMAP(unitbitmap, 32*32); | ||
71 | usb_audio_term_t oterm; | 95 | usb_audio_term_t oterm; |
72 | const struct usbmix_name_map *map; | 96 | const struct usbmix_name_map *map; |
97 | const struct usbmix_selector_map *selector_map; | ||
73 | }; | 98 | }; |
74 | 99 | ||
75 | struct usb_mixer_elem_info { | 100 | struct usb_mixer_elem_info { |
76 | snd_usb_audio_t *chip; | 101 | struct usb_mixer_interface *mixer; |
77 | unsigned int ctrlif; | 102 | usb_mixer_elem_info_t *next_id_elem; /* list of controls with same id */ |
103 | snd_ctl_elem_id_t *elem_id; | ||
78 | unsigned int id; | 104 | unsigned int id; |
79 | unsigned int control; /* CS or ICN (high byte) */ | 105 | unsigned int control; /* CS or ICN (high byte) */ |
80 | unsigned int cmask; /* channel mask bitmap: 0 = master */ | 106 | unsigned int cmask; /* channel mask bitmap: 0 = master */ |
81 | int channels; | 107 | int channels; |
82 | int val_type; | 108 | int val_type; |
83 | int min, max, res; | 109 | int min, max, res; |
84 | unsigned int initialized: 1; | 110 | u8 initialized; |
85 | }; | 111 | }; |
86 | 112 | ||
87 | 113 | ||
@@ -187,6 +213,21 @@ static int check_ignored_ctl(mixer_build_t *state, int unitid, int control) | |||
187 | return 0; | 213 | return 0; |
188 | } | 214 | } |
189 | 215 | ||
216 | /* get the mapped selector source name */ | ||
217 | static int check_mapped_selector_name(mixer_build_t *state, int unitid, | ||
218 | int index, char *buf, int buflen) | ||
219 | { | ||
220 | const struct usbmix_selector_map *p; | ||
221 | |||
222 | if (! state->selector_map) | ||
223 | return 0; | ||
224 | for (p = state->selector_map; p->id; p++) { | ||
225 | if (p->id == unitid && index < p->count) | ||
226 | return strlcpy(buf, p->names[index], buflen); | ||
227 | } | ||
228 | return 0; | ||
229 | } | ||
230 | |||
190 | /* | 231 | /* |
191 | * find an audio control unit with the given unit id | 232 | * find an audio control unit with the given unit id |
192 | */ | 233 | */ |
@@ -301,16 +342,18 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i | |||
301 | int timeout = 10; | 342 | int timeout = 10; |
302 | 343 | ||
303 | while (timeout-- > 0) { | 344 | while (timeout-- > 0) { |
304 | if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0), | 345 | if (snd_usb_ctl_msg(cval->mixer->chip->dev, |
346 | usb_rcvctrlpipe(cval->mixer->chip->dev, 0), | ||
305 | request, | 347 | request, |
306 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 348 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
307 | validx, cval->ctrlif | (cval->id << 8), | 349 | validx, cval->mixer->ctrlif | (cval->id << 8), |
308 | buf, val_len, 100) >= 0) { | 350 | buf, val_len, 100) >= 0) { |
309 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); | 351 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); |
310 | return 0; | 352 | return 0; |
311 | } | 353 | } |
312 | } | 354 | } |
313 | snd_printdd(KERN_ERR "cannot get ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type); | 355 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
356 | request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type); | ||
314 | return -EINVAL; | 357 | return -EINVAL; |
315 | } | 358 | } |
316 | 359 | ||
@@ -320,7 +363,7 @@ static int get_cur_ctl_value(usb_mixer_elem_info_t *cval, int validx, int *value | |||
320 | } | 363 | } |
321 | 364 | ||
322 | /* channel = 0: master, 1 = first channel */ | 365 | /* channel = 0: master, 1 = first channel */ |
323 | inline static int get_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, int *value) | 366 | static inline int get_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, int *value) |
324 | { | 367 | { |
325 | return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); | 368 | return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); |
326 | } | 369 | } |
@@ -339,13 +382,15 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i | |||
339 | buf[0] = value_set & 0xff; | 382 | buf[0] = value_set & 0xff; |
340 | buf[1] = (value_set >> 8) & 0xff; | 383 | buf[1] = (value_set >> 8) & 0xff; |
341 | while (timeout -- > 0) | 384 | while (timeout -- > 0) |
342 | if (snd_usb_ctl_msg(cval->chip->dev, usb_sndctrlpipe(cval->chip->dev, 0), | 385 | if (snd_usb_ctl_msg(cval->mixer->chip->dev, |
386 | usb_sndctrlpipe(cval->mixer->chip->dev, 0), | ||
343 | request, | 387 | request, |
344 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 388 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
345 | validx, cval->ctrlif | (cval->id << 8), | 389 | validx, cval->mixer->ctrlif | (cval->id << 8), |
346 | buf, val_len, 100) >= 0) | 390 | buf, val_len, 100) >= 0) |
347 | return 0; | 391 | return 0; |
348 | snd_printdd(KERN_ERR "cannot set ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d, data = 0x%x/0x%x\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]); | 392 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
393 | request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]); | ||
349 | return -EINVAL; | 394 | return -EINVAL; |
350 | } | 395 | } |
351 | 396 | ||
@@ -354,7 +399,7 @@ static int set_cur_ctl_value(usb_mixer_elem_info_t *cval, int validx, int value) | |||
354 | return set_ctl_value(cval, SET_CUR, validx, value); | 399 | return set_ctl_value(cval, SET_CUR, validx, value); |
355 | } | 400 | } |
356 | 401 | ||
357 | inline static int set_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, int value) | 402 | static inline int set_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, int value) |
358 | { | 403 | { |
359 | return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); | 404 | return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); |
360 | } | 405 | } |
@@ -385,16 +430,22 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou | |||
385 | * if failed, give up and free the control instance. | 430 | * if failed, give up and free the control instance. |
386 | */ | 431 | */ |
387 | 432 | ||
388 | static int add_control_to_empty(snd_card_t *card, snd_kcontrol_t *kctl) | 433 | static int add_control_to_empty(mixer_build_t *state, snd_kcontrol_t *kctl) |
389 | { | 434 | { |
435 | usb_mixer_elem_info_t *cval = kctl->private_data; | ||
390 | int err; | 436 | int err; |
391 | while (snd_ctl_find_id(card, &kctl->id)) | 437 | |
438 | while (snd_ctl_find_id(state->chip->card, &kctl->id)) | ||
392 | kctl->id.index++; | 439 | kctl->id.index++; |
393 | if ((err = snd_ctl_add(card, kctl)) < 0) { | 440 | if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) { |
394 | snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); | 441 | snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); |
395 | snd_ctl_free_one(kctl); | 442 | snd_ctl_free_one(kctl); |
443 | return err; | ||
396 | } | 444 | } |
397 | return err; | 445 | cval->elem_id = &kctl->id; |
446 | cval->next_id_elem = state->mixer->id_elems[cval->id]; | ||
447 | state->mixer->id_elems[cval->id] = cval; | ||
448 | return 0; | ||
398 | } | 449 | } |
399 | 450 | ||
400 | 451 | ||
@@ -572,10 +623,8 @@ static struct usb_feature_control_info audio_feature_info[] = { | |||
572 | /* private_free callback */ | 623 | /* private_free callback */ |
573 | static void usb_mixer_elem_free(snd_kcontrol_t *kctl) | 624 | static void usb_mixer_elem_free(snd_kcontrol_t *kctl) |
574 | { | 625 | { |
575 | if (kctl->private_data) { | 626 | kfree(kctl->private_data); |
576 | kfree(kctl->private_data); | 627 | kctl->private_data = NULL; |
577 | kctl->private_data = NULL; | ||
578 | } | ||
579 | } | 628 | } |
580 | 629 | ||
581 | 630 | ||
@@ -608,7 +657,8 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min) | |||
608 | } | 657 | } |
609 | if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || | 658 | if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || |
610 | get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { | 659 | get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { |
611 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", cval->id, cval->ctrlif, cval->control, cval->id); | 660 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", |
661 | cval->id, cval->mixer->ctrlif, cval->control, cval->id); | ||
612 | return -EINVAL; | 662 | return -EINVAL; |
613 | } | 663 | } |
614 | if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { | 664 | if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { |
@@ -668,7 +718,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
668 | if (cval->cmask & (1 << c)) { | 718 | if (cval->cmask & (1 << c)) { |
669 | err = get_cur_mix_value(cval, c + 1, &val); | 719 | err = get_cur_mix_value(cval, c + 1, &val); |
670 | if (err < 0) { | 720 | if (err < 0) { |
671 | if (cval->chip->ignore_ctl_error) { | 721 | if (cval->mixer->ignore_ctl_error) { |
672 | ucontrol->value.integer.value[0] = cval->min; | 722 | ucontrol->value.integer.value[0] = cval->min; |
673 | return 0; | 723 | return 0; |
674 | } | 724 | } |
@@ -684,7 +734,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
684 | /* master channel */ | 734 | /* master channel */ |
685 | err = get_cur_mix_value(cval, 0, &val); | 735 | err = get_cur_mix_value(cval, 0, &val); |
686 | if (err < 0) { | 736 | if (err < 0) { |
687 | if (cval->chip->ignore_ctl_error) { | 737 | if (cval->mixer->ignore_ctl_error) { |
688 | ucontrol->value.integer.value[0] = cval->min; | 738 | ucontrol->value.integer.value[0] = cval->min; |
689 | return 0; | 739 | return 0; |
690 | } | 740 | } |
@@ -710,7 +760,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
710 | if (cval->cmask & (1 << c)) { | 760 | if (cval->cmask & (1 << c)) { |
711 | err = get_cur_mix_value(cval, c + 1, &oval); | 761 | err = get_cur_mix_value(cval, c + 1, &oval); |
712 | if (err < 0) { | 762 | if (err < 0) { |
713 | if (cval->chip->ignore_ctl_error) | 763 | if (cval->mixer->ignore_ctl_error) |
714 | return 0; | 764 | return 0; |
715 | return err; | 765 | return err; |
716 | } | 766 | } |
@@ -727,7 +777,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
727 | } else { | 777 | } else { |
728 | /* master channel */ | 778 | /* master channel */ |
729 | err = get_cur_mix_value(cval, 0, &oval); | 779 | err = get_cur_mix_value(cval, 0, &oval); |
730 | if (err < 0 && cval->chip->ignore_ctl_error) | 780 | if (err < 0 && cval->mixer->ignore_ctl_error) |
731 | return 0; | 781 | return 0; |
732 | if (err < 0) | 782 | if (err < 0) |
733 | return err; | 783 | return err; |
@@ -779,8 +829,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, | |||
779 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 829 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
780 | return; | 830 | return; |
781 | } | 831 | } |
782 | cval->chip = state->chip; | 832 | cval->mixer = state->mixer; |
783 | cval->ctrlif = state->ctrlif; | ||
784 | cval->id = unitid; | 833 | cval->id = unitid; |
785 | cval->control = control; | 834 | cval->control = control; |
786 | cval->cmask = ctl_mask; | 835 | cval->cmask = ctl_mask; |
@@ -855,16 +904,21 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, | |||
855 | /* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */ | 904 | /* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */ |
856 | /* is not very clear from datasheets */ | 905 | /* is not very clear from datasheets */ |
857 | /* I hope that the min value is -15360 for newer firmware --jk */ | 906 | /* I hope that the min value is -15360 for newer firmware --jk */ |
858 | if (((state->vendor == 0x471 && (state->product == 0x104 || state->product == 0x105 || state->product == 0x101)) || | 907 | switch (state->chip->usb_id) { |
859 | (state->vendor == 0x672 && state->product == 0x1041)) && !strcmp(kctl->id.name, "PCM Playback Volume") && | 908 | case USB_ID(0x0471, 0x0101): |
860 | cval->min == -15616) { | 909 | case USB_ID(0x0471, 0x0104): |
861 | snd_printk("USB Audio: using volume control quirk for the UDA1321/N101 chip\n"); | 910 | case USB_ID(0x0471, 0x0105): |
862 | cval->max = -256; | 911 | case USB_ID(0x0672, 0x1041): |
912 | if (!strcmp(kctl->id.name, "PCM Playback Volume") && | ||
913 | cval->min == -15616) { | ||
914 | snd_printk("using volume control quirk for the UDA1321/N101 chip\n"); | ||
915 | cval->max = -256; | ||
916 | } | ||
863 | } | 917 | } |
864 | 918 | ||
865 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 919 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", |
866 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); | 920 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); |
867 | add_control_to_empty(state->chip->card, kctl); | 921 | add_control_to_empty(state, kctl); |
868 | } | 922 | } |
869 | 923 | ||
870 | 924 | ||
@@ -947,8 +1001,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, | |||
947 | if (! cval) | 1001 | if (! cval) |
948 | return; | 1002 | return; |
949 | 1003 | ||
950 | cval->chip = state->chip; | 1004 | cval->mixer = state->mixer; |
951 | cval->ctrlif = state->ctrlif; | ||
952 | cval->id = unitid; | 1005 | cval->id = unitid; |
953 | cval->control = in_ch + 1; /* based on 1 */ | 1006 | cval->control = in_ch + 1; /* based on 1 */ |
954 | cval->val_type = USB_MIXER_S16; | 1007 | cval->val_type = USB_MIXER_S16; |
@@ -979,7 +1032,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, | |||
979 | 1032 | ||
980 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", | 1033 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", |
981 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1034 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
982 | add_control_to_empty(state->chip->card, kctl); | 1035 | add_control_to_empty(state, kctl); |
983 | } | 1036 | } |
984 | 1037 | ||
985 | 1038 | ||
@@ -1042,7 +1095,7 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1042 | int err, val; | 1095 | int err, val; |
1043 | 1096 | ||
1044 | err = get_cur_ctl_value(cval, cval->control << 8, &val); | 1097 | err = get_cur_ctl_value(cval, cval->control << 8, &val); |
1045 | if (err < 0 && cval->chip->ignore_ctl_error) { | 1098 | if (err < 0 && cval->mixer->ignore_ctl_error) { |
1046 | ucontrol->value.integer.value[0] = cval->min; | 1099 | ucontrol->value.integer.value[0] = cval->min; |
1047 | return 0; | 1100 | return 0; |
1048 | } | 1101 | } |
@@ -1061,7 +1114,7 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1061 | 1114 | ||
1062 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); | 1115 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); |
1063 | if (err < 0) { | 1116 | if (err < 0) { |
1064 | if (cval->chip->ignore_ctl_error) | 1117 | if (cval->mixer->ignore_ctl_error) |
1065 | return 0; | 1118 | return 0; |
1066 | return err; | 1119 | return err; |
1067 | } | 1120 | } |
@@ -1179,9 +1232,6 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1179 | } | 1232 | } |
1180 | 1233 | ||
1181 | type = combine_word(&dsc[4]); | 1234 | type = combine_word(&dsc[4]); |
1182 | if (! type) | ||
1183 | return 0; /* undefined? */ | ||
1184 | |||
1185 | for (info = list; info && info->type; info++) | 1235 | for (info = list; info && info->type; info++) |
1186 | if (info->type == type) | 1236 | if (info->type == type) |
1187 | break; | 1237 | break; |
@@ -1199,8 +1249,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1199 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1249 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1200 | return -ENOMEM; | 1250 | return -ENOMEM; |
1201 | } | 1251 | } |
1202 | cval->chip = state->chip; | 1252 | cval->mixer = state->mixer; |
1203 | cval->ctrlif = state->ctrlif; | ||
1204 | cval->id = unitid; | 1253 | cval->id = unitid; |
1205 | cval->control = valinfo->control; | 1254 | cval->control = valinfo->control; |
1206 | cval->val_type = valinfo->val_type; | 1255 | cval->val_type = valinfo->val_type; |
@@ -1241,7 +1290,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1241 | 1290 | ||
1242 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", | 1291 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", |
1243 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1292 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
1244 | if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) | 1293 | if ((err = add_control_to_empty(state, kctl)) < 0) |
1245 | return err; | 1294 | return err; |
1246 | } | 1295 | } |
1247 | return 0; | 1296 | return 0; |
@@ -1289,7 +1338,7 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1289 | 1338 | ||
1290 | err = get_cur_ctl_value(cval, 0, &val); | 1339 | err = get_cur_ctl_value(cval, 0, &val); |
1291 | if (err < 0) { | 1340 | if (err < 0) { |
1292 | if (cval->chip->ignore_ctl_error) { | 1341 | if (cval->mixer->ignore_ctl_error) { |
1293 | ucontrol->value.enumerated.item[0] = 0; | 1342 | ucontrol->value.enumerated.item[0] = 0; |
1294 | return 0; | 1343 | return 0; |
1295 | } | 1344 | } |
@@ -1308,7 +1357,7 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1308 | 1357 | ||
1309 | err = get_cur_ctl_value(cval, 0, &oval); | 1358 | err = get_cur_ctl_value(cval, 0, &oval); |
1310 | if (err < 0) { | 1359 | if (err < 0) { |
1311 | if (cval->chip->ignore_ctl_error) | 1360 | if (cval->mixer->ignore_ctl_error) |
1312 | return 0; | 1361 | return 0; |
1313 | return err; | 1362 | return err; |
1314 | } | 1363 | } |
@@ -1386,8 +1435,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1386 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1435 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1387 | return -ENOMEM; | 1436 | return -ENOMEM; |
1388 | } | 1437 | } |
1389 | cval->chip = state->chip; | 1438 | cval->mixer = state->mixer; |
1390 | cval->ctrlif = state->ctrlif; | ||
1391 | cval->id = unitid; | 1439 | cval->id = unitid; |
1392 | cval->val_type = USB_MIXER_U8; | 1440 | cval->val_type = USB_MIXER_U8; |
1393 | cval->channels = 1; | 1441 | cval->channels = 1; |
@@ -1415,7 +1463,9 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1415 | kfree(cval); | 1463 | kfree(cval); |
1416 | return -ENOMEM; | 1464 | return -ENOMEM; |
1417 | } | 1465 | } |
1418 | if (check_input_term(state, desc[5 + i], &iterm) >= 0) | 1466 | len = check_mapped_selector_name(state, unitid, i, namelist[i], |
1467 | MAX_ITEM_NAME_LEN); | ||
1468 | if (! len && check_input_term(state, desc[5 + i], &iterm) >= 0) | ||
1419 | len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); | 1469 | len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); |
1420 | if (! len) | 1470 | if (! len) |
1421 | sprintf(namelist[i], "Input %d", i); | 1471 | sprintf(namelist[i], "Input %d", i); |
@@ -1450,7 +1500,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1450 | 1500 | ||
1451 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", | 1501 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", |
1452 | cval->id, kctl->id.name, num_ins); | 1502 | cval->id, kctl->id.name, num_ins); |
1453 | if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) | 1503 | if ((err = add_control_to_empty(state, kctl)) < 0) |
1454 | return err; | 1504 | return err; |
1455 | 1505 | ||
1456 | return 0; | 1506 | return 0; |
@@ -1493,41 +1543,55 @@ static int parse_audio_unit(mixer_build_t *state, int unitid) | |||
1493 | } | 1543 | } |
1494 | } | 1544 | } |
1495 | 1545 | ||
1546 | static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) | ||
1547 | { | ||
1548 | kfree(mixer->id_elems); | ||
1549 | if (mixer->urb) { | ||
1550 | kfree(mixer->urb->transfer_buffer); | ||
1551 | usb_free_urb(mixer->urb); | ||
1552 | } | ||
1553 | if (mixer->rc_urb) | ||
1554 | usb_free_urb(mixer->rc_urb); | ||
1555 | kfree(mixer->rc_setup_packet); | ||
1556 | kfree(mixer); | ||
1557 | } | ||
1558 | |||
1559 | static int snd_usb_mixer_dev_free(snd_device_t *device) | ||
1560 | { | ||
1561 | struct usb_mixer_interface *mixer = device->device_data; | ||
1562 | snd_usb_mixer_free(mixer); | ||
1563 | return 0; | ||
1564 | } | ||
1565 | |||
1496 | /* | 1566 | /* |
1497 | * create mixer controls | 1567 | * create mixer controls |
1498 | * | 1568 | * |
1499 | * walk through all OUTPUT_TERMINAL descriptors to search for mixers | 1569 | * walk through all OUTPUT_TERMINAL descriptors to search for mixers |
1500 | */ | 1570 | */ |
1501 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | 1571 | static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) |
1502 | { | 1572 | { |
1503 | unsigned char *desc; | 1573 | unsigned char *desc; |
1504 | mixer_build_t state; | 1574 | mixer_build_t state; |
1505 | int err; | 1575 | int err; |
1506 | const struct usbmix_ctl_map *map; | 1576 | const struct usbmix_ctl_map *map; |
1507 | struct usb_device_descriptor *dev = &chip->dev->descriptor; | 1577 | struct usb_host_interface *hostif; |
1508 | struct usb_host_interface *hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; | ||
1509 | |||
1510 | strcpy(chip->card->mixername, "USB Mixer"); | ||
1511 | 1578 | ||
1579 | hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; | ||
1512 | memset(&state, 0, sizeof(state)); | 1580 | memset(&state, 0, sizeof(state)); |
1513 | state.chip = chip; | 1581 | state.chip = mixer->chip; |
1582 | state.mixer = mixer; | ||
1514 | state.buffer = hostif->extra; | 1583 | state.buffer = hostif->extra; |
1515 | state.buflen = hostif->extralen; | 1584 | state.buflen = hostif->extralen; |
1516 | state.ctrlif = ctrlif; | ||
1517 | state.vendor = le16_to_cpu(dev->idVendor); | ||
1518 | state.product = le16_to_cpu(dev->idProduct); | ||
1519 | 1585 | ||
1520 | /* check the mapping table */ | 1586 | /* check the mapping table */ |
1521 | for (map = usbmix_ctl_maps; map->vendor; map++) { | 1587 | for (map = usbmix_ctl_maps; map->id; map++) { |
1522 | if (map->vendor == state.vendor && map->product == state.product) { | 1588 | if (map->id == state.chip->usb_id) { |
1523 | state.map = map->map; | 1589 | state.map = map->map; |
1524 | chip->ignore_ctl_error = map->ignore_ctl_error; | 1590 | state.selector_map = map->selector_map; |
1591 | mixer->ignore_ctl_error = map->ignore_ctl_error; | ||
1525 | break; | 1592 | break; |
1526 | } | 1593 | } |
1527 | } | 1594 | } |
1528 | #ifdef IGNORE_CTL_ERROR | ||
1529 | chip->ignore_ctl_error = 1; | ||
1530 | #endif | ||
1531 | 1595 | ||
1532 | desc = NULL; | 1596 | desc = NULL; |
1533 | while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { | 1597 | while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { |
@@ -1543,3 +1607,393 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | |||
1543 | } | 1607 | } |
1544 | return 0; | 1608 | return 0; |
1545 | } | 1609 | } |
1610 | |||
1611 | static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, | ||
1612 | int unitid) | ||
1613 | { | ||
1614 | usb_mixer_elem_info_t *info; | ||
1615 | |||
1616 | for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) | ||
1617 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1618 | info->elem_id); | ||
1619 | } | ||
1620 | |||
1621 | static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, | ||
1622 | int unitid) | ||
1623 | { | ||
1624 | if (mixer->rc_type == RC_NONE) | ||
1625 | return; | ||
1626 | /* unit ids specific to Extigy/Audigy 2 NX: */ | ||
1627 | switch (unitid) { | ||
1628 | case 0: /* remote control */ | ||
1629 | mixer->rc_urb->dev = mixer->chip->dev; | ||
1630 | usb_submit_urb(mixer->rc_urb, GFP_ATOMIC); | ||
1631 | break; | ||
1632 | case 4: /* digital in jack */ | ||
1633 | case 7: /* line in jacks */ | ||
1634 | case 19: /* speaker out jacks */ | ||
1635 | case 20: /* headphones out jack */ | ||
1636 | break; | ||
1637 | default: | ||
1638 | snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid); | ||
1639 | break; | ||
1640 | } | ||
1641 | } | ||
1642 | |||
1643 | static void snd_usb_mixer_status_complete(struct urb *urb, struct pt_regs *regs) | ||
1644 | { | ||
1645 | struct usb_mixer_interface *mixer = urb->context; | ||
1646 | |||
1647 | if (urb->status == 0) { | ||
1648 | u8 *buf = urb->transfer_buffer; | ||
1649 | int i; | ||
1650 | |||
1651 | for (i = urb->actual_length; i >= 2; buf += 2, i -= 2) { | ||
1652 | snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n", | ||
1653 | buf[0], buf[1]); | ||
1654 | /* ignore any notifications not from the control interface */ | ||
1655 | if ((buf[0] & 0x0f) != 0) | ||
1656 | continue; | ||
1657 | if (!(buf[0] & 0x40)) | ||
1658 | snd_usb_mixer_notify_id(mixer, buf[1]); | ||
1659 | else | ||
1660 | snd_usb_mixer_memory_change(mixer, buf[1]); | ||
1661 | } | ||
1662 | } | ||
1663 | if (urb->status != -ENOENT && urb->status != -ECONNRESET) { | ||
1664 | urb->dev = mixer->chip->dev; | ||
1665 | usb_submit_urb(urb, GFP_ATOMIC); | ||
1666 | } | ||
1667 | } | ||
1668 | |||
1669 | /* create the handler for the optional status interrupt endpoint */ | ||
1670 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) | ||
1671 | { | ||
1672 | struct usb_host_interface *hostif; | ||
1673 | struct usb_endpoint_descriptor *ep; | ||
1674 | void *transfer_buffer; | ||
1675 | int buffer_length; | ||
1676 | unsigned int epnum; | ||
1677 | |||
1678 | hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; | ||
1679 | /* we need one interrupt input endpoint */ | ||
1680 | if (get_iface_desc(hostif)->bNumEndpoints < 1) | ||
1681 | return 0; | ||
1682 | ep = get_endpoint(hostif, 0); | ||
1683 | if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN || | ||
1684 | (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) | ||
1685 | return 0; | ||
1686 | |||
1687 | epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | ||
1688 | buffer_length = le16_to_cpu(ep->wMaxPacketSize); | ||
1689 | transfer_buffer = kmalloc(buffer_length, GFP_KERNEL); | ||
1690 | if (!transfer_buffer) | ||
1691 | return -ENOMEM; | ||
1692 | mixer->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1693 | if (!mixer->urb) { | ||
1694 | kfree(transfer_buffer); | ||
1695 | return -ENOMEM; | ||
1696 | } | ||
1697 | usb_fill_int_urb(mixer->urb, mixer->chip->dev, | ||
1698 | usb_rcvintpipe(mixer->chip->dev, epnum), | ||
1699 | transfer_buffer, buffer_length, | ||
1700 | snd_usb_mixer_status_complete, mixer, ep->bInterval); | ||
1701 | usb_submit_urb(mixer->urb, GFP_KERNEL); | ||
1702 | return 0; | ||
1703 | } | ||
1704 | |||
1705 | static void snd_usb_soundblaster_remote_complete(struct urb *urb, | ||
1706 | struct pt_regs *regs) | ||
1707 | { | ||
1708 | struct usb_mixer_interface *mixer = urb->context; | ||
1709 | /* | ||
1710 | * format of remote control data: | ||
1711 | * Extigy: xx 00 | ||
1712 | * Audigy 2 NX: 06 80 xx 00 00 00 | ||
1713 | */ | ||
1714 | int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2; | ||
1715 | u32 code; | ||
1716 | |||
1717 | if (urb->status < 0 || urb->actual_length <= offset) | ||
1718 | return; | ||
1719 | code = mixer->rc_buffer[offset]; | ||
1720 | /* the Mute button actually changes the mixer control */ | ||
1721 | if (code == 13) | ||
1722 | snd_usb_mixer_notify_id(mixer, 18); | ||
1723 | mixer->rc_code = code; | ||
1724 | wmb(); | ||
1725 | wake_up(&mixer->rc_waitq); | ||
1726 | } | ||
1727 | |||
1728 | static int snd_usb_sbrc_hwdep_open(snd_hwdep_t *hw, struct file *file) | ||
1729 | { | ||
1730 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1731 | |||
1732 | if (test_and_set_bit(0, &mixer->rc_hwdep_open)) | ||
1733 | return -EBUSY; | ||
1734 | return 0; | ||
1735 | } | ||
1736 | |||
1737 | static int snd_usb_sbrc_hwdep_release(snd_hwdep_t *hw, struct file *file) | ||
1738 | { | ||
1739 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1740 | |||
1741 | clear_bit(0, &mixer->rc_hwdep_open); | ||
1742 | smp_mb__after_clear_bit(); | ||
1743 | return 0; | ||
1744 | } | ||
1745 | |||
1746 | static long snd_usb_sbrc_hwdep_read(snd_hwdep_t *hw, char __user *buf, | ||
1747 | long count, loff_t *offset) | ||
1748 | { | ||
1749 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1750 | int err; | ||
1751 | u32 rc_code; | ||
1752 | |||
1753 | if (count != 1 && count != 4) | ||
1754 | return -EINVAL; | ||
1755 | err = wait_event_interruptible(mixer->rc_waitq, | ||
1756 | (rc_code = xchg(&mixer->rc_code, 0)) != 0); | ||
1757 | if (err == 0) { | ||
1758 | if (count == 1) | ||
1759 | err = put_user(rc_code, buf); | ||
1760 | else | ||
1761 | err = put_user(rc_code, (u32 __user *)buf); | ||
1762 | } | ||
1763 | return err < 0 ? err : count; | ||
1764 | } | ||
1765 | |||
1766 | static unsigned int snd_usb_sbrc_hwdep_poll(snd_hwdep_t *hw, struct file *file, | ||
1767 | poll_table *wait) | ||
1768 | { | ||
1769 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1770 | |||
1771 | poll_wait(file, &mixer->rc_waitq, wait); | ||
1772 | return mixer->rc_code ? POLLIN | POLLRDNORM : 0; | ||
1773 | } | ||
1774 | |||
1775 | static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) | ||
1776 | { | ||
1777 | snd_hwdep_t *hwdep; | ||
1778 | int err, len; | ||
1779 | |||
1780 | switch (mixer->chip->usb_id) { | ||
1781 | case USB_ID(0x041e, 0x3000): | ||
1782 | mixer->rc_type = RC_EXTIGY; | ||
1783 | len = 2; | ||
1784 | break; | ||
1785 | case USB_ID(0x041e, 0x3020): | ||
1786 | mixer->rc_type = RC_AUDIGY2NX; | ||
1787 | len = 6; | ||
1788 | break; | ||
1789 | default: | ||
1790 | return 0; | ||
1791 | } | ||
1792 | |||
1793 | init_waitqueue_head(&mixer->rc_waitq); | ||
1794 | err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); | ||
1795 | if (err < 0) | ||
1796 | return err; | ||
1797 | snprintf(hwdep->name, sizeof(hwdep->name), | ||
1798 | "%s remote control", mixer->chip->card->shortname); | ||
1799 | hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC; | ||
1800 | hwdep->private_data = mixer; | ||
1801 | hwdep->ops.read = snd_usb_sbrc_hwdep_read; | ||
1802 | hwdep->ops.open = snd_usb_sbrc_hwdep_open; | ||
1803 | hwdep->ops.release = snd_usb_sbrc_hwdep_release; | ||
1804 | hwdep->ops.poll = snd_usb_sbrc_hwdep_poll; | ||
1805 | |||
1806 | mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1807 | if (!mixer->rc_urb) | ||
1808 | return -ENOMEM; | ||
1809 | mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL); | ||
1810 | if (!mixer->rc_setup_packet) { | ||
1811 | usb_free_urb(mixer->rc_urb); | ||
1812 | mixer->rc_urb = NULL; | ||
1813 | return -ENOMEM; | ||
1814 | } | ||
1815 | mixer->rc_setup_packet->bRequestType = | ||
1816 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
1817 | mixer->rc_setup_packet->bRequest = GET_MEM; | ||
1818 | mixer->rc_setup_packet->wValue = cpu_to_le16(0); | ||
1819 | mixer->rc_setup_packet->wIndex = cpu_to_le16(0); | ||
1820 | mixer->rc_setup_packet->wLength = cpu_to_le16(len); | ||
1821 | usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev, | ||
1822 | usb_rcvctrlpipe(mixer->chip->dev, 0), | ||
1823 | (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len, | ||
1824 | snd_usb_soundblaster_remote_complete, mixer); | ||
1825 | return 0; | ||
1826 | } | ||
1827 | |||
1828 | static int snd_audigy2nx_led_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
1829 | { | ||
1830 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1831 | uinfo->count = 1; | ||
1832 | uinfo->value.integer.min = 0; | ||
1833 | uinfo->value.integer.max = 1; | ||
1834 | return 0; | ||
1835 | } | ||
1836 | |||
1837 | static int snd_audigy2nx_led_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1838 | { | ||
1839 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
1840 | int index = kcontrol->private_value; | ||
1841 | |||
1842 | ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index]; | ||
1843 | return 0; | ||
1844 | } | ||
1845 | |||
1846 | static int snd_audigy2nx_led_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1847 | { | ||
1848 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
1849 | int index = kcontrol->private_value; | ||
1850 | int value = ucontrol->value.integer.value[0]; | ||
1851 | int err, changed; | ||
1852 | |||
1853 | if (value > 1) | ||
1854 | return -EINVAL; | ||
1855 | changed = value != mixer->audigy2nx_leds[index]; | ||
1856 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
1857 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | ||
1858 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
1859 | value, index + 2, NULL, 0, 100); | ||
1860 | if (err < 0) | ||
1861 | return err; | ||
1862 | mixer->audigy2nx_leds[index] = value; | ||
1863 | return changed; | ||
1864 | } | ||
1865 | |||
1866 | static snd_kcontrol_new_t snd_audigy2nx_controls[] = { | ||
1867 | { | ||
1868 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1869 | .name = "CMSS LED Switch", | ||
1870 | .info = snd_audigy2nx_led_info, | ||
1871 | .get = snd_audigy2nx_led_get, | ||
1872 | .put = snd_audigy2nx_led_put, | ||
1873 | .private_value = 0, | ||
1874 | }, | ||
1875 | { | ||
1876 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1877 | .name = "Power LED Switch", | ||
1878 | .info = snd_audigy2nx_led_info, | ||
1879 | .get = snd_audigy2nx_led_get, | ||
1880 | .put = snd_audigy2nx_led_put, | ||
1881 | .private_value = 1, | ||
1882 | }, | ||
1883 | { | ||
1884 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1885 | .name = "Dolby Digital LED Switch", | ||
1886 | .info = snd_audigy2nx_led_info, | ||
1887 | .get = snd_audigy2nx_led_get, | ||
1888 | .put = snd_audigy2nx_led_put, | ||
1889 | .private_value = 2, | ||
1890 | }, | ||
1891 | }; | ||
1892 | |||
1893 | static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | ||
1894 | { | ||
1895 | int i, err; | ||
1896 | |||
1897 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { | ||
1898 | err = snd_ctl_add(mixer->chip->card, | ||
1899 | snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); | ||
1900 | if (err < 0) | ||
1901 | return err; | ||
1902 | } | ||
1903 | mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */ | ||
1904 | return 0; | ||
1905 | } | ||
1906 | |||
1907 | static void snd_audigy2nx_proc_read(snd_info_entry_t *entry, | ||
1908 | snd_info_buffer_t *buffer) | ||
1909 | { | ||
1910 | static const struct { | ||
1911 | int unitid; | ||
1912 | const char *name; | ||
1913 | } jacks[] = { | ||
1914 | {4, "dig in "}, | ||
1915 | {7, "line in"}, | ||
1916 | {19, "spk out"}, | ||
1917 | {20, "hph out"}, | ||
1918 | }; | ||
1919 | struct usb_mixer_interface *mixer = entry->private_data; | ||
1920 | int i, err; | ||
1921 | u8 buf[3]; | ||
1922 | |||
1923 | snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); | ||
1924 | for (i = 0; i < ARRAY_SIZE(jacks); ++i) { | ||
1925 | snd_iprintf(buffer, "%s: ", jacks[i].name); | ||
1926 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
1927 | usb_rcvctrlpipe(mixer->chip->dev, 0), | ||
1928 | GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | | ||
1929 | USB_RECIP_INTERFACE, 0, | ||
1930 | jacks[i].unitid << 8, buf, 3, 100); | ||
1931 | if (err == 3 && buf[0] == 3) | ||
1932 | snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); | ||
1933 | else | ||
1934 | snd_iprintf(buffer, "?\n"); | ||
1935 | } | ||
1936 | } | ||
1937 | |||
1938 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | ||
1939 | { | ||
1940 | static snd_device_ops_t dev_ops = { | ||
1941 | .dev_free = snd_usb_mixer_dev_free | ||
1942 | }; | ||
1943 | struct usb_mixer_interface *mixer; | ||
1944 | int err; | ||
1945 | |||
1946 | strcpy(chip->card->mixername, "USB Mixer"); | ||
1947 | |||
1948 | mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL); | ||
1949 | if (!mixer) | ||
1950 | return -ENOMEM; | ||
1951 | mixer->chip = chip; | ||
1952 | mixer->ctrlif = ctrlif; | ||
1953 | #ifdef IGNORE_CTL_ERROR | ||
1954 | mixer->ignore_ctl_error = 1; | ||
1955 | #endif | ||
1956 | mixer->id_elems = kcalloc(256, sizeof(*mixer->id_elems), GFP_KERNEL); | ||
1957 | if (!mixer->id_elems) { | ||
1958 | kfree(mixer); | ||
1959 | return -ENOMEM; | ||
1960 | } | ||
1961 | |||
1962 | if ((err = snd_usb_mixer_controls(mixer)) < 0 || | ||
1963 | (err = snd_usb_mixer_status_create(mixer)) < 0) | ||
1964 | goto _error; | ||
1965 | |||
1966 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) | ||
1967 | goto _error; | ||
1968 | |||
1969 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) { | ||
1970 | snd_info_entry_t *entry; | ||
1971 | |||
1972 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | ||
1973 | goto _error; | ||
1974 | if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) | ||
1975 | snd_info_set_text_ops(entry, mixer, 1024, | ||
1976 | snd_audigy2nx_proc_read); | ||
1977 | } | ||
1978 | |||
1979 | err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); | ||
1980 | if (err < 0) | ||
1981 | goto _error; | ||
1982 | list_add(&mixer->list, &chip->mixer_list); | ||
1983 | return 0; | ||
1984 | |||
1985 | _error: | ||
1986 | snd_usb_mixer_free(mixer); | ||
1987 | return err; | ||
1988 | } | ||
1989 | |||
1990 | void snd_usb_mixer_disconnect(struct list_head *p) | ||
1991 | { | ||
1992 | struct usb_mixer_interface *mixer; | ||
1993 | |||
1994 | mixer = list_entry(p, struct usb_mixer_interface, list); | ||
1995 | if (mixer->urb) | ||
1996 | usb_kill_urb(mixer->urb); | ||
1997 | if (mixer->rc_urb) | ||
1998 | usb_kill_urb(mixer->rc_urb); | ||
1999 | } | ||
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c index c69b4b0875f8..f05500b05ec0 100644 --- a/sound/usb/usbmixer_maps.c +++ b/sound/usb/usbmixer_maps.c | |||
@@ -26,10 +26,16 @@ struct usbmix_name_map { | |||
26 | int control; | 26 | int control; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | struct usbmix_selector_map { | ||
30 | int id; | ||
31 | int count; | ||
32 | const char **names; | ||
33 | }; | ||
34 | |||
29 | struct usbmix_ctl_map { | 35 | struct usbmix_ctl_map { |
30 | int vendor; | 36 | u32 id; |
31 | int product; | ||
32 | const struct usbmix_name_map *map; | 37 | const struct usbmix_name_map *map; |
38 | const struct usbmix_selector_map *selector_map; | ||
33 | int ignore_ctl_error; | 39 | int ignore_ctl_error; |
34 | }; | 40 | }; |
35 | 41 | ||
@@ -91,6 +97,96 @@ static struct usbmix_name_map extigy_map[] = { | |||
91 | { 0 } /* terminator */ | 97 | { 0 } /* terminator */ |
92 | }; | 98 | }; |
93 | 99 | ||
100 | /* Sound Blaster MP3+ controls mapping | ||
101 | * The default mixer channels have totally misleading names, | ||
102 | * e.g. no Master and fake PCM volume | ||
103 | * Pavel Mihaylov <bin@bash.info> | ||
104 | */ | ||
105 | static struct usbmix_name_map mp3plus_map[] = { | ||
106 | /* 1: IT pcm */ | ||
107 | /* 2: IT mic */ | ||
108 | /* 3: IT line */ | ||
109 | /* 4: IT digital in */ | ||
110 | /* 5: OT digital out */ | ||
111 | /* 6: OT speaker */ | ||
112 | /* 7: OT pcm capture */ | ||
113 | { 8, "Capture Input Source" }, /* FU, default PCM Capture Source */ | ||
114 | /* (Mic, Input 1 = Line input, Input 2 = Optical input) */ | ||
115 | { 9, "Master Playback" }, /* FU, default Speaker 1 */ | ||
116 | /* { 10, "Mic Capture", 1 }, */ /* FU, Mic Capture */ | ||
117 | /* { 10, "Mic Capture", 2 }, */ /* FU, Mic Capture */ | ||
118 | { 10, "Mic Boost", 7 }, /* FU, default Auto Gain Input */ | ||
119 | { 11, "Line Capture" }, /* FU, default PCM Capture */ | ||
120 | { 12, "Digital In Playback" }, /* FU, default PCM 1 */ | ||
121 | /* { 13, "Mic Playback" }, */ /* FU, default Mic Playback */ | ||
122 | { 14, "Line Playback" }, /* FU, default Speaker */ | ||
123 | /* 15: MU */ | ||
124 | { 0 } /* terminator */ | ||
125 | }; | ||
126 | |||
127 | /* Topology of SB Audigy 2 NX | ||
128 | |||
129 | +----------------------------->EU[27]--+ | ||
130 | | v | ||
131 | | +----------------------------------->SU[29]---->FU[22]-->Dig_OUT[24] | ||
132 | | | ^ | ||
133 | USB_IN[1]-+------------+ +->EU[17]->+->FU[11]-+ | ||
134 | | v | v | | ||
135 | Dig_IN[4]---+->FU[6]-->MU[16]->FU[18]-+->EU[21]->SU[31]----->FU[30]->Hph_OUT[20] | ||
136 | | ^ | | | ||
137 | Lin_IN[7]-+--->FU[8]---+ +->EU[23]->FU[28]------------->Spk_OUT[19] | ||
138 | | | v | ||
139 | +--->FU[12]------------------------------------->SU[14]--->USB_OUT[15] | ||
140 | | ^ | ||
141 | +->FU[13]--------------------------------------+ | ||
142 | */ | ||
143 | static struct usbmix_name_map audigy2nx_map[] = { | ||
144 | /* 1: IT pcm playback */ | ||
145 | /* 4: IT digital in */ | ||
146 | { 6, "Digital In Playback" }, /* FU */ | ||
147 | /* 7: IT line in */ | ||
148 | { 8, "Line Playback" }, /* FU */ | ||
149 | { 11, "What-U-Hear Capture" }, /* FU */ | ||
150 | { 12, "Line Capture" }, /* FU */ | ||
151 | { 13, "Digital In Capture" }, /* FU */ | ||
152 | { 14, "Capture Source" }, /* SU */ | ||
153 | /* 15: OT pcm capture */ | ||
154 | /* 16: MU w/o controls */ | ||
155 | { 17, NULL }, /* DISABLED: EU (for what?) */ | ||
156 | { 18, "Master Playback" }, /* FU */ | ||
157 | /* 19: OT speaker */ | ||
158 | /* 20: OT headphone */ | ||
159 | { 21, NULL }, /* DISABLED: EU (for what?) */ | ||
160 | { 22, "Digital Out Playback" }, /* FU */ | ||
161 | { 23, NULL }, /* DISABLED: EU (for what?) */ | ||
162 | /* 24: OT digital out */ | ||
163 | { 27, NULL }, /* DISABLED: EU (for what?) */ | ||
164 | { 28, "Speaker Playback" }, /* FU */ | ||
165 | { 29, "Digital Out Source" }, /* SU */ | ||
166 | { 30, "Headphone Playback" }, /* FU */ | ||
167 | { 31, "Headphone Source" }, /* SU */ | ||
168 | { 0 } /* terminator */ | ||
169 | }; | ||
170 | |||
171 | static struct usbmix_selector_map audigy2nx_selectors[] = { | ||
172 | { | ||
173 | .id = 14, /* Capture Source */ | ||
174 | .count = 3, | ||
175 | .names = (const char*[]) {"Line", "Digital In", "What-U-Hear"} | ||
176 | }, | ||
177 | { | ||
178 | .id = 29, /* Digital Out Source */ | ||
179 | .count = 3, | ||
180 | .names = (const char*[]) {"Front", "PCM", "Digital In"} | ||
181 | }, | ||
182 | { | ||
183 | .id = 31, /* Headphone Source */ | ||
184 | .count = 2, | ||
185 | .names = (const char*[]) {"Front", "Side"} | ||
186 | }, | ||
187 | { 0 } /* terminator */ | ||
188 | }; | ||
189 | |||
94 | /* LineX FM Transmitter entry - needed to bypass controls bug */ | 190 | /* LineX FM Transmitter entry - needed to bypass controls bug */ |
95 | static struct usbmix_name_map linex_map[] = { | 191 | static struct usbmix_name_map linex_map[] = { |
96 | /* 1: IT pcm */ | 192 | /* 1: IT pcm */ |
@@ -127,9 +223,29 @@ static struct usbmix_name_map justlink_map[] = { | |||
127 | */ | 223 | */ |
128 | 224 | ||
129 | static struct usbmix_ctl_map usbmix_ctl_maps[] = { | 225 | static struct usbmix_ctl_map usbmix_ctl_maps[] = { |
130 | { 0x41e, 0x3000, extigy_map, 1 }, | 226 | { |
131 | { 0x8bb, 0x2702, linex_map, 1 }, | 227 | .id = USB_ID(0x041e, 0x3000), |
132 | { 0xc45, 0x1158, justlink_map, 0 }, | 228 | .map = extigy_map, |
229 | .ignore_ctl_error = 1, | ||
230 | }, | ||
231 | { | ||
232 | .id = USB_ID(0x041e, 0x3010), | ||
233 | .map = mp3plus_map, | ||
234 | }, | ||
235 | { | ||
236 | .id = USB_ID(0x041e, 0x3020), | ||
237 | .map = audigy2nx_map, | ||
238 | .selector_map = audigy2nx_selectors, | ||
239 | }, | ||
240 | { | ||
241 | .id = USB_ID(0x08bb, 0x2702), | ||
242 | .map = linex_map, | ||
243 | .ignore_ctl_error = 1, | ||
244 | }, | ||
245 | { | ||
246 | .id = USB_ID(0x0c45, 0x1158), | ||
247 | .map = justlink_map, | ||
248 | }, | ||
133 | { 0 } /* terminator */ | 249 | { 0 } /* terminator */ |
134 | }; | 250 | }; |
135 | 251 | ||
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 88bbd944d4be..f74e652a1e51 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h | |||
@@ -116,6 +116,7 @@ YAMAHA_DEVICE(0x1039, NULL), | |||
116 | YAMAHA_DEVICE(0x103a, NULL), | 116 | YAMAHA_DEVICE(0x103a, NULL), |
117 | YAMAHA_DEVICE(0x103b, NULL), | 117 | YAMAHA_DEVICE(0x103b, NULL), |
118 | YAMAHA_DEVICE(0x103c, NULL), | 118 | YAMAHA_DEVICE(0x103c, NULL), |
119 | YAMAHA_DEVICE(0x103d, NULL), | ||
119 | YAMAHA_DEVICE(0x2000, "DGP-7"), | 120 | YAMAHA_DEVICE(0x2000, "DGP-7"), |
120 | YAMAHA_DEVICE(0x2001, "DGP-5"), | 121 | YAMAHA_DEVICE(0x2001, "DGP-5"), |
121 | YAMAHA_DEVICE(0x2002, NULL), | 122 | YAMAHA_DEVICE(0x2002, NULL), |
@@ -203,11 +204,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
203 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 204 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
204 | .vendor_name = "EDIROL", | 205 | .vendor_name = "EDIROL", |
205 | .product_name = "UM-4", | 206 | .product_name = "UM-4", |
206 | .ifnum = 2, | 207 | .ifnum = QUIRK_ANY_INTERFACE, |
207 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 208 | .type = QUIRK_COMPOSITE, |
208 | .data = & (const snd_usb_midi_endpoint_info_t) { | 209 | .data = (const snd_usb_audio_quirk_t[]) { |
209 | .out_cables = 0x000f, | 210 | { |
210 | .in_cables = 0x000f | 211 | .ifnum = 0, |
212 | .type = QUIRK_IGNORE_INTERFACE | ||
213 | }, | ||
214 | { | ||
215 | .ifnum = 1, | ||
216 | .type = QUIRK_IGNORE_INTERFACE | ||
217 | }, | ||
218 | { | ||
219 | .ifnum = 2, | ||
220 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
221 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
222 | .out_cables = 0x000f, | ||
223 | .in_cables = 0x000f | ||
224 | } | ||
225 | }, | ||
226 | { | ||
227 | .ifnum = -1 | ||
228 | } | ||
211 | } | 229 | } |
212 | } | 230 | } |
213 | }, | 231 | }, |
@@ -216,11 +234,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
216 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 234 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
217 | .vendor_name = "Roland", | 235 | .vendor_name = "Roland", |
218 | .product_name = "SC-8850", | 236 | .product_name = "SC-8850", |
219 | .ifnum = 2, | 237 | .ifnum = QUIRK_ANY_INTERFACE, |
220 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 238 | .type = QUIRK_COMPOSITE, |
221 | .data = & (const snd_usb_midi_endpoint_info_t) { | 239 | .data = (const snd_usb_audio_quirk_t[]) { |
222 | .out_cables = 0x003f, | 240 | { |
223 | .in_cables = 0x003f | 241 | .ifnum = 0, |
242 | .type = QUIRK_IGNORE_INTERFACE | ||
243 | }, | ||
244 | { | ||
245 | .ifnum = 1, | ||
246 | .type = QUIRK_IGNORE_INTERFACE | ||
247 | }, | ||
248 | { | ||
249 | .ifnum = 2, | ||
250 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
251 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
252 | .out_cables = 0x003f, | ||
253 | .in_cables = 0x003f | ||
254 | } | ||
255 | }, | ||
256 | { | ||
257 | .ifnum = -1 | ||
258 | } | ||
224 | } | 259 | } |
225 | } | 260 | } |
226 | }, | 261 | }, |
@@ -229,11 +264,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
229 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 264 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
230 | .vendor_name = "Roland", | 265 | .vendor_name = "Roland", |
231 | .product_name = "U-8", | 266 | .product_name = "U-8", |
232 | .ifnum = 2, | 267 | .ifnum = QUIRK_ANY_INTERFACE, |
233 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 268 | .type = QUIRK_COMPOSITE, |
234 | .data = & (const snd_usb_midi_endpoint_info_t) { | 269 | .data = (const snd_usb_audio_quirk_t[]) { |
235 | .out_cables = 0x0005, | 270 | { |
236 | .in_cables = 0x0005 | 271 | .ifnum = 0, |
272 | .type = QUIRK_IGNORE_INTERFACE | ||
273 | }, | ||
274 | { | ||
275 | .ifnum = 1, | ||
276 | .type = QUIRK_IGNORE_INTERFACE | ||
277 | }, | ||
278 | { | ||
279 | .ifnum = 2, | ||
280 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
281 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
282 | .out_cables = 0x0005, | ||
283 | .in_cables = 0x0005 | ||
284 | } | ||
285 | }, | ||
286 | { | ||
287 | .ifnum = -1 | ||
288 | } | ||
237 | } | 289 | } |
238 | } | 290 | } |
239 | }, | 291 | }, |
@@ -242,11 +294,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
242 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 294 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
243 | .vendor_name = "EDIROL", | 295 | .vendor_name = "EDIROL", |
244 | .product_name = "UM-2", | 296 | .product_name = "UM-2", |
245 | .ifnum = 2, | 297 | .ifnum = QUIRK_ANY_INTERFACE, |
246 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 298 | .type = QUIRK_COMPOSITE, |
247 | .data = & (const snd_usb_midi_endpoint_info_t) { | 299 | .data = (const snd_usb_audio_quirk_t[]) { |
248 | .out_cables = 0x0003, | 300 | { |
249 | .in_cables = 0x0003 | 301 | .ifnum = 0, |
302 | .type = QUIRK_IGNORE_INTERFACE | ||
303 | }, | ||
304 | { | ||
305 | .ifnum = 1, | ||
306 | .type = QUIRK_IGNORE_INTERFACE | ||
307 | }, | ||
308 | { | ||
309 | .ifnum = 2, | ||
310 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
311 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
312 | .out_cables = 0x0003, | ||
313 | .in_cables = 0x0003 | ||
314 | } | ||
315 | }, | ||
316 | { | ||
317 | .ifnum = -1 | ||
318 | } | ||
250 | } | 319 | } |
251 | } | 320 | } |
252 | }, | 321 | }, |
@@ -255,11 +324,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
255 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 324 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
256 | .vendor_name = "Roland", | 325 | .vendor_name = "Roland", |
257 | .product_name = "SC-8820", | 326 | .product_name = "SC-8820", |
258 | .ifnum = 2, | 327 | .ifnum = QUIRK_ANY_INTERFACE, |
259 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 328 | .type = QUIRK_COMPOSITE, |
260 | .data = & (const snd_usb_midi_endpoint_info_t) { | 329 | .data = (const snd_usb_audio_quirk_t[]) { |
261 | .out_cables = 0x0013, | 330 | { |
262 | .in_cables = 0x0013 | 331 | .ifnum = 0, |
332 | .type = QUIRK_IGNORE_INTERFACE | ||
333 | }, | ||
334 | { | ||
335 | .ifnum = 1, | ||
336 | .type = QUIRK_IGNORE_INTERFACE | ||
337 | }, | ||
338 | { | ||
339 | .ifnum = 2, | ||
340 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
341 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
342 | .out_cables = 0x0013, | ||
343 | .in_cables = 0x0013 | ||
344 | } | ||
345 | }, | ||
346 | { | ||
347 | .ifnum = -1 | ||
348 | } | ||
263 | } | 349 | } |
264 | } | 350 | } |
265 | }, | 351 | }, |
@@ -268,11 +354,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
268 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 354 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
269 | .vendor_name = "Roland", | 355 | .vendor_name = "Roland", |
270 | .product_name = "PC-300", | 356 | .product_name = "PC-300", |
271 | .ifnum = 2, | 357 | .ifnum = QUIRK_ANY_INTERFACE, |
272 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 358 | .type = QUIRK_COMPOSITE, |
273 | .data = & (const snd_usb_midi_endpoint_info_t) { | 359 | .data = (const snd_usb_audio_quirk_t[]) { |
274 | .out_cables = 0x0001, | 360 | { |
275 | .in_cables = 0x0001 | 361 | .ifnum = 0, |
362 | .type = QUIRK_IGNORE_INTERFACE | ||
363 | }, | ||
364 | { | ||
365 | .ifnum = 1, | ||
366 | .type = QUIRK_IGNORE_INTERFACE | ||
367 | }, | ||
368 | { | ||
369 | .ifnum = 2, | ||
370 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
371 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
372 | .out_cables = 0x0001, | ||
373 | .in_cables = 0x0001 | ||
374 | } | ||
375 | }, | ||
376 | { | ||
377 | .ifnum = -1 | ||
378 | } | ||
276 | } | 379 | } |
277 | } | 380 | } |
278 | }, | 381 | }, |
@@ -281,11 +384,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
281 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 384 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
282 | .vendor_name = "EDIROL", | 385 | .vendor_name = "EDIROL", |
283 | .product_name = "UM-1", | 386 | .product_name = "UM-1", |
284 | .ifnum = 2, | 387 | .ifnum = QUIRK_ANY_INTERFACE, |
285 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 388 | .type = QUIRK_COMPOSITE, |
286 | .data = & (const snd_usb_midi_endpoint_info_t) { | 389 | .data = (const snd_usb_audio_quirk_t[]) { |
287 | .out_cables = 0x0001, | 390 | { |
288 | .in_cables = 0x0001 | 391 | .ifnum = 0, |
392 | .type = QUIRK_IGNORE_INTERFACE | ||
393 | }, | ||
394 | { | ||
395 | .ifnum = 1, | ||
396 | .type = QUIRK_IGNORE_INTERFACE | ||
397 | }, | ||
398 | { | ||
399 | .ifnum = 2, | ||
400 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
401 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
402 | .out_cables = 0x0001, | ||
403 | .in_cables = 0x0001 | ||
404 | } | ||
405 | }, | ||
406 | { | ||
407 | .ifnum = -1 | ||
408 | } | ||
289 | } | 409 | } |
290 | } | 410 | } |
291 | }, | 411 | }, |
@@ -294,11 +414,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
294 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 414 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
295 | .vendor_name = "Roland", | 415 | .vendor_name = "Roland", |
296 | .product_name = "SK-500", | 416 | .product_name = "SK-500", |
297 | .ifnum = 2, | 417 | .ifnum = QUIRK_ANY_INTERFACE, |
298 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 418 | .type = QUIRK_COMPOSITE, |
299 | .data = & (const snd_usb_midi_endpoint_info_t) { | 419 | .data = (const snd_usb_audio_quirk_t[]) { |
300 | .out_cables = 0x0013, | 420 | { |
301 | .in_cables = 0x0013 | 421 | .ifnum = 0, |
422 | .type = QUIRK_IGNORE_INTERFACE | ||
423 | }, | ||
424 | { | ||
425 | .ifnum = 1, | ||
426 | .type = QUIRK_IGNORE_INTERFACE | ||
427 | }, | ||
428 | { | ||
429 | .ifnum = 2, | ||
430 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
431 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
432 | .out_cables = 0x0013, | ||
433 | .in_cables = 0x0013 | ||
434 | } | ||
435 | }, | ||
436 | { | ||
437 | .ifnum = -1 | ||
438 | } | ||
302 | } | 439 | } |
303 | } | 440 | } |
304 | }, | 441 | }, |
@@ -421,11 +558,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
421 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 558 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
422 | .vendor_name = "EDIROL", | 559 | .vendor_name = "EDIROL", |
423 | .product_name = "SD-90", | 560 | .product_name = "SD-90", |
424 | .ifnum = 2, | 561 | .ifnum = QUIRK_ANY_INTERFACE, |
425 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 562 | .type = QUIRK_COMPOSITE, |
426 | .data = & (const snd_usb_midi_endpoint_info_t) { | 563 | .data = (const snd_usb_audio_quirk_t[]) { |
427 | .out_cables = 0x000f, | 564 | { |
428 | .in_cables = 0x000f | 565 | .ifnum = 0, |
566 | .type = QUIRK_IGNORE_INTERFACE | ||
567 | }, | ||
568 | { | ||
569 | .ifnum = 1, | ||
570 | .type = QUIRK_IGNORE_INTERFACE | ||
571 | }, | ||
572 | { | ||
573 | .ifnum = 2, | ||
574 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
575 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
576 | .out_cables = 0x000f, | ||
577 | .in_cables = 0x000f | ||
578 | } | ||
579 | }, | ||
580 | { | ||
581 | .ifnum = -1 | ||
582 | } | ||
429 | } | 583 | } |
430 | } | 584 | } |
431 | }, | 585 | }, |
@@ -434,11 +588,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
434 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 588 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
435 | .vendor_name = "Roland", | 589 | .vendor_name = "Roland", |
436 | .product_name = "MMP-2", | 590 | .product_name = "MMP-2", |
437 | .ifnum = 2, | 591 | .ifnum = QUIRK_ANY_INTERFACE, |
438 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 592 | .type = QUIRK_COMPOSITE, |
439 | .data = & (const snd_usb_midi_endpoint_info_t) { | 593 | .data = (const snd_usb_audio_quirk_t[]) { |
440 | .out_cables = 0x0001, | 594 | { |
441 | .in_cables = 0x0001 | 595 | .ifnum = 0, |
596 | .type = QUIRK_IGNORE_INTERFACE | ||
597 | }, | ||
598 | { | ||
599 | .ifnum = 1, | ||
600 | .type = QUIRK_IGNORE_INTERFACE | ||
601 | }, | ||
602 | { | ||
603 | .ifnum = 2, | ||
604 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
605 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
606 | .out_cables = 0x0001, | ||
607 | .in_cables = 0x0001 | ||
608 | } | ||
609 | }, | ||
610 | { | ||
611 | .ifnum = -1 | ||
612 | } | ||
442 | } | 613 | } |
443 | } | 614 | } |
444 | }, | 615 | }, |
@@ -609,15 +780,33 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
609 | } | 780 | } |
610 | }, | 781 | }, |
611 | { | 782 | { |
783 | /* | ||
784 | * This quirk is for the "Advanced Driver" mode. If off, the GS-10 | ||
785 | * has ID 0x003c and is standard compliant, but has only 16-bit PCM | ||
786 | * and no MIDI. | ||
787 | */ | ||
612 | USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b), | 788 | USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b), |
613 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 789 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
614 | .vendor_name = "BOSS", | 790 | .vendor_name = "BOSS", |
615 | .product_name = "GS-10", | 791 | .product_name = "GS-10", |
616 | .ifnum = 3, | 792 | .ifnum = QUIRK_ANY_INTERFACE, |
617 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 793 | .type = QUIRK_COMPOSITE, |
618 | .data = & (const snd_usb_midi_endpoint_info_t) { | 794 | .data = & (const snd_usb_audio_quirk_t[]) { |
619 | .out_cables = 0x0003, | 795 | { |
620 | .in_cables = 0x0003 | 796 | .ifnum = 1, |
797 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
798 | }, | ||
799 | { | ||
800 | .ifnum = 2, | ||
801 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
802 | }, | ||
803 | { | ||
804 | .ifnum = 3, | ||
805 | .type = QUIRK_MIDI_STANDARD_INTERFACE | ||
806 | }, | ||
807 | { | ||
808 | .ifnum = -1 | ||
809 | } | ||
621 | } | 810 | } |
622 | } | 811 | } |
623 | }, | 812 | }, |
@@ -1071,7 +1260,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1071 | /* Mark of the Unicorn devices */ | 1260 | /* Mark of the Unicorn devices */ |
1072 | { | 1261 | { |
1073 | /* thanks to Robert A. Lerche <ral 'at' msbit.com> */ | 1262 | /* thanks to Robert A. Lerche <ral 'at' msbit.com> */ |
1074 | USB_DEVICE(0x07fd, 0x0001), | 1263 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | |
1264 | USB_DEVICE_ID_MATCH_PRODUCT | | ||
1265 | USB_DEVICE_ID_MATCH_DEV_SUBCLASS, | ||
1266 | .idVendor = 0x07fd, | ||
1267 | .idProduct = 0x0001, | ||
1268 | .bDeviceSubClass = 2, | ||
1075 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 1269 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
1076 | .vendor_name = "MOTU", | 1270 | .vendor_name = "MOTU", |
1077 | .product_name = "Fastlane", | 1271 | .product_name = "Fastlane", |
@@ -1080,7 +1274,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1080 | .data = & (const snd_usb_audio_quirk_t[]) { | 1274 | .data = & (const snd_usb_audio_quirk_t[]) { |
1081 | { | 1275 | { |
1082 | .ifnum = 0, | 1276 | .ifnum = 0, |
1083 | .type = QUIRK_MIDI_MOTU | 1277 | .type = QUIRK_MIDI_RAW |
1084 | }, | 1278 | }, |
1085 | { | 1279 | { |
1086 | .ifnum = 1, | 1280 | .ifnum = 1, |
@@ -1185,6 +1379,25 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1185 | }, | 1379 | }, |
1186 | 1380 | ||
1187 | { | 1381 | { |
1382 | USB_DEVICE(0x4752, 0x0011), | ||
1383 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | ||
1384 | .vendor_name = "Miditech", | ||
1385 | .product_name = "Midistart-2", | ||
1386 | .ifnum = 0, | ||
1387 | .type = QUIRK_MIDI_MIDITECH | ||
1388 | } | ||
1389 | }, | ||
1390 | { | ||
1391 | USB_DEVICE(0x7104, 0x2202), | ||
1392 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | ||
1393 | .vendor_name = "Miditech", | ||
1394 | .product_name = "MidiStudio-2", | ||
1395 | .ifnum = 0, | ||
1396 | .type = QUIRK_MIDI_MIDITECH | ||
1397 | } | ||
1398 | }, | ||
1399 | |||
1400 | { | ||
1188 | /* | 1401 | /* |
1189 | * Some USB MIDI devices don't have an audio control interface, | 1402 | * Some USB MIDI devices don't have an audio control interface, |
1190 | * so we have to grab MIDI streaming interfaces here. | 1403 | * so we have to grab MIDI streaming interfaces here. |
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index bef9b0c142c4..0281a362857a 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c | |||
@@ -232,8 +232,7 @@ static int snd_usX2Y_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp) | |||
232 | if (err) | 232 | if (err) |
233 | return err; | 233 | return err; |
234 | if (dsp->index == 1) { | 234 | if (dsp->index == 1) { |
235 | set_current_state(TASK_UNINTERRUPTIBLE); | 235 | msleep(250); // give the device some time |
236 | schedule_timeout(HZ/4); // give the device some time | ||
237 | err = usX2Y_AsyncSeq04_init(priv); | 236 | err = usX2Y_AsyncSeq04_init(priv); |
238 | if (err) { | 237 | if (err) { |
239 | snd_printk("usX2Y_AsyncSeq04_init error \n"); | 238 | snd_printk("usX2Y_AsyncSeq04_init error \n"); |
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index b06a267e5dac..e6e6da159671 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c | |||
@@ -1,6 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * usbusy2y.c - ALSA USB US-428 Driver | 2 | * usbusy2y.c - ALSA USB US-428 Driver |
3 | * | 3 | * |
4 | 2005-04-14 Karsten Wiese | ||
5 | Version 0.8.7.2: | ||
6 | Call snd_card_free() instead of snd_card_free_in_thread() to prevent oops with dead keyboard symptom. | ||
7 | Tested ok with kernel 2.6.12-rc2. | ||
8 | |||
4 | 2004-12-14 Karsten Wiese | 9 | 2004-12-14 Karsten Wiese |
5 | Version 0.8.7.1: | 10 | Version 0.8.7.1: |
6 | snd_pcm_open for rawusb pcm-devices now returns -EBUSY if called without rawusb's hwdep device being open. | 11 | snd_pcm_open for rawusb pcm-devices now returns -EBUSY if called without rawusb's hwdep device being open. |
@@ -143,7 +148,7 @@ | |||
143 | 148 | ||
144 | 149 | ||
145 | MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>"); | 150 | MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>"); |
146 | MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.1"); | 151 | MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2"); |
147 | MODULE_LICENSE("GPL"); | 152 | MODULE_LICENSE("GPL"); |
148 | MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}"); | 153 | MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}"); |
149 | 154 | ||
@@ -430,8 +435,6 @@ static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr) | |||
430 | if (ptr) { | 435 | if (ptr) { |
431 | usX2Ydev_t* usX2Y = usX2Y((snd_card_t*)ptr); | 436 | usX2Ydev_t* usX2Y = usX2Y((snd_card_t*)ptr); |
432 | struct list_head* p; | 437 | struct list_head* p; |
433 | if (usX2Y->chip_status == USX2Y_STAT_CHIP_HUP) // on 2.6.1 kernel snd_usbmidi_disconnect() | ||
434 | return; // calls us back. better leave :-) . | ||
435 | usX2Y->chip.shutdown = 1; | 438 | usX2Y->chip.shutdown = 1; |
436 | usX2Y->chip_status = USX2Y_STAT_CHIP_HUP; | 439 | usX2Y->chip_status = USX2Y_STAT_CHIP_HUP; |
437 | usX2Y_unlinkSeq(&usX2Y->AS04); | 440 | usX2Y_unlinkSeq(&usX2Y->AS04); |
@@ -439,11 +442,11 @@ static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr) | |||
439 | snd_card_disconnect((snd_card_t*)ptr); | 442 | snd_card_disconnect((snd_card_t*)ptr); |
440 | /* release the midi resources */ | 443 | /* release the midi resources */ |
441 | list_for_each(p, &usX2Y->chip.midi_list) { | 444 | list_for_each(p, &usX2Y->chip.midi_list) { |
442 | snd_usbmidi_disconnect(p, &snd_usX2Y_usb_driver); | 445 | snd_usbmidi_disconnect(p); |
443 | } | 446 | } |
444 | if (usX2Y->us428ctls_sharedmem) | 447 | if (usX2Y->us428ctls_sharedmem) |
445 | wake_up(&usX2Y->us428ctls_wait_queue_head); | 448 | wake_up(&usX2Y->us428ctls_wait_queue_head); |
446 | snd_card_free_in_thread((snd_card_t*)ptr); | 449 | snd_card_free((snd_card_t*)ptr); |
447 | } | 450 | } |
448 | } | 451 | } |
449 | 452 | ||
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 4c292e090069..62dfd28b3b07 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c | |||
@@ -401,10 +401,8 @@ static void usX2Y_urbs_release(snd_usX2Y_substream_t *subs) | |||
401 | for (i = 0; i < NRURBS; i++) | 401 | for (i = 0; i < NRURBS; i++) |
402 | usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]); | 402 | usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]); |
403 | 403 | ||
404 | if (subs->tmpbuf) { | 404 | kfree(subs->tmpbuf); |
405 | kfree(subs->tmpbuf); | 405 | subs->tmpbuf = NULL; |
406 | subs->tmpbuf = NULL; | ||
407 | } | ||
408 | } | 406 | } |
409 | /* | 407 | /* |
410 | * initialize a substream's urbs | 408 | * initialize a substream's urbs |
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index bb2c8e9000c6..ef28061287f2 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c | |||
@@ -50,6 +50,7 @@ | |||
50 | Currently rawusb dma pcm buffer transport (this file) is only available to snd-usb-usx2y. | 50 | Currently rawusb dma pcm buffer transport (this file) is only available to snd-usb-usx2y. |
51 | */ | 51 | */ |
52 | 52 | ||
53 | #include <linux/delay.h> | ||
53 | #include "usbusx2yaudio.c" | 54 | #include "usbusx2yaudio.c" |
54 | 55 | ||
55 | #if defined(USX2Y_NRPACKS_VARIABLE) || (!defined(USX2Y_NRPACKS_VARIABLE) && USX2Y_NRPACKS == 1) | 56 | #if defined(USX2Y_NRPACKS_VARIABLE) || (!defined(USX2Y_NRPACKS_VARIABLE) && USX2Y_NRPACKS == 1) |
@@ -520,11 +521,8 @@ static int snd_usX2Y_usbpcm_prepare(snd_pcm_substream_t *substream) | |||
520 | usX2Y->hwdep_pcm_shm->playback_iso_start = -1; | 521 | usX2Y->hwdep_pcm_shm->playback_iso_start = -1; |
521 | if (atomic_read(&subs->state) < state_PREPARED) { | 522 | if (atomic_read(&subs->state) < state_PREPARED) { |
522 | while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > usX2Y->hwdep_pcm_shm->captured_iso_frames) { | 523 | while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > usX2Y->hwdep_pcm_shm->captured_iso_frames) { |
523 | signed long timeout; | ||
524 | snd_printd("Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", usX2Y_iso_frames_per_buffer(runtime, usX2Y), usX2Y->hwdep_pcm_shm->captured_iso_frames); | 524 | snd_printd("Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", usX2Y_iso_frames_per_buffer(runtime, usX2Y), usX2Y->hwdep_pcm_shm->captured_iso_frames); |
525 | set_current_state(TASK_INTERRUPTIBLE); | 525 | if (msleep_interruptible(10)) { |
526 | timeout = schedule_timeout(HZ/100 + 1); | ||
527 | if (signal_pending(current)) { | ||
528 | err = -ERESTARTSYS; | 526 | err = -ERESTARTSYS; |
529 | goto up_prepare_mutex; | 527 | goto up_prepare_mutex; |
530 | } | 528 | } |