diff options
Diffstat (limited to 'sound')
110 files changed, 6769 insertions, 1251 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..34c1740aa6e9 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig | |||
@@ -14,5 +14,11 @@ 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 | 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 | |||
17 | endmenu | 23 | endmenu |
18 | 24 | ||
diff --git a/sound/arm/Makefile b/sound/arm/Makefile index d7e7dc0c3cdf..f74ec28e1068 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile | |||
@@ -6,3 +6,6 @@ snd-sa11xx-uda1341-objs := sa11xx-uda1341.o | |||
6 | 6 | ||
7 | # Toplevel Module Dependency | 7 | # Toplevel Module Dependency |
8 | obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o | 8 | obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o |
9 | |||
10 | obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o | ||
11 | snd-aaci-objs := aaci.o devdma.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/core/control.c b/sound/core/control.c index f4ea6bff1dd3..4e39a2103d0a 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -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/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 1a805020f57a..468fca8894d9 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -125,17 +125,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) | 125 | static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames) |
126 | { | 126 | { |
127 | snd_pcm_runtime_t *runtime = substream->runtime; | 127 | snd_pcm_runtime_t *runtime = substream->runtime; |
128 | snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream); | 128 | long buffer_size = snd_pcm_lib_buffer_bytes(substream); |
129 | frames = frames_to_bytes(runtime, frames); | 129 | long bytes = frames_to_bytes(runtime, frames); |
130 | if (buffer_size == runtime->oss.buffer_bytes) | 130 | if (buffer_size == runtime->oss.buffer_bytes) |
131 | return frames; | 131 | return bytes; |
132 | return (runtime->oss.buffer_bytes * frames) / buffer_size; | 132 | #if BITS_PER_LONG >= 64 |
133 | return runtime->oss.buffer_bytes * bytes / buffer_size; | ||
134 | #else | ||
135 | { | ||
136 | u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes; | ||
137 | u32 rem; | ||
138 | div64_32(&bsize, buffer_size, &rem); | ||
139 | return (long)bsize; | ||
140 | } | ||
141 | #endif | ||
133 | } | 142 | } |
134 | 143 | ||
135 | static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes) | 144 | static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes) |
136 | { | 145 | { |
137 | snd_pcm_runtime_t *runtime = substream->runtime; | 146 | snd_pcm_runtime_t *runtime = substream->runtime; |
138 | snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream); | 147 | long buffer_size = snd_pcm_lib_buffer_bytes(substream); |
139 | if (buffer_size == runtime->oss.buffer_bytes) | 148 | if (buffer_size == runtime->oss.buffer_bytes) |
140 | return bytes_to_frames(runtime, bytes); | 149 | return bytes_to_frames(runtime, bytes); |
141 | return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); | 150 | return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); |
@@ -464,7 +473,8 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream) | |||
464 | sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; | 473 | sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; |
465 | sw_params->period_step = 1; | 474 | sw_params->period_step = 1; |
466 | sw_params->sleep_min = 0; | 475 | sw_params->sleep_min = 0; |
467 | sw_params->avail_min = 1; | 476 | sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? |
477 | 1 : runtime->period_size; | ||
468 | sw_params->xfer_align = 1; | 478 | sw_params->xfer_align = 1; |
469 | if (atomic_read(&runtime->mmap_count) || | 479 | if (atomic_read(&runtime->mmap_count) || |
470 | (substream->oss.setup && substream->oss.setup->nosilence)) { | 480 | (substream->oss.setup && substream->oss.setup->nosilence)) { |
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..4e582415a086 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; |
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 18247db45db6..57be9155eb62 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c | |||
@@ -414,6 +414,8 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev) | |||
414 | if (newclient) | 414 | if (newclient) |
415 | synths[card->number] = client; | 415 | synths[card->number] = client; |
416 | up(®ister_mutex); | 416 | up(®ister_mutex); |
417 | kfree(info); | ||
418 | kfree(port); | ||
417 | return 0; /* success */ | 419 | return 0; /* success */ |
418 | 420 | ||
419 | __nomem: | 421 | __nomem: |
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 21e569062bc3..df1e2bb39745 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c | |||
@@ -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 33eaa5e5d284..0815fadeb3ec 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.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..d67a5e91a108 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -69,6 +69,7 @@ typedef struct { | |||
69 | struct timespec tstamp; /* trigger tstamp */ | 69 | struct timespec tstamp; /* trigger tstamp */ |
70 | wait_queue_head_t qchange_sleep; | 70 | wait_queue_head_t qchange_sleep; |
71 | struct fasync_struct *fasync; | 71 | struct fasync_struct *fasync; |
72 | struct semaphore tread_sem; | ||
72 | } snd_timer_user_t; | 73 | } snd_timer_user_t; |
73 | 74 | ||
74 | /* list of timers */ | 75 | /* list of timers */ |
@@ -844,7 +845,7 @@ int snd_timer_dev_register(snd_device_t *dev) | |||
844 | return 0; | 845 | return 0; |
845 | } | 846 | } |
846 | 847 | ||
847 | int snd_timer_unregister(snd_timer_t *timer) | 848 | static int snd_timer_unregister(snd_timer_t *timer) |
848 | { | 849 | { |
849 | struct list_head *p, *n; | 850 | struct list_head *p, *n; |
850 | snd_timer_instance_t *ti; | 851 | snd_timer_instance_t *ti; |
@@ -945,11 +946,6 @@ struct snd_timer_system_private { | |||
945 | unsigned long correction; | 946 | unsigned long correction; |
946 | }; | 947 | }; |
947 | 948 | ||
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) | 949 | static void snd_timer_s_function(unsigned long data) |
954 | { | 950 | { |
955 | snd_timer_t *timer = (snd_timer_t *)data; | 951 | snd_timer_t *timer = (snd_timer_t *)data; |
@@ -1208,6 +1204,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) | |||
1208 | return -ENOMEM; | 1204 | return -ENOMEM; |
1209 | spin_lock_init(&tu->qlock); | 1205 | spin_lock_init(&tu->qlock); |
1210 | init_waitqueue_head(&tu->qchange_sleep); | 1206 | init_waitqueue_head(&tu->qchange_sleep); |
1207 | init_MUTEX(&tu->tread_sem); | ||
1211 | tu->ticks = 1; | 1208 | tu->ticks = 1; |
1212 | tu->queue_size = 128; | 1209 | tu->queue_size = 128; |
1213 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1210 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); |
@@ -1454,18 +1451,23 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * | |||
1454 | snd_timer_user_t *tu; | 1451 | snd_timer_user_t *tu; |
1455 | snd_timer_select_t tselect; | 1452 | snd_timer_select_t tselect; |
1456 | char str[32]; | 1453 | char str[32]; |
1457 | int err; | 1454 | int err = 0; |
1458 | 1455 | ||
1459 | tu = file->private_data; | 1456 | tu = file->private_data; |
1460 | if (tu->timeri) | 1457 | down(&tu->tread_sem); |
1458 | if (tu->timeri) { | ||
1461 | snd_timer_close(tu->timeri); | 1459 | snd_timer_close(tu->timeri); |
1462 | if (copy_from_user(&tselect, _tselect, sizeof(tselect))) | 1460 | tu->timeri = NULL; |
1463 | return -EFAULT; | 1461 | } |
1462 | if (copy_from_user(&tselect, _tselect, sizeof(tselect))) { | ||
1463 | err = -EFAULT; | ||
1464 | goto __err; | ||
1465 | } | ||
1464 | sprintf(str, "application %i", current->pid); | 1466 | sprintf(str, "application %i", current->pid); |
1465 | if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) | 1467 | if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) |
1466 | tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; | 1468 | tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; |
1467 | if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) | 1469 | if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) |
1468 | return err; | 1470 | goto __err; |
1469 | 1471 | ||
1470 | if (tu->queue) { | 1472 | if (tu->queue) { |
1471 | kfree(tu->queue); | 1473 | kfree(tu->queue); |
@@ -1477,23 +1479,27 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * | |||
1477 | } | 1479 | } |
1478 | if (tu->tread) { | 1480 | if (tu->tread) { |
1479 | tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); | 1481 | tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); |
1480 | if (tu->tqueue == NULL) { | 1482 | if (tu->tqueue == NULL) |
1481 | snd_timer_close(tu->timeri); | 1483 | err = -ENOMEM; |
1482 | return -ENOMEM; | ||
1483 | } | ||
1484 | } else { | 1484 | } else { |
1485 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1485 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); |
1486 | if (tu->queue == NULL) { | 1486 | if (tu->queue == NULL) |
1487 | snd_timer_close(tu->timeri); | 1487 | err = -ENOMEM; |
1488 | return -ENOMEM; | ||
1489 | } | ||
1490 | } | 1488 | } |
1491 | 1489 | ||
1492 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; | 1490 | if (err < 0) { |
1493 | tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | 1491 | snd_timer_close(tu->timeri); |
1494 | tu->timeri->ccallback = snd_timer_user_ccallback; | 1492 | tu->timeri = NULL; |
1495 | tu->timeri->callback_data = (void *)tu; | 1493 | } else { |
1496 | return 0; | 1494 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; |
1495 | tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | ||
1496 | tu->timeri->ccallback = snd_timer_user_ccallback; | ||
1497 | tu->timeri->callback_data = (void *)tu; | ||
1498 | } | ||
1499 | |||
1500 | __err: | ||
1501 | up(&tu->tread_sem); | ||
1502 | return err; | ||
1497 | } | 1503 | } |
1498 | 1504 | ||
1499 | static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) | 1505 | static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) |
@@ -1669,6 +1675,23 @@ static int snd_timer_user_continue(struct file *file) | |||
1669 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; | 1675 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; |
1670 | } | 1676 | } |
1671 | 1677 | ||
1678 | static int snd_timer_user_pause(struct file *file) | ||
1679 | { | ||
1680 | int err; | ||
1681 | snd_timer_user_t *tu; | ||
1682 | |||
1683 | tu = file->private_data; | ||
1684 | snd_assert(tu->timeri != NULL, return -ENXIO); | ||
1685 | return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; | ||
1686 | } | ||
1687 | |||
1688 | enum { | ||
1689 | SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20), | ||
1690 | SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21), | ||
1691 | SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22), | ||
1692 | SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), | ||
1693 | }; | ||
1694 | |||
1672 | static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1695 | static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1673 | { | 1696 | { |
1674 | snd_timer_user_t *tu; | 1697 | snd_timer_user_t *tu; |
@@ -1685,11 +1708,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l | |||
1685 | { | 1708 | { |
1686 | int xarg; | 1709 | int xarg; |
1687 | 1710 | ||
1688 | if (tu->timeri) /* too late */ | 1711 | down(&tu->tread_sem); |
1712 | if (tu->timeri) { /* too late */ | ||
1713 | up(&tu->tread_sem); | ||
1689 | return -EBUSY; | 1714 | return -EBUSY; |
1690 | if (get_user(xarg, p)) | 1715 | } |
1716 | if (get_user(xarg, p)) { | ||
1717 | up(&tu->tread_sem); | ||
1691 | return -EFAULT; | 1718 | return -EFAULT; |
1719 | } | ||
1692 | tu->tread = xarg ? 1 : 0; | 1720 | tu->tread = xarg ? 1 : 0; |
1721 | up(&tu->tread_sem); | ||
1693 | return 0; | 1722 | return 0; |
1694 | } | 1723 | } |
1695 | case SNDRV_TIMER_IOCTL_GINFO: | 1724 | case SNDRV_TIMER_IOCTL_GINFO: |
@@ -1707,11 +1736,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l | |||
1707 | case SNDRV_TIMER_IOCTL_STATUS: | 1736 | case SNDRV_TIMER_IOCTL_STATUS: |
1708 | return snd_timer_user_status(file, argp); | 1737 | return snd_timer_user_status(file, argp); |
1709 | case SNDRV_TIMER_IOCTL_START: | 1738 | case SNDRV_TIMER_IOCTL_START: |
1739 | case SNDRV_TIMER_IOCTL_START_OLD: | ||
1710 | return snd_timer_user_start(file); | 1740 | return snd_timer_user_start(file); |
1711 | case SNDRV_TIMER_IOCTL_STOP: | 1741 | case SNDRV_TIMER_IOCTL_STOP: |
1742 | case SNDRV_TIMER_IOCTL_STOP_OLD: | ||
1712 | return snd_timer_user_stop(file); | 1743 | return snd_timer_user_stop(file); |
1713 | case SNDRV_TIMER_IOCTL_CONTINUE: | 1744 | case SNDRV_TIMER_IOCTL_CONTINUE: |
1745 | case SNDRV_TIMER_IOCTL_CONTINUE_OLD: | ||
1714 | return snd_timer_user_continue(file); | 1746 | return snd_timer_user_continue(file); |
1747 | case SNDRV_TIMER_IOCTL_PAUSE: | ||
1748 | case SNDRV_TIMER_IOCTL_PAUSE_OLD: | ||
1749 | return snd_timer_user_pause(file); | ||
1715 | } | 1750 | } |
1716 | return -ENOTTY; | 1751 | return -ENOTTY; |
1717 | } | 1752 | } |
@@ -1898,4 +1933,3 @@ EXPORT_SYMBOL(snd_timer_global_free); | |||
1898 | EXPORT_SYMBOL(snd_timer_global_register); | 1933 | EXPORT_SYMBOL(snd_timer_global_register); |
1899 | EXPORT_SYMBOL(snd_timer_global_unregister); | 1934 | EXPORT_SYMBOL(snd_timer_global_unregister); |
1900 | EXPORT_SYMBOL(snd_timer_interrupt); | 1935 | 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/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/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..94bbd344be5e 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c | |||
@@ -459,7 +459,6 @@ EXPORT_SYMBOL(snd_gf1_write16); | |||
459 | EXPORT_SYMBOL(snd_gf1_look16); | 459 | EXPORT_SYMBOL(snd_gf1_look16); |
460 | EXPORT_SYMBOL(snd_gf1_i_write8); | 460 | EXPORT_SYMBOL(snd_gf1_i_write8); |
461 | EXPORT_SYMBOL(snd_gf1_i_look8); | 461 | EXPORT_SYMBOL(snd_gf1_i_look8); |
462 | EXPORT_SYMBOL(snd_gf1_i_write16); | ||
463 | EXPORT_SYMBOL(snd_gf1_i_look16); | 462 | EXPORT_SYMBOL(snd_gf1_i_look16); |
464 | EXPORT_SYMBOL(snd_gf1_dram_addr); | 463 | EXPORT_SYMBOL(snd_gf1_dram_addr); |
465 | EXPORT_SYMBOL(snd_gf1_write_addr); | 464 | EXPORT_SYMBOL(snd_gf1_write_addr); |
@@ -470,8 +469,6 @@ EXPORT_SYMBOL(snd_gf1_alloc_voice); | |||
470 | EXPORT_SYMBOL(snd_gf1_free_voice); | 469 | EXPORT_SYMBOL(snd_gf1_free_voice); |
471 | EXPORT_SYMBOL(snd_gf1_ctrl_stop); | 470 | EXPORT_SYMBOL(snd_gf1_ctrl_stop); |
472 | EXPORT_SYMBOL(snd_gf1_stop_voice); | 471 | EXPORT_SYMBOL(snd_gf1_stop_voice); |
473 | EXPORT_SYMBOL(snd_gf1_start); | ||
474 | EXPORT_SYMBOL(snd_gf1_stop); | ||
475 | /* gus_mixer.c */ | 472 | /* gus_mixer.c */ |
476 | EXPORT_SYMBOL(snd_gf1_new_mixer); | 473 | EXPORT_SYMBOL(snd_gf1_new_mixer); |
477 | /* gus_pcm.c */ | 474 | /* gus_pcm.c */ |
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index bfc2b91001d5..609838e8ef67 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c | |||
@@ -39,8 +39,8 @@ void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup) | |||
39 | } | 39 | } |
40 | } | 40 | } |
41 | 41 | ||
42 | snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc, | 42 | static snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc, |
43 | snd_gf1_mem_block_t * block) | 43 | snd_gf1_mem_block_t * block) |
44 | { | 44 | { |
45 | snd_gf1_mem_block_t *pblock, *nblock; | 45 | snd_gf1_mem_block_t *pblock, *nblock; |
46 | 46 | ||
@@ -105,8 +105,8 @@ int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block) | |||
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
107 | 107 | ||
108 | snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc, | 108 | static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc, |
109 | unsigned int address) | 109 | unsigned int address) |
110 | { | 110 | { |
111 | snd_gf1_mem_block_t *block; | 111 | snd_gf1_mem_block_t *block; |
112 | 112 | ||
@@ -118,8 +118,8 @@ snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc, | |||
118 | return NULL; | 118 | return NULL; |
119 | } | 119 | } |
120 | 120 | ||
121 | snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc, | 121 | static snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc, |
122 | unsigned int *share_id) | 122 | unsigned int *share_id) |
123 | { | 123 | { |
124 | snd_gf1_mem_block_t *block; | 124 | snd_gf1_mem_block_t *block; |
125 | 125 | ||
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/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 0b024ec1f709..36a33ae9ae03 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 }, |
@@ -462,12 +463,14 @@ int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u | |||
462 | { | 463 | { |
463 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 464 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); |
464 | struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; | 465 | struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; |
465 | unsigned short val; | 466 | unsigned short val, bitmask; |
466 | 467 | ||
468 | for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) | ||
469 | ; | ||
467 | val = snd_ac97_read_cache(ac97, e->reg); | 470 | val = snd_ac97_read_cache(ac97, e->reg); |
468 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (e->mask - 1); | 471 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); |
469 | if (e->shift_l != e->shift_r) | 472 | if (e->shift_l != e->shift_r) |
470 | ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (e->mask - 1); | 473 | ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1); |
471 | 474 | ||
472 | return 0; | 475 | return 0; |
473 | } | 476 | } |
@@ -477,17 +480,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); | 480 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); |
478 | struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; | 481 | struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value; |
479 | unsigned short val; | 482 | unsigned short val; |
480 | unsigned short mask; | 483 | unsigned short mask, bitmask; |
481 | 484 | ||
485 | for (bitmask = 1; bitmask < e->mask; bitmask <<= 1) | ||
486 | ; | ||
482 | if (ucontrol->value.enumerated.item[0] > e->mask - 1) | 487 | if (ucontrol->value.enumerated.item[0] > e->mask - 1) |
483 | return -EINVAL; | 488 | return -EINVAL; |
484 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | 489 | val = ucontrol->value.enumerated.item[0] << e->shift_l; |
485 | mask = (e->mask - 1) << e->shift_l; | 490 | mask = (bitmask - 1) << e->shift_l; |
486 | if (e->shift_l != e->shift_r) { | 491 | if (e->shift_l != e->shift_r) { |
487 | if (ucontrol->value.enumerated.item[1] > e->mask - 1) | 492 | if (ucontrol->value.enumerated.item[1] > e->mask - 1) |
488 | return -EINVAL; | 493 | return -EINVAL; |
489 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 494 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
490 | mask |= (e->mask - 1) << e->shift_r; | 495 | mask |= (bitmask - 1) << e->shift_r; |
491 | } | 496 | } |
492 | return snd_ac97_update_bits(ac97, e->reg, mask, val); | 497 | return snd_ac97_update_bits(ac97, e->reg, mask, val); |
493 | } | 498 | } |
@@ -658,11 +663,6 @@ 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) | 663 | AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1) |
659 | }; | 664 | }; |
660 | 665 | ||
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 = | 666 | static const snd_kcontrol_new_t snd_ac97_control_eapd = |
667 | AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1); | 667 | AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1); |
668 | 668 | ||
@@ -1072,9 +1072,9 @@ static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max | |||
1072 | unsigned short val; | 1072 | unsigned short val; |
1073 | snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8)); | 1073 | snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8)); |
1074 | val = snd_ac97_read(ac97, reg); | 1074 | val = snd_ac97_read(ac97, reg); |
1075 | if (! *lo_max && (val & cbit[i])) | 1075 | if (! *lo_max && (val & 0x7f) == cbit[i]) |
1076 | *lo_max = max[i]; | 1076 | *lo_max = max[i]; |
1077 | if (! *hi_max && (val & (cbit[i] << 8))) | 1077 | if (! *hi_max && ((val >> 8) & 0x7f) == cbit[i]) |
1078 | *hi_max = max[i]; | 1078 | *hi_max = max[i]; |
1079 | if (*lo_max && *hi_max) | 1079 | if (*lo_max && *hi_max) |
1080 | break; | 1080 | break; |
@@ -1872,7 +1872,11 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97) | |||
1872 | goto __access_ok; | 1872 | goto __access_ok; |
1873 | } | 1873 | } |
1874 | 1874 | ||
1875 | snd_ac97_write(ac97, AC97_RESET, 0); /* reset to defaults */ | 1875 | /* reset to defaults */ |
1876 | if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO)) | ||
1877 | snd_ac97_write(ac97, AC97_RESET, 0); | ||
1878 | if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM)) | ||
1879 | snd_ac97_write(ac97, AC97_EXTENDED_MID, 0); | ||
1876 | if (bus->ops->wait) | 1880 | if (bus->ops->wait) |
1877 | bus->ops->wait(ac97); | 1881 | bus->ops->wait(ac97); |
1878 | else { | 1882 | else { |
@@ -1964,21 +1968,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 */ | 1968 | /* note: it's important to set the rate at first */ |
1965 | tmp = AC97_MEA_GPIO; | 1969 | tmp = AC97_MEA_GPIO; |
1966 | if (ac97->ext_mid & AC97_MEI_LINE1) { | 1970 | if (ac97->ext_mid & AC97_MEI_LINE1) { |
1967 | snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 12000); | 1971 | snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 8000); |
1968 | tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1; | 1972 | tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1; |
1969 | } | 1973 | } |
1970 | if (ac97->ext_mid & AC97_MEI_LINE2) { | 1974 | if (ac97->ext_mid & AC97_MEI_LINE2) { |
1971 | snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 12000); | 1975 | snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 8000); |
1972 | tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2; | 1976 | tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2; |
1973 | } | 1977 | } |
1974 | if (ac97->ext_mid & AC97_MEI_HANDSET) { | 1978 | if (ac97->ext_mid & AC97_MEI_HANDSET) { |
1975 | snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 12000); | 1979 | snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 8000); |
1976 | tmp |= AC97_MEA_HADC | AC97_MEA_HDAC; | 1980 | tmp |= AC97_MEA_HADC | AC97_MEA_HDAC; |
1977 | } | 1981 | } |
1978 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8)); | 1982 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); |
1979 | udelay(100); | 1983 | udelay(100); |
1980 | /* nothing should be in powerdown mode */ | 1984 | /* nothing should be in powerdown mode */ |
1981 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8)); | 1985 | snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0); |
1982 | end_time = jiffies + (HZ / 10); | 1986 | end_time = jiffies + (HZ / 10); |
1983 | do { | 1987 | do { |
1984 | if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) | 1988 | if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp) |
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 13c34a5d8206..b81064133c61 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,8 @@ 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, |
1411 | }; | 1531 | }; |
1412 | 1532 | ||
1413 | static int patch_ad1888_specific(ac97_t *ac97) | 1533 | static int patch_ad1888_specific(ac97_t *ac97) |
@@ -1422,8 +1542,9 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = { | |||
1422 | .build_post_spdif = patch_ad198x_post_spdif, | 1542 | .build_post_spdif = patch_ad198x_post_spdif, |
1423 | .build_specific = patch_ad1888_specific, | 1543 | .build_specific = patch_ad1888_specific, |
1424 | #ifdef CONFIG_PM | 1544 | #ifdef CONFIG_PM |
1425 | .resume = ad18xx_resume | 1545 | .resume = ad18xx_resume, |
1426 | #endif | 1546 | #endif |
1547 | .update_jacks = ad1888_update_jacks, | ||
1427 | }; | 1548 | }; |
1428 | 1549 | ||
1429 | int patch_ad1888(ac97_t * ac97) | 1550 | int patch_ad1888(ac97_t * ac97) |
@@ -1459,8 +1580,9 @@ static struct snd_ac97_build_ops patch_ad1980_build_ops = { | |||
1459 | .build_post_spdif = patch_ad198x_post_spdif, | 1580 | .build_post_spdif = patch_ad198x_post_spdif, |
1460 | .build_specific = patch_ad1980_specific, | 1581 | .build_specific = patch_ad1980_specific, |
1461 | #ifdef CONFIG_PM | 1582 | #ifdef CONFIG_PM |
1462 | .resume = ad18xx_resume | 1583 | .resume = ad18xx_resume, |
1463 | #endif | 1584 | #endif |
1585 | .update_jacks = ad1888_update_jacks, | ||
1464 | }; | 1586 | }; |
1465 | 1587 | ||
1466 | int patch_ad1980(ac97_t * ac97) | 1588 | int patch_ad1980(ac97_t * ac97) |
@@ -1471,10 +1593,21 @@ int patch_ad1980(ac97_t * ac97) | |||
1471 | } | 1593 | } |
1472 | 1594 | ||
1473 | static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = { | 1595 | 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) | 1596 | AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0) |
1476 | }; | 1597 | }; |
1477 | 1598 | ||
1599 | static void ad1985_update_jacks(ac97_t *ac97) | ||
1600 | { | ||
1601 | /* shared Line-In */ | ||
1602 | snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12, | ||
1603 | is_shared_linein(ac97) ? 0 : 1 << 12); | ||
1604 | /* shared Mic */ | ||
1605 | snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11, | ||
1606 | is_shared_micin(ac97) ? 0 : 1 << 11); | ||
1607 | snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9, | ||
1608 | is_shared_micin(ac97) ? 0 : 1 << 9); | ||
1609 | } | ||
1610 | |||
1478 | static int patch_ad1985_specific(ac97_t *ac97) | 1611 | static int patch_ad1985_specific(ac97_t *ac97) |
1479 | { | 1612 | { |
1480 | int err; | 1613 | int err; |
@@ -1488,8 +1621,9 @@ static struct snd_ac97_build_ops patch_ad1985_build_ops = { | |||
1488 | .build_post_spdif = patch_ad198x_post_spdif, | 1621 | .build_post_spdif = patch_ad198x_post_spdif, |
1489 | .build_specific = patch_ad1985_specific, | 1622 | .build_specific = patch_ad1985_specific, |
1490 | #ifdef CONFIG_PM | 1623 | #ifdef CONFIG_PM |
1491 | .resume = ad18xx_resume | 1624 | .resume = ad18xx_resume, |
1492 | #endif | 1625 | #endif |
1626 | .update_jacks = ad1985_update_jacks, | ||
1493 | }; | 1627 | }; |
1494 | 1628 | ||
1495 | int patch_ad1985(ac97_t * ac97) | 1629 | int patch_ad1985(ac97_t * ac97) |
@@ -1521,31 +1655,25 @@ int patch_ad1985(ac97_t * ac97) | |||
1521 | /* | 1655 | /* |
1522 | * realtek ALC65x/850 codecs | 1656 | * realtek ALC65x/850 codecs |
1523 | */ | 1657 | */ |
1524 | static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | 1658 | static void alc650_update_jacks(ac97_t *ac97) |
1525 | { | 1659 | { |
1526 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 1660 | int shared; |
1527 | ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1; | 1661 | |
1528 | return 0; | 1662 | /* shared Line-In */ |
1529 | } | 1663 | shared = is_shared_linein(ac97); |
1530 | 1664 | snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9, | |
1531 | static int snd_ac97_alc650_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | 1665 | shared ? (1 << 9) : 0); |
1532 | { | 1666 | /* update shared Mic */ |
1533 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 1667 | shared = is_shared_micin(ac97); |
1534 | int change, val; | 1668 | /* disable/enable vref */ |
1535 | val = !!(snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10)); | 1669 | snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, |
1536 | change = (ucontrol->value.integer.value[0] != val); | 1670 | shared ? (1 << 12) : 0); |
1537 | if (change) { | 1671 | /* turn on/off center-on-mic */ |
1538 | /* disable/enable vref */ | 1672 | snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10, |
1539 | snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, | 1673 | shared ? (1 << 10) : 0); |
1540 | ucontrol->value.integer.value[0] ? (1 << 12) : 0); | 1674 | /* GPIO0 high for mic */ |
1541 | /* turn on/off center-on-mic */ | 1675 | snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100, |
1542 | snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10, | 1676 | shared ? 0 : 0x100); |
1543 | ucontrol->value.integer.value[0] ? (1 << 10) : 0); | ||
1544 | /* GPIO0 high for mic */ | ||
1545 | snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100, | ||
1546 | ucontrol->value.integer.value[0] ? 0 : 0x100); | ||
1547 | } | ||
1548 | return change; | ||
1549 | } | 1677 | } |
1550 | 1678 | ||
1551 | static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { | 1679 | static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { |
@@ -1558,8 +1686,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = { | |||
1558 | /* 6: Independent Master Volume Right */ | 1686 | /* 6: Independent Master Volume Right */ |
1559 | /* 7: Independent Master Volume Left */ | 1687 | /* 7: Independent Master Volume Left */ |
1560 | /* 8: reserved */ | 1688 | /* 8: reserved */ |
1561 | AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0), | 1689 | /* 9: Line-In/Surround share */ |
1562 | /* 10: mic, see below */ | 1690 | /* 10: Mic/CLFE share */ |
1563 | /* 11-13: in IEC958 controls */ | 1691 | /* 11-13: in IEC958 controls */ |
1564 | AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0), | 1692 | AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0), |
1565 | #if 0 /* always set in patch_alc650 */ | 1693 | #if 0 /* always set in patch_alc650 */ |
@@ -1570,14 +1698,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), | 1698 | 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), | 1699 | AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1), |
1572 | #endif | 1700 | #endif |
1573 | { | 1701 | AC97_SURROUND_JACK_MODE_CTL, |
1574 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1702 | 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 | }; | 1703 | }; |
1582 | 1704 | ||
1583 | static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = { | 1705 | static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = { |
@@ -1601,7 +1723,8 @@ static int patch_alc650_specific(ac97_t * ac97) | |||
1601 | } | 1723 | } |
1602 | 1724 | ||
1603 | static struct snd_ac97_build_ops patch_alc650_ops = { | 1725 | static struct snd_ac97_build_ops patch_alc650_ops = { |
1604 | .build_specific = patch_alc650_specific | 1726 | .build_specific = patch_alc650_specific, |
1727 | .update_jacks = alc650_update_jacks | ||
1605 | }; | 1728 | }; |
1606 | 1729 | ||
1607 | int patch_alc650(ac97_t * ac97) | 1730 | int patch_alc650(ac97_t * ac97) |
@@ -1659,37 +1782,27 @@ int patch_alc650(ac97_t * ac97) | |||
1659 | return 0; | 1782 | return 0; |
1660 | } | 1783 | } |
1661 | 1784 | ||
1662 | static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | 1785 | 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 | { | 1786 | { |
1671 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 1787 | int shared; |
1672 | 1788 | ||
1789 | /* shared Line-In */ | ||
1790 | shared = is_shared_linein(ac97); | ||
1791 | ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9, | ||
1792 | shared ? (1 << 9) : 0, 0); | ||
1793 | /* update shared mic */ | ||
1794 | shared = is_shared_micin(ac97); | ||
1673 | /* misc control; vrefout disable */ | 1795 | /* misc control; vrefout disable */ |
1674 | snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, | 1796 | snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, |
1675 | ucontrol->value.integer.value[0] ? (1 << 12) : 0); | 1797 | shared ? (1 << 12) : 0); |
1676 | return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10, | 1798 | ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10, |
1677 | ucontrol->value.integer.value[0] ? (1 << 10) : 0, | 1799 | shared ? (1 << 10) : 0, 0); |
1678 | 0); | ||
1679 | } | 1800 | } |
1680 | 1801 | ||
1681 | |||
1682 | static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = { | 1802 | static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = { |
1683 | AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), | 1803 | 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), | 1804 | AC97_SURROUND_JACK_MODE_CTL, |
1685 | { | 1805 | 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 | }; | 1806 | }; |
1694 | 1807 | ||
1695 | static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | 1808 | static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) |
@@ -1759,7 +1872,8 @@ static int patch_alc655_specific(ac97_t * ac97) | |||
1759 | } | 1872 | } |
1760 | 1873 | ||
1761 | static struct snd_ac97_build_ops patch_alc655_ops = { | 1874 | static struct snd_ac97_build_ops patch_alc655_ops = { |
1762 | .build_specific = patch_alc655_specific | 1875 | .build_specific = patch_alc655_specific, |
1876 | .update_jacks = alc655_update_jacks | ||
1763 | }; | 1877 | }; |
1764 | 1878 | ||
1765 | int patch_alc655(ac97_t * ac97) | 1879 | int patch_alc655(ac97_t * ac97) |
@@ -1798,63 +1912,33 @@ int patch_alc655(ac97_t * ac97) | |||
1798 | #define AC97_ALC850_JACK_SELECT 0x76 | 1912 | #define AC97_ALC850_JACK_SELECT 0x76 |
1799 | #define AC97_ALC850_MISC1 0x7a | 1913 | #define AC97_ALC850_MISC1 0x7a |
1800 | 1914 | ||
1801 | static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | 1915 | static void alc850_update_jacks(ac97_t *ac97) |
1802 | { | 1916 | { |
1803 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 1917 | int shared; |
1804 | ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2; | 1918 | |
1805 | return 0; | 1919 | /* shared Line-In */ |
1806 | } | 1920 | shared = is_shared_linein(ac97); |
1807 | |||
1808 | static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
1809 | { | ||
1810 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
1811 | |||
1812 | /* SURR 1kOhm (bit4), Amp (bit5) */ | 1921 | /* SURR 1kOhm (bit4), Amp (bit5) */ |
1813 | snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5), | 1922 | snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5), |
1814 | ucontrol->value.integer.value[0] ? (1<<5) : (1<<4)); | 1923 | shared ? (1<<5) : (1<<4)); |
1815 | /* LINE-IN = 0, SURROUND = 2 */ | 1924 | /* LINE-IN = 0, SURROUND = 2 */ |
1816 | return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12, | 1925 | snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12, |
1817 | ucontrol->value.integer.value[0] ? (2<<12) : (0<<12)); | 1926 | shared ? (2<<12) : (0<<12)); |
1818 | } | 1927 | /* update shared mic */ |
1819 | 1928 | 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) */ | 1929 | /* Vref disable (bit12), 1kOhm (bit13) */ |
1832 | snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13), | 1930 | snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13), |
1833 | ucontrol->value.integer.value[0] ? (1<<12) : (1<<13)); | 1931 | shared ? (1<<12) : (1<<13)); |
1834 | /* MIC-IN = 1, CENTER-LFE = 2 */ | 1932 | /* MIC-IN = 1, CENTER-LFE = 2 */ |
1835 | return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, | 1933 | snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, |
1836 | ucontrol->value.integer.value[0] ? (2<<4) : (1<<4)); | 1934 | shared ? (2<<4) : (1<<4)); |
1837 | } | 1935 | } |
1838 | 1936 | ||
1839 | static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = { | 1937 | static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = { |
1840 | AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), | 1938 | AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), |
1841 | { | 1939 | AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1), |
1842 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1940 | AC97_SURROUND_JACK_MODE_CTL, |
1843 | .name = "Line-In As Surround", | 1941 | 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 | }; | 1942 | }; |
1859 | 1943 | ||
1860 | static int patch_alc850_specific(ac97_t *ac97) | 1944 | static int patch_alc850_specific(ac97_t *ac97) |
@@ -1871,7 +1955,8 @@ static int patch_alc850_specific(ac97_t *ac97) | |||
1871 | } | 1955 | } |
1872 | 1956 | ||
1873 | static struct snd_ac97_build_ops patch_alc850_ops = { | 1957 | static struct snd_ac97_build_ops patch_alc850_ops = { |
1874 | .build_specific = patch_alc850_specific | 1958 | .build_specific = patch_alc850_specific, |
1959 | .update_jacks = alc850_update_jacks | ||
1875 | }; | 1960 | }; |
1876 | 1961 | ||
1877 | int patch_alc850(ac97_t *ac97) | 1962 | int patch_alc850(ac97_t *ac97) |
@@ -1911,9 +1996,17 @@ int patch_alc850(ac97_t *ac97) | |||
1911 | /* | 1996 | /* |
1912 | * C-Media CM97xx codecs | 1997 | * C-Media CM97xx codecs |
1913 | */ | 1998 | */ |
1999 | static void cm9738_update_jacks(ac97_t *ac97) | ||
2000 | { | ||
2001 | /* shared Line-In */ | ||
2002 | snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10, | ||
2003 | is_shared_linein(ac97) ? (1 << 10) : 0); | ||
2004 | } | ||
2005 | |||
1914 | static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = { | 2006 | 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), | 2007 | AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0), |
2008 | AC97_SURROUND_JACK_MODE_CTL, | ||
2009 | AC97_CHANNEL_MODE_4CH_CTL, | ||
1917 | }; | 2010 | }; |
1918 | 2011 | ||
1919 | static int patch_cm9738_specific(ac97_t * ac97) | 2012 | static int patch_cm9738_specific(ac97_t * ac97) |
@@ -1922,7 +2015,8 @@ static int patch_cm9738_specific(ac97_t * ac97) | |||
1922 | } | 2015 | } |
1923 | 2016 | ||
1924 | static struct snd_ac97_build_ops patch_cm9738_ops = { | 2017 | static struct snd_ac97_build_ops patch_cm9738_ops = { |
1925 | .build_specific = patch_cm9738_specific | 2018 | .build_specific = patch_cm9738_specific, |
2019 | .update_jacks = cm9738_update_jacks | ||
1926 | }; | 2020 | }; |
1927 | 2021 | ||
1928 | int patch_cm9738(ac97_t * ac97) | 2022 | int patch_cm9738(ac97_t * ac97) |
@@ -1986,34 +2080,19 @@ static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = { | |||
1986 | /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */ | 2080 | /* BIT 8: SPD32 - 32bit SPDIF - not supported yet */ |
1987 | }; | 2081 | }; |
1988 | 2082 | ||
1989 | static int snd_ac97_cm9739_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 2083 | static void cm9739_update_jacks(ac97_t *ac97) |
1990 | { | 2084 | { |
1991 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 2085 | /* shared Line-In */ |
1992 | if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000) | 2086 | snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10, |
1993 | ucontrol->value.integer.value[0] = 1; | 2087 | is_shared_linein(ac97) ? (1 << 10) : 0); |
1994 | else | 2088 | /* shared Mic */ |
1995 | ucontrol->value.integer.value[0] = 0; | 2089 | snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000, |
1996 | return 0; | 2090 | is_shared_micin(ac97) ? 0x1000 : 0x2000); |
1997 | } | ||
1998 | |||
1999 | static int snd_ac97_cm9739_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
2000 | { | ||
2001 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
2002 | return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000, | ||
2003 | ucontrol->value.integer.value[0] ? | ||
2004 | 0x1000 : 0x2000); | ||
2005 | } | 2091 | } |
2006 | 2092 | ||
2007 | static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = { | 2093 | static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = { |
2008 | AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0), | 2094 | AC97_SURROUND_JACK_MODE_CTL, |
2009 | { | 2095 | 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 | }; | 2096 | }; |
2018 | 2097 | ||
2019 | static int patch_cm9739_specific(ac97_t * ac97) | 2098 | static int patch_cm9739_specific(ac97_t * ac97) |
@@ -2028,7 +2107,8 @@ static int patch_cm9739_post_spdif(ac97_t * ac97) | |||
2028 | 2107 | ||
2029 | static struct snd_ac97_build_ops patch_cm9739_ops = { | 2108 | static struct snd_ac97_build_ops patch_cm9739_ops = { |
2030 | .build_specific = patch_cm9739_specific, | 2109 | .build_specific = patch_cm9739_specific, |
2031 | .build_post_spdif = patch_cm9739_post_spdif | 2110 | .build_post_spdif = patch_cm9739_post_spdif, |
2111 | .update_jacks = cm9739_update_jacks | ||
2032 | }; | 2112 | }; |
2033 | 2113 | ||
2034 | int patch_cm9739(ac97_t * ac97) | 2114 | int patch_cm9739(ac97_t * ac97) |
@@ -2087,71 +2167,97 @@ int patch_cm9739(ac97_t * ac97) | |||
2087 | } | 2167 | } |
2088 | 2168 | ||
2089 | #define AC97_CM9761_MULTI_CHAN 0x64 | 2169 | #define AC97_CM9761_MULTI_CHAN 0x64 |
2170 | #define AC97_CM9761_FUNC 0x66 | ||
2090 | #define AC97_CM9761_SPDIF_CTRL 0x6c | 2171 | #define AC97_CM9761_SPDIF_CTRL 0x6c |
2091 | 2172 | ||
2092 | static int snd_ac97_cm9761_linein_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 2173 | static void cm9761_update_jacks(ac97_t *ac97) |
2093 | { | 2174 | { |
2094 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 2175 | unsigned short surr_vals[2][2] = { |
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 | { | ||
2104 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | ||
2105 | unsigned short vals[2][2] = { | ||
2106 | { 0x0008, 0x0400 }, /* off, on */ | 2176 | { 0x0008, 0x0400 }, /* off, on */ |
2107 | { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */ | 2177 | { 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */ |
2108 | }; | 2178 | }; |
2109 | return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x0408, | 2179 | unsigned short clfe_vals[2][2] = { |
2110 | vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]); | 2180 | { 0x2000, 0x1880 }, /* off, on */ |
2181 | { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */ | ||
2182 | }; | ||
2183 | |||
2184 | /* shared Line-In */ | ||
2185 | snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x0408, | ||
2186 | surr_vals[ac97->spec.dev_flags][is_shared_linein(ac97)]); | ||
2187 | /* shared Mic */ | ||
2188 | snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3880, | ||
2189 | clfe_vals[ac97->spec.dev_flags][is_shared_micin(ac97)]); | ||
2190 | } | ||
2191 | |||
2192 | static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = { | ||
2193 | AC97_SURROUND_JACK_MODE_CTL, | ||
2194 | AC97_CHANNEL_MODE_CTL, | ||
2195 | }; | ||
2196 | |||
2197 | static int cm9761_spdif_out_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
2198 | { | ||
2199 | static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" }; | ||
2200 | |||
2201 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2202 | uinfo->count = 1; | ||
2203 | uinfo->value.enumerated.items = 3; | ||
2204 | if (uinfo->value.enumerated.item > 2) | ||
2205 | uinfo->value.enumerated.item = 2; | ||
2206 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
2207 | return 0; | ||
2111 | } | 2208 | } |
2112 | 2209 | ||
2113 | static int snd_ac97_cm9761_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 2210 | static int cm9761_spdif_out_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
2114 | { | 2211 | { |
2115 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 2212 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); |
2116 | if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000) | 2213 | |
2117 | ucontrol->value.integer.value[0] = 1; | 2214 | if (ac97->regs[AC97_CM9761_FUNC] & 0x1) |
2215 | ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */ | ||
2216 | else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2) | ||
2217 | ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */ | ||
2118 | else | 2218 | else |
2119 | ucontrol->value.integer.value[0] = 0; | 2219 | 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; | 2220 | return 0; |
2123 | } | 2221 | } |
2124 | 2222 | ||
2125 | static int snd_ac97_cm9761_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | 2223 | static int cm9761_spdif_out_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
2126 | { | 2224 | { |
2127 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); | 2225 | ac97_t *ac97 = snd_kcontrol_chip(kcontrol); |
2128 | unsigned short vals[2][2] = { | 2226 | |
2129 | { 0x2000, 0x1880 }, /* off, on */ | 2227 | if (ucontrol->value.enumerated.item[0] == 2) |
2130 | { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */ | 2228 | return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1); |
2131 | }; | 2229 | snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0); |
2132 | return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3880, | 2230 | return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2, |
2133 | vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]); | 2231 | ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0); |
2134 | } | 2232 | } |
2135 | 2233 | ||
2136 | static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = { | 2234 | static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" }; |
2137 | { | 2235 | static const struct ac97_enum cm9761_dac_clock_enum = |
2138 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2236 | AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock); |
2139 | .name = "Line-In As Surround", | 2237 | |
2140 | .info = snd_ac97_info_volsw, | 2238 | static const snd_kcontrol_new_t snd_ac97_cm9761_controls_spdif[] = { |
2141 | .get = snd_ac97_cm9761_linein_rear_get, | 2239 | { /* BIT 1: SPDIFS */ |
2142 | .put = snd_ac97_cm9761_linein_rear_put, | 2240 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
2143 | .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */ | 2241 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", |
2144 | }, | 2242 | .info = cm9761_spdif_out_source_info, |
2145 | { | 2243 | .get = cm9761_spdif_out_source_get, |
2146 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 2244 | .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 | }, | 2245 | }, |
2246 | /* BIT 2: IG_SPIV */ | ||
2247 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0), | ||
2248 | /* BIT 3: SPI2F */ | ||
2249 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0), | ||
2250 | /* BIT 4: SPI2SDI */ | ||
2251 | AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0), | ||
2252 | /* BIT 9-10: DAC_CTL */ | ||
2253 | AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum), | ||
2153 | }; | 2254 | }; |
2154 | 2255 | ||
2256 | static int patch_cm9761_post_spdif(ac97_t * ac97) | ||
2257 | { | ||
2258 | return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif)); | ||
2259 | } | ||
2260 | |||
2155 | static int patch_cm9761_specific(ac97_t * ac97) | 2261 | static int patch_cm9761_specific(ac97_t * ac97) |
2156 | { | 2262 | { |
2157 | return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls)); | 2263 | return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls)); |
@@ -2159,7 +2265,8 @@ static int patch_cm9761_specific(ac97_t * ac97) | |||
2159 | 2265 | ||
2160 | static struct snd_ac97_build_ops patch_cm9761_ops = { | 2266 | static struct snd_ac97_build_ops patch_cm9761_ops = { |
2161 | .build_specific = patch_cm9761_specific, | 2267 | .build_specific = patch_cm9761_specific, |
2162 | .build_post_spdif = patch_cm9739_post_spdif /* hope it's identical... */ | 2268 | .build_post_spdif = patch_cm9761_post_spdif, |
2269 | .update_jacks = cm9761_update_jacks | ||
2163 | }; | 2270 | }; |
2164 | 2271 | ||
2165 | int patch_cm9761(ac97_t *ac97) | 2272 | int patch_cm9761(ac97_t *ac97) |
@@ -2193,24 +2300,25 @@ int patch_cm9761(ac97_t *ac97) | |||
2193 | /* to be sure: we overwrite the ext status bits */ | 2300 | /* to be sure: we overwrite the ext status bits */ |
2194 | snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0); | 2301 | snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0); |
2195 | /* Don't set 0x0200 here. This results in the silent analog output */ | 2302 | /* Don't set 0x0200 here. This results in the silent analog output */ |
2196 | snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009); | 2303 | 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 */ | 2304 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ |
2198 | 2305 | ||
2199 | /* set-up multi channel */ | 2306 | /* set-up multi channel */ |
2200 | /* bit 15: pc master beep off | 2307 | /* bit 15: pc master beep off |
2201 | * bit 14: ?? | 2308 | * bit 14: pin47 = EAPD/SPDIF |
2202 | * bit 13: vref ctl [= cm9739] | 2309 | * bit 13: vref ctl [= cm9739] |
2203 | * bit 12: center/mic [= cm9739] (reverted on rev B) | 2310 | * bit 12: CLFE control (reverted on rev B) |
2204 | * bit 11: ?? (mic/center/lfe) (reverted on rev B) | 2311 | * bit 11: Mic/center share (reverted on rev B) |
2205 | * bit 10: suddound/line [= cm9739] | 2312 | * bit 10: suddound/line share |
2206 | * bit 9: mix 2 surround | 2313 | * bit 9: Analog-in mix -> surround |
2207 | * bit 8: ? | 2314 | * bit 8: Analog-in mix -> CLFE |
2208 | * bit 7: ?? (mic/center/lfe) | 2315 | * bit 7: Mic/LFE share (mic/center/lfe) |
2209 | * bit 4: ?? (front) | 2316 | * bit 5: vref select (9761A) |
2210 | * bit 3: ?? (line-in/rear share) (revereted with rev B) | 2317 | * bit 4: front control |
2211 | * bit 2: ?? (surround) | 2318 | * bit 3: surround control (revereted with rev B) |
2212 | * bit 1: front mic | 2319 | * bit 2: front mic |
2213 | * bit 0: mic boost | 2320 | * bit 1: stereo mic |
2321 | * bit 0: mic boost level (0=20dB, 1=30dB) | ||
2214 | */ | 2322 | */ |
2215 | 2323 | ||
2216 | #if 0 | 2324 | #if 0 |
@@ -2230,6 +2338,47 @@ int patch_cm9761(ac97_t *ac97) | |||
2230 | return 0; | 2338 | return 0; |
2231 | } | 2339 | } |
2232 | 2340 | ||
2341 | #define AC97_CM9780_SIDE 0x60 | ||
2342 | #define AC97_CM9780_JACK 0x62 | ||
2343 | #define AC97_CM9780_MIXER 0x64 | ||
2344 | #define AC97_CM9780_MULTI_CHAN 0x66 | ||
2345 | #define AC97_CM9780_SPDIF 0x6c | ||
2346 | |||
2347 | static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" }; | ||
2348 | static const struct ac97_enum cm9780_ch_select_enum = | ||
2349 | AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select); | ||
2350 | static const snd_kcontrol_new_t cm9780_controls[] = { | ||
2351 | AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1), | ||
2352 | AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0), | ||
2353 | AC97_ENUM("Side Playback Route", cm9780_ch_select_enum), | ||
2354 | }; | ||
2355 | |||
2356 | static int patch_cm9780_specific(ac97_t *ac97) | ||
2357 | { | ||
2358 | return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls)); | ||
2359 | } | ||
2360 | |||
2361 | static struct snd_ac97_build_ops patch_cm9780_ops = { | ||
2362 | .build_specific = patch_cm9780_specific, | ||
2363 | .build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */ | ||
2364 | }; | ||
2365 | |||
2366 | int patch_cm9780(ac97_t *ac97) | ||
2367 | { | ||
2368 | unsigned short val; | ||
2369 | |||
2370 | ac97->build_ops = &patch_cm9780_ops; | ||
2371 | |||
2372 | /* enable spdif */ | ||
2373 | if (ac97->ext_id & AC97_EI_SPDIF) { | ||
2374 | ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */ | ||
2375 | val = snd_ac97_read(ac97, AC97_CM9780_SPDIF); | ||
2376 | val |= 0x1; /* SPDI_EN */ | ||
2377 | snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val); | ||
2378 | } | ||
2379 | |||
2380 | return 0; | ||
2381 | } | ||
2233 | 2382 | ||
2234 | /* | 2383 | /* |
2235 | * VIA VT1616 codec | 2384 | * VIA VT1616 codec |
@@ -2263,9 +2412,21 @@ int patch_vt1616(ac97_t * ac97) | |||
2263 | return 0; | 2412 | return 0; |
2264 | } | 2413 | } |
2265 | 2414 | ||
2415 | /* | ||
2416 | */ | ||
2417 | static void it2646_update_jacks(ac97_t *ac97) | ||
2418 | { | ||
2419 | /* shared Line-In */ | ||
2420 | snd_ac97_update_bits(ac97, 0x76, 1 << 9, | ||
2421 | is_shared_linein(ac97) ? (1<<9) : 0); | ||
2422 | /* shared Mic */ | ||
2423 | snd_ac97_update_bits(ac97, 0x76, 1 << 10, | ||
2424 | is_shared_micin(ac97) ? (1<<10) : 0); | ||
2425 | } | ||
2426 | |||
2266 | static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = { | 2427 | static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = { |
2267 | AC97_SINGLE("Line-In As Surround", 0x76, 9, 1, 0), | 2428 | AC97_SURROUND_JACK_MODE_CTL, |
2268 | AC97_SINGLE("Mic As Center/LFE", 0x76, 10, 1, 0), | 2429 | AC97_CHANNEL_MODE_CTL, |
2269 | }; | 2430 | }; |
2270 | 2431 | ||
2271 | static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = { | 2432 | static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = { |
@@ -2285,7 +2446,8 @@ static int patch_it2646_specific(ac97_t * ac97) | |||
2285 | } | 2446 | } |
2286 | 2447 | ||
2287 | static struct snd_ac97_build_ops patch_it2646_ops = { | 2448 | static struct snd_ac97_build_ops patch_it2646_ops = { |
2288 | .build_specific = patch_it2646_specific | 2449 | .build_specific = patch_it2646_specific, |
2450 | .update_jacks = it2646_update_jacks | ||
2289 | }; | 2451 | }; |
2290 | 2452 | ||
2291 | int patch_it2646(ac97_t * ac97) | 2453 | int patch_it2646(ac97_t * ac97) |
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..038f56ad42f1 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -2270,7 +2270,7 @@ static struct pci_driver driver = { | |||
2270 | 2270 | ||
2271 | static int __init alsa_card_ali_init(void) | 2271 | static int __init alsa_card_ali_init(void) |
2272 | { | 2272 | { |
2273 | return pci_module_init(&driver); | 2273 | return pci_register_driver(&driver); |
2274 | } | 2274 | } |
2275 | 2275 | ||
2276 | static void __exit alsa_card_ali_exit(void) | 2276 | 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..06551a69fb40 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -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..9220aae632b0 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -1332,7 +1332,7 @@ static struct pci_driver driver = { | |||
1332 | 1332 | ||
1333 | static int __init alsa_card_atiixp_init(void) | 1333 | static int __init alsa_card_atiixp_init(void) |
1334 | { | 1334 | { |
1335 | return pci_module_init(&driver); | 1335 | return pci_register_driver(&driver); |
1336 | } | 1336 | } |
1337 | 1337 | ||
1338 | static void __exit alsa_card_atiixp_exit(void) | 1338 | 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..defdc5a459f0 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -918,7 +918,7 @@ static int __init alsa_card_bt87x_init(void) | |||
918 | { | 918 | { |
919 | if (load_all) | 919 | if (load_all) |
920 | driver.id_table = snd_bt87x_default_ids; | 920 | driver.id_table = snd_bt87x_default_ids; |
921 | return pci_module_init(&driver); | 921 | return pci_register_driver(&driver); |
922 | } | 922 | } |
923 | 923 | ||
924 | static void __exit alsa_card_bt87x_exit(void) | 924 | static void __exit alsa_card_bt87x_exit(void) |
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index deb028851056..c623858428cd 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h | |||
@@ -508,9 +508,17 @@ struct snd_ca0106_pcm { | |||
508 | unsigned short running; | 508 | unsigned short running; |
509 | }; | 509 | }; |
510 | 510 | ||
511 | typedef struct { | ||
512 | u32 serial; | ||
513 | char * name; | ||
514 | int ac97; | ||
515 | int gpio_type; | ||
516 | } ca0106_details_t; | ||
517 | |||
511 | // definition of the chip-specific record | 518 | // definition of the chip-specific record |
512 | struct snd_ca0106 { | 519 | struct snd_ca0106 { |
513 | snd_card_t *card; | 520 | snd_card_t *card; |
521 | ca0106_details_t *details; | ||
514 | struct pci_dev *pci; | 522 | struct pci_dev *pci; |
515 | 523 | ||
516 | unsigned long port; | 524 | unsigned long port; |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 82533b45bc8c..a56e68ea87bc 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -161,18 +161,29 @@ MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard."); | |||
161 | 161 | ||
162 | #include "ca0106.h" | 162 | #include "ca0106.h" |
163 | 163 | ||
164 | typedef struct { | 164 | static ca0106_details_t ca0106_chip_details[] = { |
165 | u32 serial; | 165 | /* AudigyLS[SB0310] */ |
166 | char * name; | 166 | { .serial = 0x10021102, |
167 | } ca0106_names_t; | 167 | .name = "AudigyLS [SB0310]", |
168 | 168 | .ac97 = 1 } , | |
169 | static ca0106_names_t ca0106_chip_names[] = { | 169 | /* Unknown AudigyLS that also says SB0310 on it */ |
170 | { 0x10021102, "AudigyLS [SB0310]"} , | 170 | { .serial = 0x10051102, |
171 | { 0x10051102, "AudigyLS [SB0310b]"} , /* Unknown AudigyLS that also says SB0310 on it */ | 171 | .name = "AudigyLS [SB0310b]", |
172 | { 0x10061102, "Live! 7.1 24bit [SB0410]"} , /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */ | 172 | .ac97 = 1 } , |
173 | { 0x10071102, "Live! 7.1 24bit [SB0413]"} , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ | 173 | /* 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 */ | 174 | { .serial = 0x10061102, |
175 | { 0, "AudigyLS [Unknown]" } | 175 | .name = "Live! 7.1 24bit [SB0410]", |
176 | .gpio_type = 1 } , | ||
177 | /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ | ||
178 | { .serial = 0x10071102, | ||
179 | .name = "Live! 7.1 24bit [SB0413]", | ||
180 | .gpio_type = 1 } , | ||
181 | /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ | ||
182 | { .serial = 0x10091462, | ||
183 | .name = "MSI K8N Diamond MB [SB0438]", | ||
184 | .gpio_type = 1 } , | ||
185 | { .serial = 0, | ||
186 | .name = "AudigyLS [Unknown]" } | ||
176 | }; | 187 | }; |
177 | 188 | ||
178 | /* hardware definition */ | 189 | /* hardware definition */ |
@@ -810,6 +821,7 @@ static int snd_ca0106_ac97(ca0106_t *chip) | |||
810 | 821 | ||
811 | memset(&ac97, 0, sizeof(ac97)); | 822 | memset(&ac97, 0, sizeof(ac97)); |
812 | ac97.private_data = chip; | 823 | ac97.private_data = chip; |
824 | ac97.scaps = AC97_SCAP_NO_SPDIF; | ||
813 | return snd_ac97_mixer(pbus, &ac97, &chip->ac97); | 825 | return snd_ac97_mixer(pbus, &ac97, &chip->ac97); |
814 | } | 826 | } |
815 | 827 | ||
@@ -993,6 +1005,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card, | |||
993 | ca0106_t **rchip) | 1005 | ca0106_t **rchip) |
994 | { | 1006 | { |
995 | ca0106_t *chip; | 1007 | ca0106_t *chip; |
1008 | ca0106_details_t *c; | ||
996 | int err; | 1009 | int err; |
997 | int ch; | 1010 | int ch; |
998 | static snd_device_ops_t ops = { | 1011 | static snd_device_ops_t ops = { |
@@ -1054,6 +1067,15 @@ static int __devinit snd_ca0106_create(snd_card_t *card, | |||
1054 | printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model, | 1067 | printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model, |
1055 | chip->revision, chip->serial); | 1068 | chip->revision, chip->serial); |
1056 | #endif | 1069 | #endif |
1070 | strcpy(card->driver, "CA0106"); | ||
1071 | strcpy(card->shortname, "CA0106"); | ||
1072 | |||
1073 | for (c=ca0106_chip_details; c->serial; c++) { | ||
1074 | if (c->serial == chip->serial) break; | ||
1075 | } | ||
1076 | chip->details = c; | ||
1077 | sprintf(card->longname, "%s at 0x%lx irq %i", | ||
1078 | c->name, chip->port, chip->irq); | ||
1057 | 1079 | ||
1058 | outl(0, chip->port + INTE); | 1080 | outl(0, chip->port + INTE); |
1059 | 1081 | ||
@@ -1113,7 +1135,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. */ | 1135 | //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */ |
1114 | /* Analog or Digital output */ | 1136 | /* Analog or Digital output */ |
1115 | snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf); | 1137 | 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 */ | 1138 | 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 */ | 1139 | chip->spdif_enable = 0; /* Set digital SPDIF output off */ |
1118 | chip->capture_source = 3; /* Set CAPTURE_SOURCE */ | 1140 | chip->capture_source = 3; /* Set CAPTURE_SOURCE */ |
1119 | //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */ | 1141 | //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */ |
@@ -1138,13 +1160,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 */ | 1160 | 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 */ | 1161 | chip->capture_source = 3; /* Set CAPTURE_SOURCE */ |
1140 | 1162 | ||
1141 | if ((chip->serial == 0x10061102) || | 1163 | 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. */ | 1164 | /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ |
1145 | outl(0x0, chip->port+GPIO); | 1165 | outl(0x0, chip->port+GPIO); |
1146 | //outl(0x00f0e000, chip->port+GPIO); /* Analog */ | 1166 | //outl(0x00f0e000, chip->port+GPIO); /* Analog */ |
1147 | outl(0x005f4300, chip->port+GPIO); /* Analog */ | 1167 | outl(0x005f4301, chip->port+GPIO); /* Analog */ |
1148 | } else { | 1168 | } else { |
1149 | outl(0x0, chip->port+GPIO); | 1169 | outl(0x0, chip->port+GPIO); |
1150 | outl(0x005f03a3, chip->port+GPIO); /* Analog */ | 1170 | outl(0x005f03a3, chip->port+GPIO); /* Analog */ |
@@ -1172,7 +1192,6 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1172 | static int dev; | 1192 | static int dev; |
1173 | snd_card_t *card; | 1193 | snd_card_t *card; |
1174 | ca0106_t *chip; | 1194 | ca0106_t *chip; |
1175 | ca0106_names_t *c; | ||
1176 | int err; | 1195 | int err; |
1177 | 1196 | ||
1178 | if (dev >= SNDRV_CARDS) | 1197 | if (dev >= SNDRV_CARDS) |
@@ -1207,9 +1226,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1207 | snd_card_free(card); | 1226 | snd_card_free(card); |
1208 | return err; | 1227 | return err; |
1209 | } | 1228 | } |
1210 | if ((chip->serial != 0x10061102) && | 1229 | 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) { | 1230 | if ((err = snd_ca0106_ac97(chip)) < 0) { |
1214 | snd_card_free(card); | 1231 | snd_card_free(card); |
1215 | return err; | 1232 | return err; |
@@ -1222,15 +1239,6 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1222 | 1239 | ||
1223 | snd_ca0106_proc_init(chip); | 1240 | snd_ca0106_proc_init(chip); |
1224 | 1241 | ||
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) { | 1242 | if ((err = snd_card_register(card)) < 0) { |
1235 | snd_card_free(card); | 1243 | snd_card_free(card); |
1236 | return err; | 1244 | return err; |
@@ -1267,7 +1275,7 @@ static int __init alsa_card_ca0106_init(void) | |||
1267 | { | 1275 | { |
1268 | int err; | 1276 | int err; |
1269 | 1277 | ||
1270 | if ((err = pci_module_init(&driver)) > 0) | 1278 | if ((err = pci_register_driver(&driver)) > 0) |
1271 | return err; | 1279 | return err; |
1272 | 1280 | ||
1273 | return 0; | 1281 | return 0; |
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 97bed1b0899d..48e248608244 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -113,7 +113,7 @@ static int snd_ca0106_shared_spdif_put(snd_kcontrol_t * kcontrol, | |||
113 | } else { | 113 | } else { |
114 | /* Analog */ | 114 | /* Analog */ |
115 | snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); | 115 | snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); |
116 | snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000b0000); | 116 | snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000); |
117 | snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, | 117 | snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, |
118 | snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000); | 118 | snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000); |
119 | mask = inl(emu->port + GPIO) | 0x101; | 119 | mask = inl(emu->port + GPIO) | 0x101; |
@@ -437,7 +437,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 = | 437 | static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown = |
438 | { | 438 | { |
439 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 439 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
440 | .name = "Analog Unknown Volume", | 440 | .name = "Analog Side Volume", |
441 | .info = snd_ca0106_volume_info, | 441 | .info = snd_ca0106_volume_info, |
442 | .get = snd_ca0106_volume_get_analog_unknown, | 442 | .get = snd_ca0106_volume_get_analog_unknown, |
443 | .put = snd_ca0106_volume_put_analog_unknown | 443 | .put = snd_ca0106_volume_put_analog_unknown |
@@ -620,11 +620,6 @@ int __devinit snd_ca0106_mixer(ca0106_t *emu) | |||
620 | return -ENOMEM; | 620 | return -ENOMEM; |
621 | if ((err = snd_ctl_add(card, kctl))) | 621 | if ((err = snd_ctl_add(card, kctl))) |
622 | return err; | 622 | return err; |
623 | if ((kctl = ctl_find(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT))) != NULL) { | ||
624 | /* already defined by ac97, remove it */ | ||
625 | /* FIXME: or do we need both controls? */ | ||
626 | remove_ctl(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT)); | ||
627 | } | ||
628 | if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL) | 623 | if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL) |
629 | return -ENOMEM; | 624 | return -ENOMEM; |
630 | if ((err = snd_ctl_add(card, kctl))) | 625 | if ((err = snd_ctl_add(card, kctl))) |
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index afb711421e47..3e5161a32363 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c | |||
@@ -95,7 +95,7 @@ static struct snd_ca0106_category_str snd_ca0106_con_category[] = { | |||
95 | }; | 95 | }; |
96 | 96 | ||
97 | 97 | ||
98 | void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value) | 98 | static void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value) |
99 | { | 99 | { |
100 | int i; | 100 | int i; |
101 | u32 status[4]; | 101 | u32 status[4]; |
@@ -418,6 +418,7 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu) | |||
418 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32); | 418 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32); |
419 | entry->c.text.write_size = 64; | 419 | entry->c.text.write_size = 64; |
420 | entry->c.text.write = snd_ca0106_proc_reg_write32; | 420 | entry->c.text.write = snd_ca0106_proc_reg_write32; |
421 | entry->mode |= S_IWUSR; | ||
421 | } | 422 | } |
422 | if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) | 423 | if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) |
423 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16); | 424 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16); |
@@ -427,6 +428,7 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu) | |||
427 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1); | 428 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1); |
428 | entry->c.text.write_size = 64; | 429 | entry->c.text.write_size = 64; |
429 | entry->c.text.write = snd_ca0106_proc_reg_write; | 430 | entry->c.text.write = snd_ca0106_proc_reg_write; |
431 | entry->mode |= S_IWUSR; | ||
430 | // entry->private_data = emu; | 432 | // entry->private_data = emu; |
431 | } | 433 | } |
432 | if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) | 434 | if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 113208fbde1b..b4503385ea69 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -519,40 +519,50 @@ inline static unsigned char snd_cmipci_read_b(cmipci_t *cm, unsigned int cmd) | |||
519 | } | 519 | } |
520 | 520 | ||
521 | /* bit operations for dword register */ | 521 | /* bit operations for dword register */ |
522 | static void snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) | 522 | static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) |
523 | { | 523 | { |
524 | unsigned int val; | 524 | unsigned int val, oval; |
525 | val = inl(cm->iobase + cmd); | 525 | val = oval = inl(cm->iobase + cmd); |
526 | val |= flag; | 526 | val |= flag; |
527 | if (val == oval) | ||
528 | return 0; | ||
527 | outl(val, cm->iobase + cmd); | 529 | outl(val, cm->iobase + cmd); |
530 | return 1; | ||
528 | } | 531 | } |
529 | 532 | ||
530 | static void snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) | 533 | static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) |
531 | { | 534 | { |
532 | unsigned int val; | 535 | unsigned int val, oval; |
533 | val = inl(cm->iobase + cmd); | 536 | val = oval = inl(cm->iobase + cmd); |
534 | val &= ~flag; | 537 | val &= ~flag; |
538 | if (val == oval) | ||
539 | return 0; | ||
535 | outl(val, cm->iobase + cmd); | 540 | outl(val, cm->iobase + cmd); |
541 | return 1; | ||
536 | } | 542 | } |
537 | 543 | ||
538 | #if 0 // not used | ||
539 | /* bit operations for byte register */ | 544 | /* bit operations for byte register */ |
540 | static void snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) | 545 | static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) |
541 | { | 546 | { |
542 | unsigned char val; | 547 | unsigned char val, oval; |
543 | val = inb(cm->iobase + cmd); | 548 | val = oval = inb(cm->iobase + cmd); |
544 | val |= flag; | 549 | val |= flag; |
550 | if (val == oval) | ||
551 | return 0; | ||
545 | outb(val, cm->iobase + cmd); | 552 | outb(val, cm->iobase + cmd); |
553 | return 1; | ||
546 | } | 554 | } |
547 | 555 | ||
548 | static void snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) | 556 | static int snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) |
549 | { | 557 | { |
550 | unsigned char val; | 558 | unsigned char val, oval; |
551 | val = inb(cm->iobase + cmd); | 559 | val = oval = inb(cm->iobase + cmd); |
552 | val &= ~flag; | 560 | val &= ~flag; |
561 | if (val == oval) | ||
562 | return 0; | ||
553 | outb(val, cm->iobase + cmd); | 563 | outb(val, cm->iobase + cmd); |
564 | return 1; | ||
554 | } | 565 | } |
555 | #endif | ||
556 | 566 | ||
557 | 567 | ||
558 | /* | 568 | /* |
@@ -2250,8 +2260,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); | 2260 | DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); |
2251 | #endif | 2261 | #endif |
2252 | DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); | 2262 | 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); | 2263 | // 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); | 2264 | // 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 */ | 2265 | // 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); | 2266 | DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); |
2257 | 2267 | ||
@@ -2300,10 +2310,114 @@ static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v | |||
2300 | } | 2310 | } |
2301 | 2311 | ||
2302 | 2312 | ||
2313 | static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol, | ||
2314 | snd_ctl_elem_info_t *uinfo) | ||
2315 | { | ||
2316 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2317 | static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" }; | ||
2318 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2319 | uinfo->count = 1; | ||
2320 | uinfo->value.enumerated.items = cm->chip_version >= 39 ? 3 : 2; | ||
2321 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2322 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
2323 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
2324 | return 0; | ||
2325 | } | ||
2326 | |||
2327 | static inline unsigned int get_line_in_mode(cmipci_t *cm) | ||
2328 | { | ||
2329 | unsigned int val; | ||
2330 | if (cm->chip_version >= 39) { | ||
2331 | val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL); | ||
2332 | if (val & CM_LINE_AS_BASS) | ||
2333 | return 2; | ||
2334 | } | ||
2335 | val = snd_cmipci_read_b(cm, CM_REG_MIXER1); | ||
2336 | if (val & CM_SPK4) | ||
2337 | return 1; | ||
2338 | return 0; | ||
2339 | } | ||
2340 | |||
2341 | static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol, | ||
2342 | snd_ctl_elem_value_t *ucontrol) | ||
2343 | { | ||
2344 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2345 | |||
2346 | spin_lock_irq(&cm->reg_lock); | ||
2347 | ucontrol->value.enumerated.item[0] = get_line_in_mode(cm); | ||
2348 | spin_unlock_irq(&cm->reg_lock); | ||
2349 | return 0; | ||
2350 | } | ||
2351 | |||
2352 | static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol, | ||
2353 | snd_ctl_elem_value_t *ucontrol) | ||
2354 | { | ||
2355 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2356 | int change; | ||
2357 | |||
2358 | spin_lock_irq(&cm->reg_lock); | ||
2359 | if (ucontrol->value.enumerated.item[0] == 2) | ||
2360 | change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); | ||
2361 | else | ||
2362 | change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); | ||
2363 | if (ucontrol->value.enumerated.item[0] == 1) | ||
2364 | change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4); | ||
2365 | else | ||
2366 | change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4); | ||
2367 | spin_unlock_irq(&cm->reg_lock); | ||
2368 | return change; | ||
2369 | } | ||
2370 | |||
2371 | static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol, | ||
2372 | snd_ctl_elem_info_t *uinfo) | ||
2373 | { | ||
2374 | static char *texts[2] = { "Mic-In", "Center/LFE Output" }; | ||
2375 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
2376 | uinfo->count = 1; | ||
2377 | uinfo->value.enumerated.items = 2; | ||
2378 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
2379 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
2380 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
2381 | return 0; | ||
2382 | } | ||
2383 | |||
2384 | static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol, | ||
2385 | snd_ctl_elem_value_t *ucontrol) | ||
2386 | { | ||
2387 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2388 | /* same bit as spdi_phase */ | ||
2389 | spin_lock_irq(&cm->reg_lock); | ||
2390 | ucontrol->value.enumerated.item[0] = | ||
2391 | (snd_cmipci_read_b(cm, CM_REG_MISC) & CM_SPDIF_INVERSE) ? 1 : 0; | ||
2392 | spin_unlock_irq(&cm->reg_lock); | ||
2393 | return 0; | ||
2394 | } | ||
2395 | |||
2396 | static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol, | ||
2397 | snd_ctl_elem_value_t *ucontrol) | ||
2398 | { | ||
2399 | cmipci_t *cm = snd_kcontrol_chip(kcontrol); | ||
2400 | int change; | ||
2401 | |||
2402 | spin_lock_irq(&cm->reg_lock); | ||
2403 | if (ucontrol->value.enumerated.item[0]) | ||
2404 | change = snd_cmipci_set_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); | ||
2405 | else | ||
2406 | change = snd_cmipci_clear_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE); | ||
2407 | spin_unlock_irq(&cm->reg_lock); | ||
2408 | return change; | ||
2409 | } | ||
2410 | |||
2303 | /* both for CM8338/8738 */ | 2411 | /* both for CM8338/8738 */ |
2304 | static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = { | 2412 | static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = { |
2305 | DEFINE_MIXER_SWITCH("Four Channel Mode", fourch), | 2413 | DEFINE_MIXER_SWITCH("Four Channel Mode", fourch), |
2306 | DEFINE_MIXER_SWITCH("Line-In As Rear", line_rear), | 2414 | { |
2415 | .name = "Line-In Mode", | ||
2416 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2417 | .info = snd_cmipci_line_in_mode_info, | ||
2418 | .get = snd_cmipci_line_in_mode_get, | ||
2419 | .put = snd_cmipci_line_in_mode_put, | ||
2420 | }, | ||
2307 | }; | 2421 | }; |
2308 | 2422 | ||
2309 | /* for non-multichannel chips */ | 2423 | /* for non-multichannel chips */ |
@@ -2341,10 +2455,15 @@ static snd_kcontrol_new_t snd_cmipci_old_mixer_switches[] __devinitdata = { | |||
2341 | 2455 | ||
2342 | /* only for model 039 or later */ | 2456 | /* only for model 039 or later */ |
2343 | static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = { | 2457 | 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), | 2458 | DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2), |
2346 | DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2), | 2459 | DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2), |
2347 | DEFINE_MIXER_SWITCH("Mic As Center/LFE", spdi_phase), /* same bit as spdi_phase */ | 2460 | { |
2461 | .name = "Mic-In Mode", | ||
2462 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2463 | .info = snd_cmipci_mic_in_mode_info, | ||
2464 | .get = snd_cmipci_mic_in_mode_get, | ||
2465 | .put = snd_cmipci_mic_in_mode_put, | ||
2466 | } | ||
2348 | }; | 2467 | }; |
2349 | 2468 | ||
2350 | /* card control switches */ | 2469 | /* card control switches */ |
@@ -2944,7 +3063,7 @@ static struct pci_driver driver = { | |||
2944 | 3063 | ||
2945 | static int __init alsa_card_cmipci_init(void) | 3064 | static int __init alsa_card_cmipci_init(void) |
2946 | { | 3065 | { |
2947 | return pci_module_init(&driver); | 3066 | return pci_register_driver(&driver); |
2948 | } | 3067 | } |
2949 | 3068 | ||
2950 | static void __exit alsa_card_cmipci_exit(void) | 3069 | static void __exit alsa_card_cmipci_exit(void) |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index d7e06b3caf97..b6e1854e9389 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) */ |
@@ -1461,6 +1464,11 @@ static int snd_cs4281_chip_init(cs4281_t *chip) | |||
1461 | int timeout; | 1464 | int timeout; |
1462 | int retry_count = 2; | 1465 | int retry_count = 2; |
1463 | 1466 | ||
1467 | /* Having EPPMC.FPDN=1 prevent proper chip initialisation */ | ||
1468 | tmp = snd_cs4281_peekBA0(chip, BA0_EPPMC); | ||
1469 | if (tmp & BA0_EPPMC_FPDN) | ||
1470 | snd_cs4281_pokeBA0(chip, BA0_EPPMC, tmp & ~BA0_EPPMC_FPDN); | ||
1471 | |||
1464 | __retry: | 1472 | __retry: |
1465 | tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); | 1473 | tmp = snd_cs4281_peekBA0(chip, BA0_CFLR); |
1466 | if (tmp != BA0_CFLR_DEFAULT) { | 1474 | if (tmp != BA0_CFLR_DEFAULT) { |
@@ -2124,7 +2132,7 @@ static struct pci_driver driver = { | |||
2124 | 2132 | ||
2125 | static int __init alsa_card_cs4281_init(void) | 2133 | static int __init alsa_card_cs4281_init(void) |
2126 | { | 2134 | { |
2127 | return pci_module_init(&driver); | 2135 | return pci_register_driver(&driver); |
2128 | } | 2136 | } |
2129 | 2137 | ||
2130 | static void __exit alsa_card_cs4281_exit(void) | 2138 | 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/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 6446afe19d80..2085a998eaeb 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -228,7 +228,7 @@ static struct pci_driver driver = { | |||
228 | 228 | ||
229 | static int __init alsa_card_emu10k1_init(void) | 229 | static int __init alsa_card_emu10k1_init(void) |
230 | { | 230 | { |
231 | return pci_module_init(&driver); | 231 | return pci_register_driver(&driver); |
232 | } | 232 | } |
233 | 233 | ||
234 | static void __exit alsa_card_emu10k1_exit(void) | 234 | 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..77be07283bb0 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,7 +189,7 @@ 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->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */ |
195 | /* Hacks for Alice3 to work independent of haP16V driver */ | 195 | /* Hacks for Alice3 to work independent of haP16V driver */ |
@@ -600,7 +600,7 @@ static int snd_emu10k1_free(emu10k1_t *emu) | |||
600 | if (emu->port) | 600 | if (emu->port) |
601 | pci_release_regions(emu->pci); | 601 | pci_release_regions(emu->pci); |
602 | pci_disable_device(emu->pci); | 602 | pci_disable_device(emu->pci); |
603 | if (emu->audigy && emu->revision == 4) /* P16V */ | 603 | if (emu->card_capabilities->ca0151_chip) /* P16V */ |
604 | snd_p16v_free(emu); | 604 | snd_p16v_free(emu); |
605 | kfree(emu); | 605 | kfree(emu); |
606 | return 0; | 606 | return 0; |
@@ -612,21 +612,24 @@ static int snd_emu10k1_dev_free(snd_device_t *device) | |||
612 | return snd_emu10k1_free(emu); | 612 | return snd_emu10k1_free(emu); |
613 | } | 613 | } |
614 | 614 | ||
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[] = { | 615 | 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.*/ | 616 | /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ |
619 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, | 617 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, |
620 | .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", | 618 | .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", |
619 | .id = "Audigy2", | ||
621 | .emu10k2_chip = 1, | 620 | .emu10k2_chip = 1, |
622 | .ca0108_chip = 1, | 621 | .ca0108_chip = 1, |
623 | .spk71 = 1} , | 622 | .spk71 = 1, |
623 | .ac97_chip = 1} , | ||
624 | {.vendor = 0x1102, .device = 0x0008, | 624 | {.vendor = 0x1102, .device = 0x0008, |
625 | .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", | 625 | .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", |
626 | .id = "Audigy2", | ||
626 | .emu10k2_chip = 1, | 627 | .emu10k2_chip = 1, |
627 | .ca0108_chip = 1} , | 628 | .ca0108_chip = 1, |
629 | .ac97_chip = 1} , | ||
628 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, | 630 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, |
629 | .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", | 631 | .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", |
632 | .id = "Audigy2", | ||
630 | .emu10k2_chip = 1, | 633 | .emu10k2_chip = 1, |
631 | .ca0102_chip = 1, | 634 | .ca0102_chip = 1, |
632 | .ca0151_chip = 1, | 635 | .ca0151_chip = 1, |
@@ -635,6 +638,7 @@ static emu_chip_details_t emu_chip_details[] = { | |||
635 | .ac97_chip = 1} , | 638 | .ac97_chip = 1} , |
636 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, | 639 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, |
637 | .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", | 640 | .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", |
641 | .id = "Audigy2", | ||
638 | .emu10k2_chip = 1, | 642 | .emu10k2_chip = 1, |
639 | .ca0102_chip = 1, | 643 | .ca0102_chip = 1, |
640 | .ca0151_chip = 1, | 644 | .ca0151_chip = 1, |
@@ -643,6 +647,7 @@ static emu_chip_details_t emu_chip_details[] = { | |||
643 | .ac97_chip = 1} , | 647 | .ac97_chip = 1} , |
644 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, | 648 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, |
645 | .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", | 649 | .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", |
650 | .id = "Audigy2", | ||
646 | .emu10k2_chip = 1, | 651 | .emu10k2_chip = 1, |
647 | .ca0102_chip = 1, | 652 | .ca0102_chip = 1, |
648 | .ca0151_chip = 1, | 653 | .ca0151_chip = 1, |
@@ -651,6 +656,7 @@ static emu_chip_details_t emu_chip_details[] = { | |||
651 | .ac97_chip = 1} , | 656 | .ac97_chip = 1} , |
652 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, | 657 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, |
653 | .driver = "Audigy2", .name = "Audigy 2 [SB0240]", | 658 | .driver = "Audigy2", .name = "Audigy 2 [SB0240]", |
659 | .id = "Audigy2", | ||
654 | .emu10k2_chip = 1, | 660 | .emu10k2_chip = 1, |
655 | .ca0102_chip = 1, | 661 | .ca0102_chip = 1, |
656 | .ca0151_chip = 1, | 662 | .ca0151_chip = 1, |
@@ -659,35 +665,87 @@ static emu_chip_details_t emu_chip_details[] = { | |||
659 | .ac97_chip = 1} , | 665 | .ac97_chip = 1} , |
660 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, | 666 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, |
661 | .driver = "Audigy2", .name = "Audigy 2 EX [1005]", | 667 | .driver = "Audigy2", .name = "Audigy 2 EX [1005]", |
668 | .id = "Audigy2", | ||
662 | .emu10k2_chip = 1, | 669 | .emu10k2_chip = 1, |
663 | .ca0102_chip = 1, | 670 | .ca0102_chip = 1, |
664 | .ca0151_chip = 1, | 671 | .ca0151_chip = 1, |
665 | .spdif_bug = 1} , | 672 | .spdif_bug = 1} , |
666 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, | 673 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, |
667 | .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", | 674 | .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", |
675 | .id = "Audigy2", | ||
668 | .emu10k2_chip = 1, | 676 | .emu10k2_chip = 1, |
669 | .ca0102_chip = 1, | 677 | .ca0102_chip = 1, |
670 | .ca0151_chip = 1, | 678 | .ca0151_chip = 1, |
671 | .spk71 = 1, | 679 | .spk71 = 1, |
672 | .spdif_bug = 1, | 680 | .spdif_bug = 1, |
673 | .ac97_chip = 1} , | 681 | .ac97_chip = 1} , |
682 | {.vendor = 0x1102, .device = 0x0004, .revision = 0x04, | ||
683 | .driver = "Audigy2", .name = "Audigy 2 [Unknown]", | ||
684 | .id = "Audigy2", | ||
685 | .emu10k2_chip = 1, | ||
686 | .ca0102_chip = 1, | ||
687 | .ca0151_chip = 1, | ||
688 | .spdif_bug = 1, | ||
689 | .ac97_chip = 1} , | ||
690 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10020052, | ||
691 | .driver = "Audigy", .name = "Audigy 1 ES [SB0160]", | ||
692 | .id = "Audigy", | ||
693 | .emu10k2_chip = 1, | ||
694 | .ca0102_chip = 1, | ||
695 | .spdif_bug = 1, | ||
696 | .ac97_chip = 1} , | ||
697 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102, | ||
698 | .driver = "Audigy", .name = "Audigy 1 [SB0090]", | ||
699 | .id = "Audigy", | ||
700 | .emu10k2_chip = 1, | ||
701 | .ca0102_chip = 1, | ||
702 | .ac97_chip = 1} , | ||
703 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102, | ||
704 | .driver = "Audigy", .name = "Audigy 1 [SB0090]", | ||
705 | .id = "Audigy", | ||
706 | .emu10k2_chip = 1, | ||
707 | .ca0102_chip = 1, | ||
708 | .ac97_chip = 1} , | ||
674 | {.vendor = 0x1102, .device = 0x0004, | 709 | {.vendor = 0x1102, .device = 0x0004, |
675 | .driver = "Audigy", .name = "Audigy 1 or 2 [Unknown]", | 710 | .driver = "Audigy", .name = "Audigy 1 [Unknown]", |
711 | .id = "Audigy", | ||
676 | .emu10k2_chip = 1, | 712 | .emu10k2_chip = 1, |
677 | .ca0102_chip = 1, | 713 | .ca0102_chip = 1, |
678 | .spdif_bug = 1} , | 714 | .ac97_chip = 1} , |
679 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, | 715 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, |
680 | .driver = "EMU10K1", .name = "E-mu APS [4001]", | 716 | .driver = "EMU10K1", .name = "E-mu APS [4001]", |
717 | .id = "APS", | ||
681 | .emu10k1_chip = 1, | 718 | .emu10k1_chip = 1, |
682 | .ecard = 1} , | 719 | .ecard = 1} , |
720 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, | ||
721 | .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]", | ||
722 | .id = "Live", | ||
723 | .emu10k1_chip = 1, | ||
724 | .ac97_chip = 1, | ||
725 | .sblive51 = 1} , | ||
683 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, | 726 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, |
684 | .driver = "EMU10K1", .name = "SB Live 5.1", | 727 | .driver = "EMU10K1", .name = "SB Live 5.1", |
728 | .id = "Live", | ||
729 | .emu10k1_chip = 1, | ||
730 | .ac97_chip = 1, | ||
731 | .sblive51 = 1} , | ||
732 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, | ||
733 | .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]", | ||
734 | .id = "Live", | ||
685 | .emu10k1_chip = 1, | 735 | .emu10k1_chip = 1, |
686 | .ac97_chip = 1} , | 736 | .ac97_chip = 1} , |
737 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102, | ||
738 | .driver = "EMU10K1", .name = "SBLive! Value [CT4832]", | ||
739 | .id = "Live", | ||
740 | .emu10k1_chip = 1, | ||
741 | .ac97_chip = 1, | ||
742 | .sblive51 = 1} , | ||
687 | {.vendor = 0x1102, .device = 0x0002, | 743 | {.vendor = 0x1102, .device = 0x0002, |
688 | .driver = "EMU10K1", .name = "SB Live [Unknown]", | 744 | .driver = "EMU10K1", .name = "SB Live [Unknown]", |
745 | .id = "Live", | ||
689 | .emu10k1_chip = 1, | 746 | .emu10k1_chip = 1, |
690 | .ac97_chip = 1} , | 747 | .ac97_chip = 1, |
748 | .sblive51 = 1} , | ||
691 | { } /* terminator */ | 749 | { } /* terminator */ |
692 | }; | 750 | }; |
693 | 751 | ||
@@ -738,13 +796,15 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
738 | emu->revision = revision; | 796 | emu->revision = revision; |
739 | pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); | 797 | pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); |
740 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model); | 798 | 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); | 799 | 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 | 800 | ||
744 | for (c = emu_chip_details; c->vendor; c++) { | 801 | for (c = emu_chip_details; c->vendor; c++) { |
745 | if (c->vendor == pci->vendor && c->device == pci->device) { | 802 | if (c->vendor == pci->vendor && c->device == pci->device) { |
746 | if (c->subsystem == emu->serial) break; | 803 | if (c->subsystem && c->subsystem != emu->serial) |
747 | if (c->subsystem == 0) break; | 804 | continue; |
805 | if (c->revision && c->revision != emu->revision) | ||
806 | continue; | ||
807 | break; | ||
748 | } | 808 | } |
749 | } | 809 | } |
750 | if (c->vendor == 0) { | 810 | if (c->vendor == 0) { |
@@ -759,6 +819,23 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
759 | else | 819 | else |
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); | 820 | snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial); |
761 | 821 | ||
822 | if (!*card->id && c->id) { | ||
823 | int i, n = 0; | ||
824 | strlcpy(card->id, c->id, sizeof(card->id)); | ||
825 | for (;;) { | ||
826 | for (i = 0; i < snd_ecards_limit; i++) { | ||
827 | if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id)) | ||
828 | break; | ||
829 | } | ||
830 | if (i >= snd_ecards_limit) | ||
831 | break; | ||
832 | n++; | ||
833 | if (n >= SNDRV_CARDS) | ||
834 | break; | ||
835 | snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n); | ||
836 | } | ||
837 | } | ||
838 | |||
762 | is_audigy = emu->audigy = c->emu10k2_chip; | 839 | is_audigy = emu->audigy = c->emu10k2_chip; |
763 | 840 | ||
764 | /* set the DMA transfer mask */ | 841 | /* set the DMA transfer mask */ |
@@ -816,15 +893,6 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
816 | 893 | ||
817 | pci_set_master(pci); | 894 | pci_set_master(pci); |
818 | 895 | ||
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; | 896 | emu->fx8010.fxbus_mask = 0x303f; |
829 | if (extin_mask == 0) | 897 | if (extin_mask == 0) |
830 | extin_mask = 0x3fcf; | 898 | extin_mask = 0x3fcf; |
@@ -833,7 +901,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
833 | emu->fx8010.extin_mask = extin_mask; | 901 | emu->fx8010.extin_mask = extin_mask; |
834 | emu->fx8010.extout_mask = extout_mask; | 902 | emu->fx8010.extout_mask = extout_mask; |
835 | 903 | ||
836 | if (emu->APS) { | 904 | if (emu->card_capabilities->ecard) { |
837 | if ((err = snd_emu10k1_ecard_init(emu)) < 0) { | 905 | if ((err = snd_emu10k1_ecard_init(emu)) < 0) { |
838 | snd_emu10k1_free(emu); | 906 | snd_emu10k1_free(emu); |
839 | return err; | 907 | return err; |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 27dfd8ddddf4..f8d92335a353 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -1075,6 +1075,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); | 1075 | snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read); |
1076 | entry->c.text.write_size = 64; | 1076 | entry->c.text.write_size = 64; |
1077 | entry->c.text.write = snd_emu10k1x_proc_reg_write; | 1077 | entry->c.text.write = snd_emu10k1x_proc_reg_write; |
1078 | entry->mode |= S_IWUSR; | ||
1078 | entry->private_data = emu; | 1079 | entry->private_data = emu; |
1079 | } | 1080 | } |
1080 | 1081 | ||
@@ -1627,7 +1628,7 @@ static int __init alsa_card_emu10k1x_init(void) | |||
1627 | { | 1628 | { |
1628 | int err; | 1629 | int err; |
1629 | 1630 | ||
1630 | if ((err = pci_module_init(&driver)) > 0) | 1631 | if ((err = pci_register_driver(&driver)) > 0) |
1631 | return err; | 1632 | return err; |
1632 | 1633 | ||
1633 | return 0; | 1634 | 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..fd7cc389f82a 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; |
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/p16v.c b/sound/pci/emu10k1/p16v.c index d03cb2fefc9e..98f980189892 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 | } |
@@ -694,6 +891,106 @@ static snd_kcontrol_new_t snd_p16v_volume_control_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 Capture source", | ||
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 Capture channel", | ||
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..4e63498a58b2 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -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..ea889b311390 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -2559,6 +2559,7 @@ static struct ess_device_list pm_whitelist[] __devinitdata = { | |||
2559 | { TYPE_MAESTRO2E, 0x103c }, | 2559 | { TYPE_MAESTRO2E, 0x103c }, |
2560 | { TYPE_MAESTRO2E, 0x1179 }, | 2560 | { TYPE_MAESTRO2E, 0x1179 }, |
2561 | { TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */ | 2561 | { TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */ |
2562 | { TYPE_MAESTRO2E, 0x1558 }, | ||
2562 | }; | 2563 | }; |
2563 | 2564 | ||
2564 | static struct ess_device_list mpu_blacklist[] __devinitdata = { | 2565 | static struct ess_device_list mpu_blacklist[] __devinitdata = { |
@@ -2795,7 +2796,7 @@ static struct pci_driver driver = { | |||
2795 | 2796 | ||
2796 | static int __init alsa_card_es1968_init(void) | 2797 | static int __init alsa_card_es1968_init(void) |
2797 | { | 2798 | { |
2798 | return pci_module_init(&driver); | 2799 | return pci_register_driver(&driver); |
2799 | } | 2800 | } |
2800 | 2801 | ||
2801 | static void __exit alsa_card_es1968_exit(void) | 2802 | 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..e6efaed4b464 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, |
@@ -658,7 +663,7 @@ static void put_vol_mute(struct hda_codec *codec, | |||
658 | /* | 663 | /* |
659 | * read/write AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. | 664 | * read/write AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit. |
660 | */ | 665 | */ |
661 | int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index) | 666 | static int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index) |
662 | { | 667 | { |
663 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); | 668 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index)); |
664 | if (! info) | 669 | if (! info) |
@@ -667,7 +672,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int d | |||
667 | return info->vol[ch]; | 672 | return info->vol[ch]; |
668 | } | 673 | } |
669 | 674 | ||
670 | int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val) | 675 | static int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val) |
671 | { | 676 | { |
672 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); | 677 | struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx)); |
673 | if (! info) | 678 | if (! info) |
@@ -1448,10 +1453,6 @@ static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream | |||
1448 | snd_assert(info->nid, return -EINVAL); | 1453 | snd_assert(info->nid, return -EINVAL); |
1449 | info->ops.prepare = hda_pcm_default_prepare; | 1454 | info->ops.prepare = hda_pcm_default_prepare; |
1450 | } | 1455 | } |
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) { | 1456 | if (info->ops.cleanup == NULL) { |
1456 | snd_assert(info->nid, return -EINVAL); | 1457 | snd_assert(info->nid, return -EINVAL); |
1457 | info->ops.cleanup = hda_pcm_default_cleanup; | 1458 | info->ops.cleanup = hda_pcm_default_cleanup; |
@@ -1530,7 +1531,7 @@ int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config | |||
1530 | struct hda_board_config *c; | 1531 | struct hda_board_config *c; |
1531 | 1532 | ||
1532 | if (codec->bus->modelname) { | 1533 | if (codec->bus->modelname) { |
1533 | for (c = tbl; c->modelname || c->pci_vendor; c++) { | 1534 | for (c = tbl; c->modelname || c->pci_subvendor; c++) { |
1534 | if (c->modelname && | 1535 | if (c->modelname && |
1535 | ! strcmp(codec->bus->modelname, c->modelname)) { | 1536 | ! strcmp(codec->bus->modelname, c->modelname)) { |
1536 | snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname); | 1537 | snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname); |
@@ -1543,9 +1544,9 @@ int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config | |||
1543 | u16 subsystem_vendor, subsystem_device; | 1544 | u16 subsystem_vendor, subsystem_device; |
1544 | pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); | 1545 | 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); | 1546 | pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device); |
1546 | for (c = tbl; c->modelname || c->pci_vendor; c++) { | 1547 | for (c = tbl; c->modelname || c->pci_subvendor; c++) { |
1547 | if (c->pci_vendor == subsystem_vendor && | 1548 | if (c->pci_subvendor == subsystem_vendor && |
1548 | c->pci_device == subsystem_device) | 1549 | c->pci_subdevice == subsystem_device) |
1549 | return c->config; | 1550 | return c->config; |
1550 | } | 1551 | } |
1551 | } | 1552 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index c9e9dc9c7c98..1b1203539ea6 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -176,16 +176,15 @@ enum { | |||
176 | #define AC_PINCAP_OUT (1<<4) /* output capable */ | 176 | #define AC_PINCAP_OUT (1<<4) /* output capable */ |
177 | #define AC_PINCAP_IN (1<<5) /* input capable */ | 177 | #define AC_PINCAP_IN (1<<5) /* input capable */ |
178 | #define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */ | 178 | #define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */ |
179 | #define AC_PINCAP_VREF (7<<8) | 179 | #define AC_PINCAP_VREF (0x37<<8) |
180 | #define AC_PINCAP_VREF_SHIFT 8 | 180 | #define AC_PINCAP_VREF_SHIFT 8 |
181 | #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ | 181 | #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ |
182 | /* Vref status (used in pin cap and pin ctl) */ | 182 | /* Vref status (used in pin cap) */ |
183 | #define AC_PIN_VREF_HIZ (1<<0) /* Hi-Z */ | 183 | #define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */ |
184 | #define AC_PIN_VREF_50 (1<<1) /* 50% */ | 184 | #define AC_PINCAP_VREF_50 (1<<1) /* 50% */ |
185 | #define AC_PIN_VREF_GRD (1<<2) /* ground */ | 185 | #define AC_PINCAP_VREF_GRD (1<<2) /* ground */ |
186 | #define AC_PIN_VREF_80 (1<<4) /* 80% */ | 186 | #define AC_PINCAP_VREF_80 (1<<4) /* 80% */ |
187 | #define AC_PIN_VREF_100 (1<<5) /* 100% */ | 187 | #define AC_PINCAP_VREF_100 (1<<5) /* 100% */ |
188 | |||
189 | 188 | ||
190 | /* Amplifier capabilities */ | 189 | /* Amplifier capabilities */ |
191 | #define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */ | 190 | #define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */ |
@@ -248,6 +247,11 @@ enum { | |||
248 | 247 | ||
249 | /* Pin widget control - 8bit */ | 248 | /* Pin widget control - 8bit */ |
250 | #define AC_PINCTL_VREFEN (0x7<<0) | 249 | #define AC_PINCTL_VREFEN (0x7<<0) |
250 | #define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ | ||
251 | #define AC_PINCTL_VREF_50 1 /* 50% */ | ||
252 | #define AC_PINCTL_VREF_GRD 2 /* ground */ | ||
253 | #define AC_PINCTL_VREF_80 4 /* 80% */ | ||
254 | #define AC_PINCTL_VREF_100 5 /* 100% */ | ||
251 | #define AC_PINCTL_IN_EN (1<<5) | 255 | #define AC_PINCTL_IN_EN (1<<5) |
252 | #define AC_PINCTL_OUT_EN (1<<6) | 256 | #define AC_PINCTL_OUT_EN (1<<6) |
253 | #define AC_PINCTL_HP_EN (1<<7) | 257 | #define AC_PINCTL_HP_EN (1<<7) |
@@ -255,7 +259,9 @@ enum { | |||
255 | /* configuration default - 32bit */ | 259 | /* configuration default - 32bit */ |
256 | #define AC_DEFCFG_SEQUENCE (0xf<<0) | 260 | #define AC_DEFCFG_SEQUENCE (0xf<<0) |
257 | #define AC_DEFCFG_DEF_ASSOC (0xf<<4) | 261 | #define AC_DEFCFG_DEF_ASSOC (0xf<<4) |
262 | #define AC_DEFCFG_ASSOC_SHIFT 4 | ||
258 | #define AC_DEFCFG_MISC (0xf<<8) | 263 | #define AC_DEFCFG_MISC (0xf<<8) |
264 | #define AC_DEFCFG_MISC_SHIFT 8 | ||
259 | #define AC_DEFCFG_COLOR (0xf<<12) | 265 | #define AC_DEFCFG_COLOR (0xf<<12) |
260 | #define AC_DEFCFG_COLOR_SHIFT 12 | 266 | #define AC_DEFCFG_COLOR_SHIFT 12 |
261 | #define AC_DEFCFG_CONN_TYPE (0xf<<16) | 267 | #define AC_DEFCFG_CONN_TYPE (0xf<<16) |
@@ -413,7 +419,7 @@ struct hda_bus { | |||
413 | 419 | ||
414 | /* codec linked list */ | 420 | /* codec linked list */ |
415 | struct list_head codec_list; | 421 | struct list_head codec_list; |
416 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS]; /* caddr -> codec */ | 422 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */ |
417 | 423 | ||
418 | struct semaphore cmd_mutex; | 424 | struct semaphore cmd_mutex; |
419 | 425 | ||
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 69f7b6c4cf83..bfbeff2e0d0c 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 */ |
@@ -426,7 +426,7 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) | |||
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..f05a6384b9c0 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 */ |
@@ -183,6 +189,18 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
183 | #define ICH6_MAX_CORB_ENTRIES 256 | 189 | #define ICH6_MAX_CORB_ENTRIES 256 |
184 | #define ICH6_MAX_RIRB_ENTRIES 256 | 190 | #define ICH6_MAX_RIRB_ENTRIES 256 |
185 | 191 | ||
192 | /* position fix mode */ | ||
193 | enum { | ||
194 | POS_FIX_FIFO, | ||
195 | POS_FIX_NONE, | ||
196 | POS_FIX_POSBUF | ||
197 | }; | ||
198 | |||
199 | /* Defines for ATI HD Audio support in SB450 south bridge */ | ||
200 | #define ATI_SB450_HDAUDIO_PCI_DEVICE_ID 0x437b | ||
201 | #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 | ||
202 | #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 | ||
203 | |||
186 | 204 | ||
187 | /* | 205 | /* |
188 | * Use CORB/RIRB for communication from/to codecs. | 206 | * Use CORB/RIRB for communication from/to codecs. |
@@ -191,12 +209,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
191 | #define USE_CORB_RIRB | 209 | #define USE_CORB_RIRB |
192 | 210 | ||
193 | /* | 211 | /* |
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 | */ | 212 | */ |
201 | 213 | ||
202 | typedef struct snd_azx azx_t; | 214 | typedef struct snd_azx azx_t; |
@@ -271,6 +283,9 @@ struct snd_azx { | |||
271 | struct snd_dma_buffer bdl; | 283 | struct snd_dma_buffer bdl; |
272 | struct snd_dma_buffer rb; | 284 | struct snd_dma_buffer rb; |
273 | struct snd_dma_buffer posbuf; | 285 | struct snd_dma_buffer posbuf; |
286 | |||
287 | /* flags */ | ||
288 | int position_fix; | ||
274 | }; | 289 | }; |
275 | 290 | ||
276 | /* | 291 | /* |
@@ -638,7 +653,7 @@ static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev) | |||
638 | */ | 653 | */ |
639 | static void azx_init_chip(azx_t *chip) | 654 | static void azx_init_chip(azx_t *chip) |
640 | { | 655 | { |
641 | unsigned char tcsel_reg; | 656 | unsigned char tcsel_reg, ati_misc_cntl2; |
642 | 657 | ||
643 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) | 658 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) |
644 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS | 659 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS |
@@ -657,11 +672,20 @@ static void azx_init_chip(azx_t *chip) | |||
657 | /* initialize the codec command I/O */ | 672 | /* initialize the codec command I/O */ |
658 | azx_init_cmd_io(chip); | 673 | azx_init_cmd_io(chip); |
659 | 674 | ||
660 | #ifdef USE_POSBUF | 675 | if (chip->position_fix == POS_FIX_POSBUF) { |
661 | /* program the position buffer */ | 676 | /* program the position buffer */ |
662 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); | 677 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); |
663 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); | 678 | azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr)); |
664 | #endif | 679 | } |
680 | |||
681 | /* For ATI SB450 azalia HD audio, we need to enable snoop */ | ||
682 | if (chip->pci->vendor == PCI_VENDOR_ID_ATI && | ||
683 | chip->pci->device == ATI_SB450_HDAUDIO_PCI_DEVICE_ID) { | ||
684 | pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | ||
685 | &ati_misc_cntl2); | ||
686 | pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, | ||
687 | (ati_misc_cntl2 & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP); | ||
688 | } | ||
665 | } | 689 | } |
666 | 690 | ||
667 | 691 | ||
@@ -791,11 +815,12 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev) | |||
791 | /* upper BDL address */ | 815 | /* upper BDL address */ |
792 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); | 816 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr)); |
793 | 817 | ||
794 | #ifdef USE_POSBUF | 818 | if (chip->position_fix == POS_FIX_POSBUF) { |
795 | /* enable the position buffer */ | 819 | /* enable the position buffer */ |
796 | if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 820 | if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) |
797 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); | 821 | azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); |
798 | #endif | 822 | } |
823 | |||
799 | /* set the interrupt enable bits in the descriptor control register */ | 824 | /* 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); | 825 | azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK); |
801 | 826 | ||
@@ -1036,16 +1061,20 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | |||
1036 | 1061 | ||
1037 | static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream) | 1062 | static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream) |
1038 | { | 1063 | { |
1064 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | ||
1065 | azx_t *chip = apcm->chip; | ||
1039 | azx_dev_t *azx_dev = get_azx_dev(substream); | 1066 | azx_dev_t *azx_dev = get_azx_dev(substream); |
1040 | unsigned int pos; | 1067 | unsigned int pos; |
1041 | 1068 | ||
1042 | #ifdef USE_POSBUF | 1069 | if (chip->position_fix == POS_FIX_POSBUF) { |
1043 | /* use the position buffer */ | 1070 | /* use the position buffer */ |
1044 | pos = *azx_dev->posbuf; | 1071 | pos = *azx_dev->posbuf; |
1045 | #else | 1072 | } else { |
1046 | /* read LPIB */ | 1073 | /* read LPIB */ |
1047 | pos = azx_sd_readl(azx_dev, SD_LPIB) + azx_dev->fifo_size; | 1074 | pos = azx_sd_readl(azx_dev, SD_LPIB); |
1048 | #endif | 1075 | if (chip->position_fix == POS_FIX_FIFO) |
1076 | pos += azx_dev->fifo_size; | ||
1077 | } | ||
1049 | if (pos >= azx_dev->bufsize) | 1078 | if (pos >= azx_dev->bufsize) |
1050 | pos = 0; | 1079 | pos = 0; |
1051 | return bytes_to_frames(substream->runtime, pos); | 1080 | return bytes_to_frames(substream->runtime, pos); |
@@ -1155,9 +1184,8 @@ static int __devinit azx_init_stream(azx_t *chip) | |||
1155 | azx_dev_t *azx_dev = &chip->azx_dev[i]; | 1184 | azx_dev_t *azx_dev = &chip->azx_dev[i]; |
1156 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); | 1185 | azx_dev->bdl = (u32 *)(chip->bdl.area + off); |
1157 | azx_dev->bdl_addr = chip->bdl.addr + off; | 1186 | azx_dev->bdl_addr = chip->bdl.addr + off; |
1158 | #ifdef USE_POSBUF | 1187 | if (chip->position_fix == POS_FIX_POSBUF) |
1159 | azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); | 1188 | azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); |
1160 | #endif | ||
1161 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ | 1189 | /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ |
1162 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); | 1190 | azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); |
1163 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ | 1191 | /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ |
@@ -1237,10 +1265,8 @@ static int azx_free(azx_t *chip) | |||
1237 | snd_dma_free_pages(&chip->bdl); | 1265 | snd_dma_free_pages(&chip->bdl); |
1238 | if (chip->rb.area) | 1266 | if (chip->rb.area) |
1239 | snd_dma_free_pages(&chip->rb); | 1267 | snd_dma_free_pages(&chip->rb); |
1240 | #ifdef USE_POSBUF | ||
1241 | if (chip->posbuf.area) | 1268 | if (chip->posbuf.area) |
1242 | snd_dma_free_pages(&chip->posbuf); | 1269 | snd_dma_free_pages(&chip->posbuf); |
1243 | #endif | ||
1244 | pci_release_regions(chip->pci); | 1270 | pci_release_regions(chip->pci); |
1245 | pci_disable_device(chip->pci); | 1271 | pci_disable_device(chip->pci); |
1246 | kfree(chip); | 1272 | kfree(chip); |
@@ -1256,7 +1282,8 @@ static int azx_dev_free(snd_device_t *device) | |||
1256 | /* | 1282 | /* |
1257 | * constructor | 1283 | * constructor |
1258 | */ | 1284 | */ |
1259 | static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip) | 1285 | static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, |
1286 | int posfix, azx_t **rchip) | ||
1260 | { | 1287 | { |
1261 | azx_t *chip; | 1288 | azx_t *chip; |
1262 | int err = 0; | 1289 | int err = 0; |
@@ -1283,6 +1310,8 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r | |||
1283 | chip->pci = pci; | 1310 | chip->pci = pci; |
1284 | chip->irq = -1; | 1311 | chip->irq = -1; |
1285 | 1312 | ||
1313 | chip->position_fix = posfix; | ||
1314 | |||
1286 | if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { | 1315 | if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { |
1287 | kfree(chip); | 1316 | kfree(chip); |
1288 | pci_disable_device(pci); | 1317 | pci_disable_device(pci); |
@@ -1314,14 +1343,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"); | 1343 | snd_printk(KERN_ERR SFX "cannot allocate BDL\n"); |
1315 | goto errout; | 1344 | goto errout; |
1316 | } | 1345 | } |
1317 | #ifdef USE_POSBUF | 1346 | if (chip->position_fix == POS_FIX_POSBUF) { |
1318 | /* allocate memory for the position buffer */ | 1347 | /* allocate memory for the position buffer */ |
1319 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), | 1348 | if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), |
1320 | MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) { | 1349 | MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) { |
1321 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); | 1350 | snd_printk(KERN_ERR SFX "cannot allocate posbuf\n"); |
1322 | goto errout; | 1351 | goto errout; |
1352 | } | ||
1323 | } | 1353 | } |
1324 | #endif | ||
1325 | /* allocate CORB/RIRB */ | 1354 | /* allocate CORB/RIRB */ |
1326 | if ((err = azx_alloc_cmd_io(chip)) < 0) | 1355 | if ((err = azx_alloc_cmd_io(chip)) < 0) |
1327 | goto errout; | 1356 | goto errout; |
@@ -1372,7 +1401,7 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * | |||
1372 | return -ENOMEM; | 1401 | return -ENOMEM; |
1373 | } | 1402 | } |
1374 | 1403 | ||
1375 | if ((err = azx_create(card, pci, &chip)) < 0) { | 1404 | if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) { |
1376 | snd_card_free(card); | 1405 | snd_card_free(card); |
1377 | return err; | 1406 | return err; |
1378 | } | 1407 | } |
@@ -1424,6 +1453,8 @@ static struct pci_device_id azx_ids[] = { | |||
1424 | { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */ | 1453 | { 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 */ | 1454 | { 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 */ | 1455 | { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */ |
1456 | { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */ | ||
1457 | { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */ | ||
1427 | { 0, } | 1458 | { 0, } |
1428 | }; | 1459 | }; |
1429 | MODULE_DEVICE_TABLE(pci, azx_ids); | 1460 | MODULE_DEVICE_TABLE(pci, azx_ids); |
@@ -1439,7 +1470,7 @@ static struct pci_driver driver = { | |||
1439 | 1470 | ||
1440 | static int __init alsa_card_azx_init(void) | 1471 | static int __init alsa_card_azx_init(void) |
1441 | { | 1472 | { |
1442 | return pci_module_init(&driver); | 1473 | return pci_register_driver(&driver); |
1443 | } | 1474 | } |
1444 | 1475 | ||
1445 | static void __exit alsa_card_azx_exit(void) | 1476 | 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..b8fbbc4901d9 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -126,8 +126,8 @@ 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, struct hda_board_config *tbl); |
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..15df7162f17e 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -157,6 +157,7 @@ static const char *get_jack_color(u32 cfg) | |||
157 | static void print_pin_caps(snd_info_buffer_t *buffer, | 157 | static void print_pin_caps(snd_info_buffer_t *buffer, |
158 | struct hda_codec *codec, hda_nid_t nid) | 158 | struct hda_codec *codec, hda_nid_t nid) |
159 | { | 159 | { |
160 | static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" }; | ||
160 | static char *jack_types[16] = { | 161 | static char *jack_types[16] = { |
161 | "Line Out", "Speaker", "HP Out", "CD", | 162 | "Line Out", "Speaker", "HP Out", "CD", |
162 | "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", | 163 | "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", |
@@ -176,7 +177,8 @@ static void print_pin_caps(snd_info_buffer_t *buffer, | |||
176 | snd_iprintf(buffer, " HP"); | 177 | snd_iprintf(buffer, " HP"); |
177 | snd_iprintf(buffer, "\n"); | 178 | snd_iprintf(buffer, "\n"); |
178 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 179 | 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, | 180 | snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, |
181 | jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT], | ||
180 | jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT], | 182 | jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT], |
181 | jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3], | 183 | jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3], |
182 | get_jack_location(caps)); | 184 | get_jack_location(caps)); |
@@ -266,13 +268,19 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer) | |||
266 | 268 | ||
267 | if (wid_caps & AC_WCAP_CONN_LIST) { | 269 | if (wid_caps & AC_WCAP_CONN_LIST) { |
268 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; | 270 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; |
269 | int c, conn_len; | 271 | int c, conn_len, curr = -1; |
270 | conn_len = snd_hda_get_connections(codec, nid, conn, | 272 | conn_len = snd_hda_get_connections(codec, nid, conn, |
271 | HDA_MAX_CONNECTIONS); | 273 | HDA_MAX_CONNECTIONS); |
274 | if (conn_len > 1 && wid_type != AC_WID_AUD_MIX) | ||
275 | curr = snd_hda_codec_read(codec, nid, 0, | ||
276 | AC_VERB_GET_CONNECT_SEL, 0); | ||
272 | snd_iprintf(buffer, " Connection: %d\n", conn_len); | 277 | snd_iprintf(buffer, " Connection: %d\n", conn_len); |
273 | snd_iprintf(buffer, " "); | 278 | snd_iprintf(buffer, " "); |
274 | for (c = 0; c < conn_len; c++) | 279 | for (c = 0; c < conn_len; c++) { |
275 | snd_iprintf(buffer, " 0x%02x", conn[c]); | 280 | snd_iprintf(buffer, " 0x%02x", conn[c]); |
281 | if (c == curr) | ||
282 | snd_iprintf(buffer, "*"); | ||
283 | } | ||
276 | snd_iprintf(buffer, "\n"); | 284 | snd_iprintf(buffer, "\n"); |
277 | } | 285 | } |
278 | } | 286 | } |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 75d23849f71a..caa486993446 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); |
@@ -97,7 +323,7 @@ static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ | |||
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..087230ca20a5 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,7 @@ 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 */ | ||
51 | 54 | ||
52 | /* capture */ | 55 | /* capture */ |
53 | hda_nid_t *adc_nids; | 56 | hda_nid_t *adc_nids; |
@@ -63,6 +66,15 @@ struct cmi_spec { | |||
63 | const struct cmi_channel_mode *channel_modes; | 66 | const struct cmi_channel_mode *channel_modes; |
64 | 67 | ||
65 | struct hda_pcm pcm_rec[2]; /* PCM information */ | 68 | struct hda_pcm pcm_rec[2]; /* PCM information */ |
69 | |||
70 | /* pin deafault configuration */ | ||
71 | hda_nid_t pin_nid[NUM_PINS]; | ||
72 | unsigned int def_conf[NUM_PINS]; | ||
73 | unsigned int pin_def_confs; | ||
74 | |||
75 | /* multichannel pins */ | ||
76 | hda_nid_t multich_pin[4]; /* max 8-channel */ | ||
77 | struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */ | ||
66 | }; | 78 | }; |
67 | 79 | ||
68 | /* | 80 | /* |
@@ -278,8 +290,10 @@ static struct hda_verb cmi9880_basic_init[] = { | |||
278 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 290 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, |
279 | /* port-G for CLFE (rear panel) */ | 291 | /* port-G for CLFE (rear panel) */ |
280 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 292 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, |
293 | { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
281 | /* port-H for side (rear panel) */ | 294 | /* port-H for side (rear panel) */ |
282 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 295 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, |
296 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
283 | /* port-C for line-in (rear panel) */ | 297 | /* port-C for line-in (rear panel) */ |
284 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, | 298 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, |
285 | /* port-B for mic-in (rear panel) with vref */ | 299 | /* port-B for mic-in (rear panel) with vref */ |
@@ -305,6 +319,10 @@ static struct hda_verb cmi9880_allout_init[] = { | |||
305 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 319 | { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, |
306 | /* port-G for CLFE (rear panel) */ | 320 | /* port-G for CLFE (rear panel) */ |
307 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 321 | { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, |
322 | { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
323 | /* port-H for side (rear panel) */ | ||
324 | { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | ||
325 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
308 | /* port-C for surround (rear panel) */ | 326 | /* port-C for surround (rear panel) */ |
309 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, | 327 | { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, |
310 | /* port-B for mic-in (rear panel) with vref */ | 328 | /* port-B for mic-in (rear panel) with vref */ |
@@ -347,6 +365,174 @@ static int cmi9880_build_controls(struct hda_codec *codec) | |||
347 | return 0; | 365 | return 0; |
348 | } | 366 | } |
349 | 367 | ||
368 | #define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) | ||
369 | #define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT) | ||
370 | #define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE) | ||
371 | |||
372 | /* get all pin default configuration in def_conf */ | ||
373 | static int cmi9880_get_pin_def_config(struct hda_codec *codec) | ||
374 | { | ||
375 | struct cmi_spec *spec = codec->spec; | ||
376 | hda_nid_t nid, nid_start; | ||
377 | int i = 0, nodes; | ||
378 | |||
379 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); | ||
380 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | ||
381 | unsigned int wid_caps = snd_hda_param_read(codec, nid, | ||
382 | AC_PAR_AUDIO_WIDGET_CAP); | ||
383 | unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
384 | /* read all default configuration for pin complex */ | ||
385 | if (wid_type == AC_WID_PIN) { | ||
386 | spec->pin_nid[i] = nid; | ||
387 | spec->def_conf[i] = | ||
388 | snd_hda_codec_read(codec, nid, 0, | ||
389 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
390 | i++; | ||
391 | } | ||
392 | } | ||
393 | spec->pin_def_confs = i; | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | /* get a pin default configuration of nid in def_conf */ | ||
398 | static unsigned int cmi9880_get_def_config(struct hda_codec *codec, hda_nid_t nid) | ||
399 | { | ||
400 | struct cmi_spec *spec = codec->spec; | ||
401 | int i = 0; | ||
402 | |||
403 | while (spec->pin_nid[i] != nid && i < spec->pin_def_confs) | ||
404 | i++; | ||
405 | if (i == spec->pin_def_confs) | ||
406 | return (unsigned int) -1; | ||
407 | else | ||
408 | return spec->def_conf[i]; | ||
409 | } | ||
410 | |||
411 | /* decide what pins to use for multichannel playback */ | ||
412 | static int cmi9880_get_multich_pins(struct hda_codec *codec) | ||
413 | { | ||
414 | struct cmi_spec *spec = codec->spec; | ||
415 | int i, j, pins, seq[4]; | ||
416 | int max_channel = 0; | ||
417 | unsigned int def_conf, sequence; | ||
418 | hda_nid_t nid; | ||
419 | |||
420 | memset(spec->multich_pin, 0, sizeof(spec->multich_pin)); | ||
421 | for (pins = 0, i = 0; i < spec->pin_def_confs && pins < 4; i++) { | ||
422 | def_conf = spec->def_conf[i]; | ||
423 | /* skip pin not connected */ | ||
424 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | ||
425 | continue; | ||
426 | /* get the sequence if association == 1 */ | ||
427 | /* the other pins have association = 0, incorrect in spec 1.0 */ | ||
428 | if (get_defcfg_association(def_conf) == 1) { | ||
429 | sequence = get_defcfg_sequence(def_conf); | ||
430 | seq[pins] = sequence; | ||
431 | spec->multich_pin[pins] = spec->pin_nid[i]; | ||
432 | pins++; // ready for next slot | ||
433 | max_channel += 2; | ||
434 | } | ||
435 | } | ||
436 | /* sort by sequence, data collected here will be for Windows */ | ||
437 | for (i = 0; i < pins; i++) { | ||
438 | for (j = i + 1; j < pins; j++) { | ||
439 | if (seq[j] < seq[i]) { | ||
440 | sequence = seq[j]; | ||
441 | nid = spec->multich_pin[j]; | ||
442 | seq[j] = seq[i]; | ||
443 | spec->multich_pin[j] = spec->multich_pin[i]; | ||
444 | seq[i] = sequence; | ||
445 | spec->multich_pin[i] = nid; | ||
446 | } | ||
447 | } | ||
448 | } | ||
449 | /* the pin assignment is for front, C/LFE, surround and back */ | ||
450 | if (max_channel >= 6) { | ||
451 | hda_nid_t temp; | ||
452 | /* exchange pin of C/LFE and surround */ | ||
453 | temp = spec->multich_pin[1]; | ||
454 | spec->multich_pin[1] = spec->multich_pin[2]; | ||
455 | spec->multich_pin[2] = temp; | ||
456 | } | ||
457 | return max_channel; | ||
458 | } | ||
459 | |||
460 | /* fill in the multi_dac_nids table, which will decide | ||
461 | which audio widget to use for each channel */ | ||
462 | static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec) | ||
463 | { | ||
464 | struct cmi_spec *spec = codec->spec; | ||
465 | hda_nid_t nid; | ||
466 | int assigned[4]; | ||
467 | int i, j; | ||
468 | |||
469 | /* clear the table, only one c-media dac assumed here */ | ||
470 | memset(spec->dac_nids, 0, sizeof(spec->dac_nids)); | ||
471 | memset(assigned, 0, sizeof(assigned)); | ||
472 | /* check the pins we found */ | ||
473 | for (i = 0; i < spec->multiout.max_channels / 2; i++) { | ||
474 | nid = spec->multich_pin[i]; | ||
475 | /* nid 0x0b~0x0e is hardwired to audio widget 0x3~0x6 */ | ||
476 | if (nid <= 0x0e && nid >= 0x0b) { | ||
477 | spec->dac_nids[i] = nid - 0x08; | ||
478 | assigned[nid - 0x0b] = 1; | ||
479 | } | ||
480 | } | ||
481 | /* left pin can be connect to any audio widget */ | ||
482 | for (i = 0; i < spec->multiout.max_channels / 2; i++) { | ||
483 | if (!assigned[i]) { | ||
484 | /* search for an empty channel */ | ||
485 | /* I should also check the pin type */ | ||
486 | for (j = 0; j < ARRAY_SIZE(spec->dac_nids); j++) | ||
487 | if (! spec->dac_nids[j]) { | ||
488 | spec->dac_nids[j] = i + 3; | ||
489 | assigned[i] = 1; | ||
490 | break; | ||
491 | } | ||
492 | } | ||
493 | } | ||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | /* create multi_init table, which is used for multichannel initialization */ | ||
498 | static int cmi9880_fill_multi_init(struct hda_codec *codec) | ||
499 | { | ||
500 | struct cmi_spec *spec = codec->spec; | ||
501 | hda_nid_t nid; | ||
502 | int i, j, k, len; | ||
503 | |||
504 | /* clear the table, only one c-media dac assumed here */ | ||
505 | memset(spec->multi_init, 0, sizeof(spec->multi_init)); | ||
506 | for (j = 0, i = 0; i < spec->multiout.max_channels / 2; i++) { | ||
507 | hda_nid_t conn[4]; | ||
508 | nid = spec->multich_pin[i]; | ||
509 | /* set as output */ | ||
510 | spec->multi_init[j].nid = nid; | ||
511 | spec->multi_init[j].verb = AC_VERB_SET_PIN_WIDGET_CONTROL; | ||
512 | spec->multi_init[j].param = 0xc0; | ||
513 | j++; | ||
514 | /* nid 0x0f,0x10,0x1f,0x20 are needed to set connection */ | ||
515 | switch (nid) { | ||
516 | case 0x0f: | ||
517 | case 0x10: | ||
518 | case 0x1f: | ||
519 | case 0x20: | ||
520 | /* set connection */ | ||
521 | spec->multi_init[j].nid = nid; | ||
522 | spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL; | ||
523 | /* find the index in connect list */ | ||
524 | len = snd_hda_get_connections(codec, nid, conn, 4); | ||
525 | for (k = 0; k < len; k++) | ||
526 | if (conn[k] == spec->dac_nids[i]) | ||
527 | break; | ||
528 | spec->multi_init[j].param = k < len ? k : 0; | ||
529 | j++; | ||
530 | break; | ||
531 | } | ||
532 | } | ||
533 | return 0; | ||
534 | } | ||
535 | |||
350 | static int cmi9880_init(struct hda_codec *codec) | 536 | static int cmi9880_init(struct hda_codec *codec) |
351 | { | 537 | { |
352 | struct cmi_spec *spec = codec->spec; | 538 | struct cmi_spec *spec = codec->spec; |
@@ -354,6 +540,8 @@ static int cmi9880_init(struct hda_codec *codec) | |||
354 | snd_hda_sequence_write(codec, cmi9880_allout_init); | 540 | snd_hda_sequence_write(codec, cmi9880_allout_init); |
355 | else | 541 | else |
356 | snd_hda_sequence_write(codec, cmi9880_basic_init); | 542 | snd_hda_sequence_write(codec, cmi9880_basic_init); |
543 | if (spec->board_config == CMI_AUTO) | ||
544 | snd_hda_sequence_write(codec, spec->multi_init); | ||
357 | return 0; | 545 | return 0; |
358 | } | 546 | } |
359 | 547 | ||
@@ -540,6 +728,7 @@ static struct hda_board_config cmi9880_cfg_tbl[] = { | |||
540 | { .modelname = "full", .config = CMI_FULL }, | 728 | { .modelname = "full", .config = CMI_FULL }, |
541 | { .modelname = "full_dig", .config = CMI_FULL_DIG }, | 729 | { .modelname = "full_dig", .config = CMI_FULL_DIG }, |
542 | { .modelname = "allout", .config = CMI_ALLOUT }, | 730 | { .modelname = "allout", .config = CMI_ALLOUT }, |
731 | { .modelname = "auto", .config = CMI_AUTO }, | ||
543 | {} /* terminator */ | 732 | {} /* terminator */ |
544 | }; | 733 | }; |
545 | 734 | ||
@@ -564,10 +753,13 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
564 | codec->spec = spec; | 753 | codec->spec = spec; |
565 | spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl); | 754 | spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl); |
566 | if (spec->board_config < 0) { | 755 | if (spec->board_config < 0) { |
567 | snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n"); | 756 | snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n"); |
568 | spec->board_config = CMI_FULL_DIG; /* try everything */ | 757 | spec->board_config = CMI_AUTO; /* try everything */ |
569 | } | 758 | } |
570 | 759 | ||
760 | /* copy default DAC NIDs */ | ||
761 | memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids)); | ||
762 | |||
571 | switch (spec->board_config) { | 763 | switch (spec->board_config) { |
572 | case CMI_MINIMAL: | 764 | case CMI_MINIMAL: |
573 | case CMI_MIN_FP: | 765 | case CMI_MIN_FP: |
@@ -599,10 +791,58 @@ static int patch_cmi9880(struct hda_codec *codec) | |||
599 | spec->input_mux = &cmi9880_no_line_mux; | 791 | spec->input_mux = &cmi9880_no_line_mux; |
600 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | 792 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; |
601 | break; | 793 | break; |
794 | case CMI_AUTO: | ||
795 | { | ||
796 | unsigned int port_e, port_f, port_g, port_h; | ||
797 | unsigned int port_spdifi, port_spdifo; | ||
798 | int max_channels; | ||
799 | /* collect pin default configuration */ | ||
800 | cmi9880_get_pin_def_config(codec); | ||
801 | port_e = cmi9880_get_def_config(codec, 0x0f); | ||
802 | port_f = cmi9880_get_def_config(codec, 0x10); | ||
803 | port_g = cmi9880_get_def_config(codec, 0x1f); | ||
804 | port_h = cmi9880_get_def_config(codec, 0x20); | ||
805 | port_spdifi = cmi9880_get_def_config(codec, 0x13); | ||
806 | port_spdifo = cmi9880_get_def_config(codec, 0x12); | ||
807 | spec->front_panel = 1; | ||
808 | if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE || | ||
809 | get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { | ||
810 | spec->surr_switch = 1; | ||
811 | /* no front panel */ | ||
812 | if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || | ||
813 | get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) { | ||
814 | /* no optional rear panel */ | ||
815 | spec->board_config = CMI_MINIMAL; | ||
816 | spec->front_panel = 0; | ||
817 | spec->num_ch_modes = 2; | ||
818 | } else { | ||
819 | spec->board_config = CMI_MIN_FP; | ||
820 | spec->num_ch_modes = 3; | ||
821 | } | ||
822 | spec->channel_modes = cmi9880_channel_modes; | ||
823 | spec->input_mux = &cmi9880_basic_mux; | ||
824 | spec->multiout.max_channels = cmi9880_channel_modes[0].channels; | ||
825 | } else { | ||
826 | spec->input_mux = &cmi9880_basic_mux; | ||
827 | if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE) | ||
828 | spec->multiout.dig_out_nid = CMI_DIG_OUT_NID; | ||
829 | if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE) | ||
830 | spec->dig_in_nid = CMI_DIG_IN_NID; | ||
831 | spec->multiout.max_channels = 8; | ||
832 | } | ||
833 | max_channels = cmi9880_get_multich_pins(codec); | ||
834 | if (max_channels > 0) { | ||
835 | spec->multiout.max_channels = max_channels; | ||
836 | cmi9880_fill_multi_dac_nids(codec); | ||
837 | cmi9880_fill_multi_init(codec); | ||
838 | } else | ||
839 | snd_printd("patch_cmedia: cannot detect association in defcfg\n"); | ||
840 | break; | ||
841 | } | ||
602 | } | 842 | } |
603 | 843 | ||
604 | spec->multiout.num_dacs = 4; | 844 | spec->multiout.num_dacs = 4; |
605 | spec->multiout.dac_nids = cmi9880_dac_nids; | 845 | spec->multiout.dac_nids = spec->dac_nids; |
606 | 846 | ||
607 | spec->adc_nids = cmi9880_adc_nids; | 847 | spec->adc_nids = cmi9880_adc_nids; |
608 | 848 | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 17c5062423ae..ee1c4cd7f00a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -39,6 +39,8 @@ enum { | |||
39 | ALC880_5ST, | 39 | ALC880_5ST, |
40 | ALC880_5ST_DIG, | 40 | ALC880_5ST_DIG, |
41 | ALC880_W810, | 41 | ALC880_W810, |
42 | ALC880_Z71V, | ||
43 | ALC880_TEST, | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | struct alc_spec { | 46 | struct alc_spec { |
@@ -90,10 +92,25 @@ static hda_nid_t alc880_w810_dac_nids[3] = { | |||
90 | 0x02, 0x03, 0x04 | 92 | 0x02, 0x03, 0x04 |
91 | }; | 93 | }; |
92 | 94 | ||
95 | static hda_nid_t alc880_z71v_dac_nids[1] = { | ||
96 | /* front only? */ | ||
97 | 0x02 | ||
98 | }; | ||
99 | |||
100 | #if 0 | ||
101 | /* The datasheet says the node 0x07 is connected from inputs, | ||
102 | * but it shows zero connection in the real implementation. | ||
103 | */ | ||
93 | static hda_nid_t alc880_adc_nids[3] = { | 104 | static hda_nid_t alc880_adc_nids[3] = { |
94 | /* ADC0-2 */ | 105 | /* ADC0-2 */ |
95 | 0x07, 0x08, 0x09, | 106 | 0x07, 0x08, 0x09, |
96 | }; | 107 | }; |
108 | #else | ||
109 | static hda_nid_t alc880_adc_nids[2] = { | ||
110 | /* ADC1-2 */ | ||
111 | 0x08, 0x09, | ||
112 | }; | ||
113 | #endif | ||
97 | 114 | ||
98 | #define ALC880_DIGOUT_NID 0x06 | 115 | #define ALC880_DIGOUT_NID 0x06 |
99 | #define ALC880_DIGIN_NID 0x0a | 116 | #define ALC880_DIGIN_NID 0x0a |
@@ -284,19 +301,24 @@ static struct alc_channel_mode alc880_w810_modes[1] = { | |||
284 | { 6, NULL } | 301 | { 6, NULL } |
285 | }; | 302 | }; |
286 | 303 | ||
304 | static struct alc_channel_mode alc880_z71v_modes[1] = { | ||
305 | { 2, NULL } | ||
306 | }; | ||
307 | |||
287 | /* | 308 | /* |
288 | */ | 309 | */ |
289 | static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | 310 | static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) |
290 | { | 311 | { |
291 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 312 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
292 | struct alc_spec *spec = codec->spec; | 313 | struct alc_spec *spec = codec->spec; |
314 | int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; | ||
293 | 315 | ||
294 | snd_assert(spec->channel_mode, return -ENXIO); | 316 | snd_assert(spec->channel_mode, return -ENXIO); |
295 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 317 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
296 | uinfo->count = 1; | 318 | uinfo->count = 1; |
297 | uinfo->value.enumerated.items = 2; | 319 | uinfo->value.enumerated.items = items; |
298 | if (uinfo->value.enumerated.item >= 2) | 320 | if (uinfo->value.enumerated.item >= items) |
299 | uinfo->value.enumerated.item = 1; | 321 | uinfo->value.enumerated.item = items - 1; |
300 | sprintf(uinfo->value.enumerated.name, "%dch", | 322 | sprintf(uinfo->value.enumerated.name, "%dch", |
301 | spec->channel_mode[uinfo->value.enumerated.item].channels); | 323 | spec->channel_mode[uinfo->value.enumerated.item].channels); |
302 | return 0; | 324 | return 0; |
@@ -306,10 +328,16 @@ static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc | |||
306 | { | 328 | { |
307 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 329 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
308 | struct alc_spec *spec = codec->spec; | 330 | struct alc_spec *spec = codec->spec; |
331 | int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; | ||
332 | int i; | ||
309 | 333 | ||
310 | snd_assert(spec->channel_mode, return -ENXIO); | 334 | snd_assert(spec->channel_mode, return -ENXIO); |
311 | ucontrol->value.enumerated.item[0] = | 335 | for (i = 0; i < items; i++) { |
312 | (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1; | 336 | if (spec->multiout.max_channels == spec->channel_mode[i].channels) { |
337 | ucontrol->value.enumerated.item[0] = i; | ||
338 | break; | ||
339 | } | ||
340 | } | ||
313 | return 0; | 341 | return 0; |
314 | } | 342 | } |
315 | 343 | ||
@@ -362,10 +390,11 @@ static snd_kcontrol_new_t alc880_base_mixer[] = { | |||
362 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 390 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
363 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 391 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
364 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), | 392 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), |
365 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | 393 | /* We don't use NID 0x07 - see above */ |
366 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | 394 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
367 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | 395 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
368 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | 396 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), |
397 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
369 | { | 398 | { |
370 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 399 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
371 | /* The multiple "Capture Source" controls confuse alsamixer | 400 | /* The multiple "Capture Source" controls confuse alsamixer |
@@ -416,10 +445,11 @@ static snd_kcontrol_new_t alc880_five_stack_mixer[] = { | |||
416 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 445 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
417 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 446 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
418 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), | 447 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT), |
419 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | 448 | /* We don't use NID 0x07 - see above */ |
420 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | 449 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
421 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | 450 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
422 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | 451 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), |
452 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
423 | { | 453 | { |
424 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 454 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
425 | /* The multiple "Capture Source" controls confuse alsamixer | 455 | /* The multiple "Capture Source" controls confuse alsamixer |
@@ -475,6 +505,37 @@ static snd_kcontrol_new_t alc880_w810_base_mixer[] = { | |||
475 | { } /* end */ | 505 | { } /* end */ |
476 | }; | 506 | }; |
477 | 507 | ||
508 | static snd_kcontrol_new_t alc880_z71v_mixer[] = { | ||
509 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
510 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
511 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
512 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
513 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
514 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
515 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
516 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
517 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | ||
518 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | ||
519 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | ||
520 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | ||
521 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | ||
522 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | ||
523 | { | ||
524 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
525 | /* The multiple "Capture Source" controls confuse alsamixer | ||
526 | * So call somewhat different.. | ||
527 | * FIXME: the controls appear in the "playback" view! | ||
528 | */ | ||
529 | /* .name = "Capture Source", */ | ||
530 | .name = "Input Source", | ||
531 | .count = 3, | ||
532 | .info = alc_mux_enum_info, | ||
533 | .get = alc_mux_enum_get, | ||
534 | .put = alc_mux_enum_put, | ||
535 | }, | ||
536 | { } /* end */ | ||
537 | }; | ||
538 | |||
478 | /* | 539 | /* |
479 | */ | 540 | */ |
480 | static int alc_build_controls(struct hda_codec *codec) | 541 | static int alc_build_controls(struct hda_codec *codec) |
@@ -517,8 +578,16 @@ static struct hda_verb alc880_init_verbs_three_stack[] = { | |||
517 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 578 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, |
518 | /* unmute amp left and right */ | 579 | /* unmute amp left and right */ |
519 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 580 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, |
520 | /* set connection select to line in (default select for this ADC) */ | 581 | /* set connection select to mic in */ |
521 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x02}, | 582 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
583 | /* unmute amp left and right */ | ||
584 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
585 | /* set connection select to mic in */ | ||
586 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
587 | /* unmute amp left and right */ | ||
588 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
589 | /* set connection select to mic in */ | ||
590 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
522 | /* unmute front mixer amp left (volume = 0) */ | 591 | /* unmute front mixer amp left (volume = 0) */ |
523 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 592 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
524 | /* mute pin widget amp left and right (no gain on this amp) */ | 593 | /* mute pin widget amp left and right (no gain on this amp) */ |
@@ -592,8 +661,16 @@ static struct hda_verb alc880_init_verbs_five_stack[] = { | |||
592 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 661 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, |
593 | /* unmute amp left and right */ | 662 | /* unmute amp left and right */ |
594 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 663 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, |
595 | /* set connection select to line in (default select for this ADC) */ | 664 | /* set connection select to mic in */ |
596 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x02}, | 665 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
666 | /* unmute amp left and right */ | ||
667 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
668 | /* set connection select to mic in */ | ||
669 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
670 | /* unmute amp left and right */ | ||
671 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
672 | /* set connection select to mic in */ | ||
673 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
597 | /* unmute front mixer amp left and right (volume = 0) */ | 674 | /* unmute front mixer amp left and right (volume = 0) */ |
598 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 675 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, |
599 | /* mute pin widget amp left and right (no gain on this amp) */ | 676 | /* mute pin widget amp left and right (no gain on this amp) */ |
@@ -719,6 +796,65 @@ static struct hda_verb alc880_w810_init_verbs[] = { | |||
719 | { } | 796 | { } |
720 | }; | 797 | }; |
721 | 798 | ||
799 | static struct hda_verb alc880_z71v_init_verbs[] = { | ||
800 | /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ | ||
801 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
802 | /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */ | ||
803 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, | ||
804 | /* front channel selector/amp: output 0: unmuted, max volume */ | ||
805 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
806 | /* front out pin: muted, (no volume selection) */ | ||
807 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
808 | /* front out pin: NOT headphone enable, out enable, vref disabled */ | ||
809 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
810 | /* headphone channel selector/amp: input 0: DAC: unmuted, (no volume selection) */ | ||
811 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
812 | /* headphone channel selector/amp: input 1: capture mix: muted, (no volume selection) */ | ||
813 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180}, | ||
814 | /* headphone channel selector/amp: output 0: unmuted, max volume */ | ||
815 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
816 | /* headphone out pin: muted, (no volume selection) */ | ||
817 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
818 | /* headpohne out pin: headphone enable, out enable, vref disabled */ | ||
819 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, | ||
820 | |||
821 | /* Line In pin widget for input */ | ||
822 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
823 | /* CD pin widget for input */ | ||
824 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
825 | /* Mic1 (rear panel) pin widget for input and vref at 80% */ | ||
826 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
827 | /* Mic2 (front panel) pin widget for input and vref at 80% */ | ||
828 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
829 | /* unmute amp left and right */ | ||
830 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
831 | /* set connection select to mic in */ | ||
832 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
833 | /* unmute amp left and right */ | ||
834 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
835 | /* set connection select to mic in */ | ||
836 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
837 | /* unmute amp left and right */ | ||
838 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
839 | /* set connection select to mic in */ | ||
840 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
841 | /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer | ||
842 | * widget(nid=0x0B) to support the input path of analog loopback | ||
843 | */ | ||
844 | /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */ | ||
845 | /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/ | ||
846 | /* unmute CD */ | ||
847 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, | ||
848 | /* unmute Line In */ | ||
849 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | ||
850 | /* unmute Mic 1 */ | ||
851 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
852 | /* unmute Line In 2 (for PASD boards Mic 2) */ | ||
853 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, | ||
854 | |||
855 | { } | ||
856 | }; | ||
857 | |||
722 | static int alc_init(struct hda_codec *codec) | 858 | static int alc_init(struct hda_codec *codec) |
723 | { | 859 | { |
724 | struct alc_spec *spec = codec->spec; | 860 | struct alc_spec *spec = codec->spec; |
@@ -842,7 +978,9 @@ static struct hda_pcm_stream alc880_pcm_analog_capture = { | |||
842 | .substreams = 2, | 978 | .substreams = 2, |
843 | .channels_min = 2, | 979 | .channels_min = 2, |
844 | .channels_max = 2, | 980 | .channels_max = 2, |
845 | .nid = 0x07, /* NID to query formats and rates */ | 981 | .nid = 0x08, /* NID to query formats and rates |
982 | * (0x07 might be broken on some devices) | ||
983 | */ | ||
846 | .ops = { | 984 | .ops = { |
847 | .prepare = alc880_capture_pcm_prepare, | 985 | .prepare = alc880_capture_pcm_prepare, |
848 | .cleanup = alc880_capture_pcm_cleanup | 986 | .cleanup = alc880_capture_pcm_cleanup |
@@ -921,77 +1059,336 @@ static struct hda_codec_ops alc_patch_ops = { | |||
921 | #endif | 1059 | #endif |
922 | }; | 1060 | }; |
923 | 1061 | ||
1062 | |||
1063 | /* | ||
1064 | * Test configuration for debugging | ||
1065 | * | ||
1066 | * Almost all inputs/outputs are enabled. I/O pins can be configured via | ||
1067 | * enum controls. | ||
1068 | */ | ||
1069 | #ifdef CONFIG_SND_DEBUG | ||
1070 | static hda_nid_t alc880_test_dac_nids[4] = { | ||
1071 | 0x02, 0x03, 0x04, 0x05 | ||
1072 | }; | ||
1073 | |||
1074 | static struct hda_input_mux alc880_test_capture_source = { | ||
1075 | .num_items = 5, | ||
1076 | .items = { | ||
1077 | { "In-1", 0x0 }, | ||
1078 | { "In-2", 0x1 }, | ||
1079 | { "In-3", 0x2 }, | ||
1080 | { "In-4", 0x3 }, | ||
1081 | { "CD", 0x4 }, | ||
1082 | }, | ||
1083 | }; | ||
1084 | |||
1085 | static struct alc_channel_mode alc880_test_modes[4] = { | ||
1086 | { 2, NULL }, | ||
1087 | { 4, NULL }, | ||
1088 | { 6, NULL }, | ||
1089 | { 8, NULL }, | ||
1090 | }; | ||
1091 | |||
1092 | static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
1093 | { | ||
1094 | static char *texts[] = { | ||
1095 | "N/A", "Line Out", "HP Out", | ||
1096 | "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" | ||
1097 | }; | ||
1098 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1099 | uinfo->count = 1; | ||
1100 | uinfo->value.enumerated.items = 8; | ||
1101 | if (uinfo->value.enumerated.item >= 8) | ||
1102 | uinfo->value.enumerated.item = 7; | ||
1103 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1104 | return 0; | ||
1105 | } | ||
1106 | |||
1107 | static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1108 | { | ||
1109 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1110 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1111 | unsigned int pin_ctl, item = 0; | ||
1112 | |||
1113 | pin_ctl = snd_hda_codec_read(codec, nid, 0, | ||
1114 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1115 | if (pin_ctl & AC_PINCTL_OUT_EN) { | ||
1116 | if (pin_ctl & AC_PINCTL_HP_EN) | ||
1117 | item = 2; | ||
1118 | else | ||
1119 | item = 1; | ||
1120 | } else if (pin_ctl & AC_PINCTL_IN_EN) { | ||
1121 | switch (pin_ctl & AC_PINCTL_VREFEN) { | ||
1122 | case AC_PINCTL_VREF_HIZ: item = 3; break; | ||
1123 | case AC_PINCTL_VREF_50: item = 4; break; | ||
1124 | case AC_PINCTL_VREF_GRD: item = 5; break; | ||
1125 | case AC_PINCTL_VREF_80: item = 6; break; | ||
1126 | case AC_PINCTL_VREF_100: item = 7; break; | ||
1127 | } | ||
1128 | } | ||
1129 | ucontrol->value.enumerated.item[0] = item; | ||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1134 | { | ||
1135 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1136 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1137 | static unsigned int ctls[] = { | ||
1138 | 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, | ||
1139 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, | ||
1140 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, | ||
1141 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, | ||
1142 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, | ||
1143 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, | ||
1144 | }; | ||
1145 | unsigned int old_ctl, new_ctl; | ||
1146 | |||
1147 | old_ctl = snd_hda_codec_read(codec, nid, 0, | ||
1148 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
1149 | new_ctl = ctls[ucontrol->value.enumerated.item[0]]; | ||
1150 | if (old_ctl != new_ctl) { | ||
1151 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); | ||
1152 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
1153 | ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000); | ||
1154 | return 1; | ||
1155 | } | ||
1156 | return 0; | ||
1157 | } | ||
1158 | |||
1159 | static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
1160 | { | ||
1161 | static char *texts[] = { | ||
1162 | "Front", "Surround", "CLFE", "Side" | ||
1163 | }; | ||
1164 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1165 | uinfo->count = 1; | ||
1166 | uinfo->value.enumerated.items = 4; | ||
1167 | if (uinfo->value.enumerated.item >= 4) | ||
1168 | uinfo->value.enumerated.item = 3; | ||
1169 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
1170 | return 0; | ||
1171 | } | ||
1172 | |||
1173 | static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1174 | { | ||
1175 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1176 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1177 | unsigned int sel; | ||
1178 | |||
1179 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); | ||
1180 | ucontrol->value.enumerated.item[0] = sel & 3; | ||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1185 | { | ||
1186 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1187 | hda_nid_t nid = (hda_nid_t)kcontrol->private_value; | ||
1188 | unsigned int sel; | ||
1189 | |||
1190 | sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; | ||
1191 | if (ucontrol->value.enumerated.item[0] != sel) { | ||
1192 | sel = ucontrol->value.enumerated.item[0] & 3; | ||
1193 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); | ||
1194 | return 1; | ||
1195 | } | ||
1196 | return 0; | ||
1197 | } | ||
1198 | |||
1199 | #define PIN_CTL_TEST(xname,nid) { \ | ||
1200 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1201 | .name = xname, \ | ||
1202 | .info = alc_test_pin_ctl_info, \ | ||
1203 | .get = alc_test_pin_ctl_get, \ | ||
1204 | .put = alc_test_pin_ctl_put, \ | ||
1205 | .private_value = nid \ | ||
1206 | } | ||
1207 | |||
1208 | #define PIN_SRC_TEST(xname,nid) { \ | ||
1209 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1210 | .name = xname, \ | ||
1211 | .info = alc_test_pin_src_info, \ | ||
1212 | .get = alc_test_pin_src_get, \ | ||
1213 | .put = alc_test_pin_src_put, \ | ||
1214 | .private_value = nid \ | ||
1215 | } | ||
1216 | |||
1217 | static snd_kcontrol_new_t alc880_test_mixer[] = { | ||
1218 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
1219 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | ||
1220 | HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), | ||
1221 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
1222 | PIN_CTL_TEST("Front Pin Mode", 0x14), | ||
1223 | PIN_CTL_TEST("Surround Pin Mode", 0x15), | ||
1224 | PIN_CTL_TEST("CLFE Pin Mode", 0x16), | ||
1225 | PIN_CTL_TEST("Side Pin Mode", 0x17), | ||
1226 | PIN_CTL_TEST("In-1 Pin Mode", 0x18), | ||
1227 | PIN_CTL_TEST("In-2 Pin Mode", 0x19), | ||
1228 | PIN_CTL_TEST("In-3 Pin Mode", 0x1a), | ||
1229 | PIN_CTL_TEST("In-4 Pin Mode", 0x1b), | ||
1230 | PIN_SRC_TEST("In-1 Pin Source", 0x18), | ||
1231 | PIN_SRC_TEST("In-2 Pin Source", 0x19), | ||
1232 | PIN_SRC_TEST("In-3 Pin Source", 0x1a), | ||
1233 | PIN_SRC_TEST("In-4 Pin Source", 0x1b), | ||
1234 | HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
1235 | HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
1236 | HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
1237 | HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
1238 | HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), | ||
1239 | HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), | ||
1240 | HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), | ||
1241 | HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), | ||
1242 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), | ||
1243 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), | ||
1244 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | ||
1245 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | ||
1246 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | ||
1247 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | ||
1248 | { | ||
1249 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1250 | .name = "Input Source", | ||
1251 | .count = 2, | ||
1252 | .info = alc_mux_enum_info, | ||
1253 | .get = alc_mux_enum_get, | ||
1254 | .put = alc_mux_enum_put, | ||
1255 | }, | ||
1256 | { | ||
1257 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1258 | .name = "Channel Mode", | ||
1259 | .info = alc880_ch_mode_info, | ||
1260 | .get = alc880_ch_mode_get, | ||
1261 | .put = alc880_ch_mode_put, | ||
1262 | .private_value = ARRAY_SIZE(alc880_test_modes), | ||
1263 | }, | ||
1264 | { } /* end */ | ||
1265 | }; | ||
1266 | |||
1267 | static struct hda_verb alc880_test_init_verbs[] = { | ||
1268 | /* Unmute inputs of 0x0c - 0x0f */ | ||
1269 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
1270 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7100}, | ||
1271 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
1272 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7100}, | ||
1273 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
1274 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7100}, | ||
1275 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
1276 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0x7100}, | ||
1277 | /* Vol output for 0x0c-0x0f */ | ||
1278 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
1279 | {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
1280 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
1281 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | ||
1282 | /* Set output pins 0x14-0x17 */ | ||
1283 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
1284 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
1285 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
1286 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
1287 | /* Unmute output pins 0x14-0x17 */ | ||
1288 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
1289 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
1290 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
1291 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
1292 | /* Set input pins 0x18-0x1c */ | ||
1293 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, /* vref 80% */ | ||
1294 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
1295 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
1296 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
1297 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
1298 | /* Mute input pins 0x18-0x1b */ | ||
1299 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
1300 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
1301 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
1302 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | ||
1303 | /* ADC set up */ | ||
1304 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
1305 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1306 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
1307 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1308 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | ||
1309 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1310 | { } | ||
1311 | }; | ||
1312 | #endif | ||
1313 | |||
924 | /* | 1314 | /* |
925 | */ | 1315 | */ |
926 | 1316 | ||
927 | static struct hda_board_config alc880_cfg_tbl[] = { | 1317 | static struct hda_board_config alc880_cfg_tbl[] = { |
928 | /* Back 3 jack, front 2 jack */ | 1318 | /* Back 3 jack, front 2 jack */ |
929 | { .modelname = "3stack", .config = ALC880_3ST }, | 1319 | { .modelname = "3stack", .config = ALC880_3ST }, |
930 | { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST }, | 1320 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST }, |
931 | { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST }, | 1321 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST }, |
932 | { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST }, | 1322 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST }, |
933 | { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST }, | 1323 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST }, |
934 | { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST }, | 1324 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST }, |
935 | { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST }, | 1325 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST }, |
936 | { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST }, | 1326 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST }, |
937 | { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST }, | 1327 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST }, |
938 | { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST }, | 1328 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST }, |
939 | { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST }, | 1329 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST }, |
940 | { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST }, | 1330 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST }, |
941 | { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST }, | 1331 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST }, |
942 | { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST }, | 1332 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST }, |
943 | { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST }, | 1333 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST }, |
944 | { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST }, | 1334 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST }, |
945 | { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST }, | 1335 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, |
946 | { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST }, | 1336 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, |
947 | { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST }, | 1337 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, |
948 | { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST }, | 1338 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST }, |
949 | { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST }, | 1339 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST }, |
950 | { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST }, | 1340 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST }, |
951 | { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST }, | 1341 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST }, |
952 | { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST }, | 1342 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST }, |
953 | { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST }, | 1343 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST }, |
954 | { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST }, | 1344 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST }, |
955 | { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST }, | 1345 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST }, |
956 | { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST }, | 1346 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST }, |
957 | { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST }, | 1347 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST }, |
958 | { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST }, | 1348 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST }, |
959 | { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST }, | 1349 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST }, |
960 | { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST }, | 1350 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, |
961 | { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST }, | 1351 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, |
962 | 1352 | ||
963 | /* Back 3 jack, front 2 jack (Internal add Aux-In) */ | 1353 | /* Back 3 jack, front 2 jack (Internal add Aux-In) */ |
964 | { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST }, | 1354 | { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST }, |
965 | 1355 | ||
966 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ | 1356 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */ |
967 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, | 1357 | { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, |
968 | { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG }, | 1358 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, |
969 | 1359 | ||
970 | /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ | 1360 | /* 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 }, | 1361 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, |
972 | { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG }, | 1362 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG }, |
973 | { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG }, | 1363 | { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG }, |
974 | 1364 | ||
975 | /* Back 5 jack, front 2 jack */ | 1365 | /* Back 5 jack, front 2 jack */ |
976 | { .modelname = "5stack", .config = ALC880_5ST }, | 1366 | { .modelname = "5stack", .config = ALC880_5ST }, |
977 | { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST }, | 1367 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST }, |
978 | { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST }, | 1368 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST }, |
979 | { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST }, | 1369 | { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST }, |
980 | { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST }, | 1370 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST }, |
981 | 1371 | ||
982 | /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */ | 1372 | /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */ |
983 | { .modelname = "5stack-digout", .config = ALC880_5ST_DIG }, | 1373 | { .modelname = "5stack-digout", .config = ALC880_5ST_DIG }, |
984 | { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG }, | 1374 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG }, |
985 | { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG }, | 1375 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG }, |
986 | { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG }, | 1376 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG }, |
987 | { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG }, | 1377 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG }, |
988 | { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG }, | 1378 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG }, |
989 | { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG }, | 1379 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG }, |
990 | { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG }, | 1380 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG }, |
991 | { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG }, | 1381 | { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG }, |
992 | 1382 | ||
993 | { .modelname = "w810", .config = ALC880_W810 }, | 1383 | { .modelname = "w810", .config = ALC880_W810 }, |
994 | { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 }, | 1384 | { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 }, |
1385 | |||
1386 | { .modelname = "z71v", .config = ALC880_Z71V }, | ||
1387 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V }, | ||
1388 | |||
1389 | #ifdef CONFIG_SND_DEBUG | ||
1390 | { .modelname = "test", .config = ALC880_TEST }, | ||
1391 | #endif | ||
995 | 1392 | ||
996 | {} | 1393 | {} |
997 | }; | 1394 | }; |
@@ -1023,6 +1420,16 @@ static int patch_alc880(struct hda_codec *codec) | |||
1023 | spec->mixers[spec->num_mixers] = alc880_five_stack_mixer; | 1420 | spec->mixers[spec->num_mixers] = alc880_five_stack_mixer; |
1024 | spec->num_mixers++; | 1421 | spec->num_mixers++; |
1025 | break; | 1422 | break; |
1423 | case ALC880_Z71V: | ||
1424 | spec->mixers[spec->num_mixers] = alc880_z71v_mixer; | ||
1425 | spec->num_mixers++; | ||
1426 | break; | ||
1427 | #ifdef CONFIG_SND_DEBUG | ||
1428 | case ALC880_TEST: | ||
1429 | spec->mixers[spec->num_mixers] = alc880_test_mixer; | ||
1430 | spec->num_mixers++; | ||
1431 | break; | ||
1432 | #endif | ||
1026 | default: | 1433 | default: |
1027 | spec->mixers[spec->num_mixers] = alc880_base_mixer; | 1434 | spec->mixers[spec->num_mixers] = alc880_base_mixer; |
1028 | spec->num_mixers++; | 1435 | spec->num_mixers++; |
@@ -1033,6 +1440,8 @@ static int patch_alc880(struct hda_codec *codec) | |||
1033 | case ALC880_3ST_DIG: | 1440 | case ALC880_3ST_DIG: |
1034 | case ALC880_5ST_DIG: | 1441 | case ALC880_5ST_DIG: |
1035 | case ALC880_W810: | 1442 | case ALC880_W810: |
1443 | case ALC880_Z71V: | ||
1444 | case ALC880_TEST: | ||
1036 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | 1445 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; |
1037 | break; | 1446 | break; |
1038 | default: | 1447 | default: |
@@ -1063,6 +1472,18 @@ static int patch_alc880(struct hda_codec *codec) | |||
1063 | spec->channel_mode = alc880_w810_modes; | 1472 | spec->channel_mode = alc880_w810_modes; |
1064 | spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes); | 1473 | spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes); |
1065 | break; | 1474 | break; |
1475 | case ALC880_Z71V: | ||
1476 | spec->init_verbs = alc880_z71v_init_verbs; | ||
1477 | spec->channel_mode = alc880_z71v_modes; | ||
1478 | spec->num_channel_mode = ARRAY_SIZE(alc880_z71v_modes); | ||
1479 | break; | ||
1480 | #ifdef CONFIG_SND_DEBUG | ||
1481 | case ALC880_TEST: | ||
1482 | spec->init_verbs = alc880_test_init_verbs; | ||
1483 | spec->channel_mode = alc880_test_modes; | ||
1484 | spec->num_channel_mode = ARRAY_SIZE(alc880_test_modes); | ||
1485 | break; | ||
1486 | #endif | ||
1066 | default: | 1487 | default: |
1067 | spec->init_verbs = alc880_init_verbs_three_stack; | 1488 | spec->init_verbs = alc880_init_verbs_three_stack; |
1068 | spec->channel_mode = alc880_threestack_modes; | 1489 | spec->channel_mode = alc880_threestack_modes; |
@@ -1086,6 +1507,18 @@ static int patch_alc880(struct hda_codec *codec) | |||
1086 | spec->multiout.dac_nids = alc880_w810_dac_nids; | 1507 | spec->multiout.dac_nids = alc880_w810_dac_nids; |
1087 | // No dedicated headphone socket - it's shared with built-in speakers. | 1508 | // No dedicated headphone socket - it's shared with built-in speakers. |
1088 | break; | 1509 | break; |
1510 | case ALC880_Z71V: | ||
1511 | spec->multiout.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids); | ||
1512 | spec->multiout.dac_nids = alc880_z71v_dac_nids; | ||
1513 | spec->multiout.hp_nid = 0x03; | ||
1514 | break; | ||
1515 | #ifdef CONFIG_SND_DEBUG | ||
1516 | case ALC880_TEST: | ||
1517 | spec->multiout.num_dacs = ARRAY_SIZE(alc880_test_dac_nids); | ||
1518 | spec->multiout.dac_nids = alc880_test_dac_nids; | ||
1519 | spec->input_mux = &alc880_test_capture_source; | ||
1520 | break; | ||
1521 | #endif | ||
1089 | default: | 1522 | default: |
1090 | spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids); | 1523 | spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids); |
1091 | spec->multiout.dac_nids = alc880_dac_nids; | 1524 | spec->multiout.dac_nids = alc880_dac_nids; |
@@ -1093,7 +1526,8 @@ static int patch_alc880(struct hda_codec *codec) | |||
1093 | break; | 1526 | break; |
1094 | } | 1527 | } |
1095 | 1528 | ||
1096 | spec->input_mux = &alc880_capture_source; | 1529 | if (! spec->input_mux) |
1530 | spec->input_mux = &alc880_capture_source; | ||
1097 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); | 1531 | spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids); |
1098 | spec->adc_nids = alc880_adc_nids; | 1532 | spec->adc_nids = alc880_adc_nids; |
1099 | 1533 | ||
@@ -1434,11 +1868,13 @@ static struct hda_verb alc882_init_verbs[] = { | |||
1434 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, | 1868 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))}, |
1435 | /* ADC1: unmute amp left and right */ | 1869 | /* ADC1: unmute amp left and right */ |
1436 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 1870 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, |
1871 | {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1437 | /* ADC2: unmute amp left and right */ | 1872 | /* ADC2: unmute amp left and right */ |
1438 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 1873 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, |
1874 | {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1439 | /* ADC3: unmute amp left and right */ | 1875 | /* ADC3: unmute amp left and right */ |
1440 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, | 1876 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000}, |
1441 | 1877 | {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, | |
1442 | /* Unmute front loopback */ | 1878 | /* Unmute front loopback */ |
1443 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 1879 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, |
1444 | /* Unmute rear loopback */ | 1880 | /* Unmute rear loopback */ |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c new file mode 100644 index 000000000000..1534e20af63d --- /dev/null +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -0,0 +1,560 @@ | |||
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 "hda_codec.h" | ||
34 | #include "hda_local.h" | ||
35 | |||
36 | #undef STAC_TEST | ||
37 | |||
38 | struct sigmatel_spec { | ||
39 | /* playback */ | ||
40 | struct hda_multi_out multiout; | ||
41 | hda_nid_t playback_nid; | ||
42 | |||
43 | /* capture */ | ||
44 | hda_nid_t *adc_nids; | ||
45 | hda_nid_t *mux_nids; | ||
46 | unsigned int num_adcs; | ||
47 | hda_nid_t capture_nid; | ||
48 | |||
49 | /* power management*/ | ||
50 | hda_nid_t *pstate_nids; | ||
51 | unsigned int num_pstates; | ||
52 | |||
53 | /* pin widgets */ | ||
54 | hda_nid_t *pin_nids; | ||
55 | unsigned int num_pins; | ||
56 | #ifdef STAC_TEST | ||
57 | unsigned int *pin_configs; | ||
58 | #endif | ||
59 | |||
60 | /* codec specific stuff */ | ||
61 | struct hda_verb *init; | ||
62 | snd_kcontrol_new_t *mixer; | ||
63 | |||
64 | /* capture source */ | ||
65 | const struct hda_input_mux *input_mux; | ||
66 | unsigned int cur_mux[2]; | ||
67 | |||
68 | /* channel mode */ | ||
69 | unsigned int num_ch_modes; | ||
70 | unsigned int cur_ch_mode; | ||
71 | const struct sigmatel_channel_mode *channel_modes; | ||
72 | |||
73 | struct hda_pcm pcm_rec[1]; /* PCM information */ | ||
74 | }; | ||
75 | |||
76 | static hda_nid_t stac9200_adc_nids[1] = { | ||
77 | 0x03, | ||
78 | }; | ||
79 | |||
80 | static hda_nid_t stac9200_mux_nids[1] = { | ||
81 | 0x0c, | ||
82 | }; | ||
83 | |||
84 | static hda_nid_t stac9200_dac_nids[1] = { | ||
85 | 0x02, | ||
86 | }; | ||
87 | |||
88 | static hda_nid_t stac9200_pstate_nids[3] = { | ||
89 | 0x01, 0x02, 0x03, | ||
90 | }; | ||
91 | |||
92 | static hda_nid_t stac9200_pin_nids[8] = { | ||
93 | 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, | ||
94 | }; | ||
95 | |||
96 | static hda_nid_t stac922x_adc_nids[2] = { | ||
97 | 0x06, 0x07, | ||
98 | }; | ||
99 | |||
100 | static hda_nid_t stac922x_mux_nids[2] = { | ||
101 | 0x12, 0x13, | ||
102 | }; | ||
103 | |||
104 | static hda_nid_t stac922x_dac_nids[4] = { | ||
105 | 0x02, 0x03, 0x04, 0x05, | ||
106 | }; | ||
107 | |||
108 | static hda_nid_t stac922x_pstate_nids[7] = { | ||
109 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | ||
110 | }; | ||
111 | |||
112 | static hda_nid_t stac922x_pin_nids[10] = { | ||
113 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
114 | 0x0f, 0x10, 0x11, 0x15, 0x1b, | ||
115 | }; | ||
116 | |||
117 | static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
118 | { | ||
119 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
120 | struct sigmatel_spec *spec = codec->spec; | ||
121 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | ||
122 | } | ||
123 | |||
124 | static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
125 | { | ||
126 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
127 | struct sigmatel_spec *spec = codec->spec; | ||
128 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
129 | |||
130 | ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx]; | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
135 | { | ||
136 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
137 | struct sigmatel_spec *spec = codec->spec; | ||
138 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
139 | |||
140 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | ||
141 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); | ||
142 | } | ||
143 | |||
144 | static struct hda_verb stac9200_ch2_init[] = { | ||
145 | /* set dac0mux for dac converter */ | ||
146 | { 0x07, 0x701, 0x00}, | ||
147 | {} | ||
148 | }; | ||
149 | |||
150 | static struct hda_verb stac922x_ch2_init[] = { | ||
151 | /* set master volume and direct control */ | ||
152 | { 0x16, 0x70f, 0xff}, | ||
153 | {} | ||
154 | }; | ||
155 | |||
156 | struct sigmatel_channel_mode { | ||
157 | unsigned int channels; | ||
158 | const struct hda_verb *sequence; | ||
159 | }; | ||
160 | |||
161 | static snd_kcontrol_new_t stac9200_mixer[] = { | ||
162 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | ||
163 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | ||
164 | { | ||
165 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
166 | .name = "Input Source", | ||
167 | .count = 1, | ||
168 | .info = stac92xx_mux_enum_info, | ||
169 | .get = stac92xx_mux_enum_get, | ||
170 | .put = stac92xx_mux_enum_put, | ||
171 | }, | ||
172 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | ||
173 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | ||
174 | HDA_CODEC_VOLUME("Input Mux Volume", 0x0c, 0, HDA_OUTPUT), | ||
175 | { } /* end */ | ||
176 | }; | ||
177 | |||
178 | static snd_kcontrol_new_t stac922x_mixer[] = { | ||
179 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x2, 0x0, HDA_OUTPUT), | ||
180 | HDA_CODEC_MUTE("PCM Playback Switch", 0x2, 0x0, HDA_OUTPUT), | ||
181 | { | ||
182 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
183 | .name = "Input Source", | ||
184 | .count = 1, | ||
185 | .info = stac92xx_mux_enum_info, | ||
186 | .get = stac92xx_mux_enum_get, | ||
187 | .put = stac92xx_mux_enum_put, | ||
188 | }, | ||
189 | HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT), | ||
190 | HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT), | ||
191 | HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT), | ||
192 | { } /* end */ | ||
193 | }; | ||
194 | |||
195 | static struct hda_input_mux stac9200_input_mux = { | ||
196 | .num_items = 5, | ||
197 | .items = { | ||
198 | { "Port B", 0x0 }, | ||
199 | { "Port C", 0x1 }, | ||
200 | { "Port D", 0x2 }, | ||
201 | { "Port A", 0x3 }, | ||
202 | { "CD", 0x4 }, | ||
203 | } | ||
204 | }; | ||
205 | |||
206 | static struct hda_input_mux stac922x_input_mux = { | ||
207 | .num_items = 7, | ||
208 | .items = { | ||
209 | { "Port E", 0x0 }, | ||
210 | { "CD", 0x1 }, | ||
211 | { "Port F", 0x2 }, | ||
212 | { "Port B", 0x3 }, | ||
213 | { "Port C", 0x4 }, | ||
214 | { "Port D", 0x5 }, | ||
215 | { "Port A", 0x6 }, | ||
216 | } | ||
217 | }; | ||
218 | |||
219 | static int stac92xx_build_controls(struct hda_codec *codec) | ||
220 | { | ||
221 | struct sigmatel_spec *spec = codec->spec; | ||
222 | int err; | ||
223 | |||
224 | err = snd_hda_add_new_ctls(codec, spec->mixer); | ||
225 | if (err < 0) | ||
226 | return err; | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | #ifdef STAC_TEST | ||
232 | static unsigned int stac9200_pin_configs[8] = { | ||
233 | 0x40000100, 0x40000100, 0x0221401f, 0x01114010, | ||
234 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, | ||
235 | }; | ||
236 | |||
237 | static unsigned int stac922x_pin_configs[14] = { | ||
238 | 0x40000100, 0x40000100, 0x40000100, 0x01114010, | ||
239 | 0x01813122, 0x40000100, 0x40000100, 0x40000100, | ||
240 | 0x40000100, 0x40000100, | ||
241 | }; | ||
242 | |||
243 | static void stac92xx_set_config_regs(struct hda_codec *codec) | ||
244 | { | ||
245 | int i; | ||
246 | struct sigmatel_spec *spec = codec->spec; | ||
247 | unsigned int pin_cfg; | ||
248 | |||
249 | for (i=0; i < spec->num_pins; i++) { | ||
250 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | ||
251 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | ||
252 | spec->pin_configs[i] & 0x000000ff); | ||
253 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | ||
254 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, | ||
255 | (spec->pin_configs[i] & 0x0000ff00) >> 8); | ||
256 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | ||
257 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, | ||
258 | (spec->pin_configs[i] & 0x00ff0000) >> 16); | ||
259 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | ||
260 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | ||
261 | spec->pin_configs[i] >> 24); | ||
262 | pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0, | ||
263 | AC_VERB_GET_CONFIG_DEFAULT, | ||
264 | 0x00); | ||
265 | printk("pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg); | ||
266 | } | ||
267 | } | ||
268 | #endif | ||
269 | |||
270 | static int stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int value) | ||
271 | { | ||
272 | unsigned int pin_ctl; | ||
273 | |||
274 | pin_ctl = snd_hda_codec_read(codec, nid, 0, | ||
275 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
276 | 0x00); | ||
277 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
278 | pin_ctl | value); | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int stac92xx_set_vref(struct hda_codec *codec, hda_nid_t nid) | ||
284 | { | ||
285 | unsigned int vref_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) >> AC_PINCAP_VREF_SHIFT; | ||
286 | unsigned int vref_ctl = AC_PINCTL_VREF_HIZ; | ||
287 | |||
288 | if (vref_caps & AC_PINCAP_VREF_100) | ||
289 | vref_ctl = AC_PINCTL_VREF_100; | ||
290 | else if (vref_caps & AC_PINCAP_VREF_80) | ||
291 | vref_ctl = AC_PINCTL_VREF_80; | ||
292 | else if (vref_caps & AC_PINCAP_VREF_50) | ||
293 | vref_ctl = AC_PINCTL_VREF_50; | ||
294 | else if (vref_caps & AC_PINCAP_VREF_GRD) | ||
295 | vref_ctl = AC_PINCTL_VREF_GRD; | ||
296 | |||
297 | stac92xx_set_pinctl(codec, nid, vref_ctl); | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg) | ||
303 | { | ||
304 | switch((pin_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) { | ||
305 | case AC_JACK_HP_OUT: | ||
306 | /* Enable HP amp */ | ||
307 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_HP_EN); | ||
308 | /* Fall through */ | ||
309 | case AC_JACK_LINE_OUT: | ||
310 | case AC_JACK_SPEAKER: | ||
311 | /* Enable output */ | ||
312 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | ||
313 | break; | ||
314 | case AC_JACK_MIC_IN: | ||
315 | /* Set vref */ | ||
316 | stac92xx_set_vref(codec, nid); | ||
317 | case AC_JACK_CD: | ||
318 | case AC_JACK_LINE_IN: | ||
319 | case AC_JACK_AUX: | ||
320 | /* Enable input */ | ||
321 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); | ||
322 | break; | ||
323 | } | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int stac92xx_config_pins(struct hda_codec *codec) | ||
329 | { | ||
330 | struct sigmatel_spec *spec = codec->spec; | ||
331 | int i; | ||
332 | unsigned int pin_cfg; | ||
333 | |||
334 | for (i=0; i < spec->num_pins; i++) { | ||
335 | /* Default to disabled */ | ||
336 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | ||
337 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
338 | 0x00); | ||
339 | |||
340 | pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0, | ||
341 | AC_VERB_GET_CONFIG_DEFAULT, | ||
342 | 0x00); | ||
343 | if (((pin_cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) == AC_JACK_PORT_NONE) | ||
344 | continue; /* Move on */ | ||
345 | |||
346 | stac92xx_config_pin(codec, spec->pin_nids[i], pin_cfg); | ||
347 | } | ||
348 | |||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static int stac92xx_init(struct hda_codec *codec) | ||
353 | { | ||
354 | struct sigmatel_spec *spec = codec->spec; | ||
355 | int i; | ||
356 | |||
357 | for (i=0; i < spec->num_pstates; i++) | ||
358 | snd_hda_codec_write(codec, spec->pstate_nids[i], 0, | ||
359 | AC_VERB_SET_POWER_STATE, 0x00); | ||
360 | |||
361 | mdelay(100); | ||
362 | |||
363 | snd_hda_sequence_write(codec, spec->init); | ||
364 | |||
365 | #ifdef STAC_TEST | ||
366 | stac92xx_set_config_regs(codec); | ||
367 | #endif | ||
368 | |||
369 | stac92xx_config_pins(codec); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | /* | ||
375 | * Analog playback callbacks | ||
376 | */ | ||
377 | static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
378 | struct hda_codec *codec, | ||
379 | snd_pcm_substream_t *substream) | ||
380 | { | ||
381 | struct sigmatel_spec *spec = codec->spec; | ||
382 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); | ||
383 | } | ||
384 | |||
385 | static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
386 | struct hda_codec *codec, | ||
387 | unsigned int stream_tag, | ||
388 | unsigned int format, | ||
389 | snd_pcm_substream_t *substream) | ||
390 | { | ||
391 | struct sigmatel_spec *spec = codec->spec; | ||
392 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | ||
393 | format, substream); | ||
394 | } | ||
395 | |||
396 | static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
397 | struct hda_codec *codec, | ||
398 | snd_pcm_substream_t *substream) | ||
399 | { | ||
400 | struct sigmatel_spec *spec = codec->spec; | ||
401 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * Analog capture callbacks | ||
406 | */ | ||
407 | static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
408 | struct hda_codec *codec, | ||
409 | unsigned int stream_tag, | ||
410 | unsigned int format, | ||
411 | snd_pcm_substream_t *substream) | ||
412 | { | ||
413 | struct sigmatel_spec *spec = codec->spec; | ||
414 | |||
415 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], | ||
416 | stream_tag, 0, format); | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
421 | struct hda_codec *codec, | ||
422 | snd_pcm_substream_t *substream) | ||
423 | { | ||
424 | struct sigmatel_spec *spec = codec->spec; | ||
425 | |||
426 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0); | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static struct hda_pcm_stream stac92xx_pcm_analog_playback = { | ||
431 | .substreams = 1, | ||
432 | .channels_min = 2, | ||
433 | .channels_max = 2, | ||
434 | .nid = 0x02, /* NID to query formats and rates */ | ||
435 | .ops = { | ||
436 | .open = stac92xx_playback_pcm_open, | ||
437 | .prepare = stac92xx_playback_pcm_prepare, | ||
438 | .cleanup = stac92xx_playback_pcm_cleanup | ||
439 | }, | ||
440 | }; | ||
441 | |||
442 | static struct hda_pcm_stream stac92xx_pcm_analog_capture = { | ||
443 | .substreams = 2, | ||
444 | .channels_min = 2, | ||
445 | .channels_max = 2, | ||
446 | .nid = 0x06, /* NID to query formats and rates */ | ||
447 | .ops = { | ||
448 | .prepare = stac92xx_capture_pcm_prepare, | ||
449 | .cleanup = stac92xx_capture_pcm_cleanup | ||
450 | }, | ||
451 | }; | ||
452 | |||
453 | static int stac92xx_build_pcms(struct hda_codec *codec) | ||
454 | { | ||
455 | struct sigmatel_spec *spec = codec->spec; | ||
456 | struct hda_pcm *info = spec->pcm_rec; | ||
457 | |||
458 | codec->num_pcms = 1; | ||
459 | codec->pcm_info = info; | ||
460 | |||
461 | info->name = "STAC92xx"; | ||
462 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; | ||
463 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->playback_nid; | ||
464 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; | ||
465 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid; | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | static void stac92xx_free(struct hda_codec *codec) | ||
471 | { | ||
472 | kfree(codec->spec); | ||
473 | } | ||
474 | |||
475 | static struct hda_codec_ops stac92xx_patch_ops = { | ||
476 | .build_controls = stac92xx_build_controls, | ||
477 | .build_pcms = stac92xx_build_pcms, | ||
478 | .init = stac92xx_init, | ||
479 | .free = stac92xx_free, | ||
480 | }; | ||
481 | |||
482 | static int patch_stac9200(struct hda_codec *codec) | ||
483 | { | ||
484 | struct sigmatel_spec *spec; | ||
485 | |||
486 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | ||
487 | if (spec == NULL) | ||
488 | return -ENOMEM; | ||
489 | |||
490 | codec->spec = spec; | ||
491 | |||
492 | spec->multiout.max_channels = 2; | ||
493 | spec->multiout.num_dacs = 1; | ||
494 | spec->multiout.dac_nids = stac9200_dac_nids; | ||
495 | spec->adc_nids = stac9200_adc_nids; | ||
496 | spec->mux_nids = stac9200_mux_nids; | ||
497 | spec->input_mux = &stac9200_input_mux; | ||
498 | spec->pstate_nids = stac9200_pstate_nids; | ||
499 | spec->num_pstates = 3; | ||
500 | spec->pin_nids = stac9200_pin_nids; | ||
501 | #ifdef STAC_TEST | ||
502 | spec->pin_configs = stac9200_pin_configs; | ||
503 | #endif | ||
504 | spec->num_pins = 8; | ||
505 | spec->init = stac9200_ch2_init; | ||
506 | spec->mixer = stac9200_mixer; | ||
507 | spec->playback_nid = 0x02; | ||
508 | spec->capture_nid = 0x03; | ||
509 | |||
510 | codec->patch_ops = stac92xx_patch_ops; | ||
511 | |||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | static int patch_stac922x(struct hda_codec *codec) | ||
516 | { | ||
517 | struct sigmatel_spec *spec; | ||
518 | |||
519 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | ||
520 | if (spec == NULL) | ||
521 | return -ENOMEM; | ||
522 | |||
523 | codec->spec = spec; | ||
524 | |||
525 | spec->multiout.max_channels = 2; | ||
526 | spec->multiout.num_dacs = 4; | ||
527 | spec->multiout.dac_nids = stac922x_dac_nids; | ||
528 | spec->adc_nids = stac922x_adc_nids; | ||
529 | spec->mux_nids = stac922x_mux_nids; | ||
530 | spec->input_mux = &stac922x_input_mux; | ||
531 | spec->pstate_nids = stac922x_pstate_nids; | ||
532 | spec->num_pstates = 7; | ||
533 | spec->pin_nids = stac922x_pin_nids; | ||
534 | #ifdef STAC_TEST | ||
535 | spec->pin_configs = stac922x_pin_configs; | ||
536 | #endif | ||
537 | spec->num_pins = 10; | ||
538 | spec->init = stac922x_ch2_init; | ||
539 | spec->mixer = stac922x_mixer; | ||
540 | spec->playback_nid = 0x02; | ||
541 | spec->capture_nid = 0x06; | ||
542 | |||
543 | codec->patch_ops = stac92xx_patch_ops; | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | /* | ||
549 | * patch entries | ||
550 | */ | ||
551 | struct hda_codec_preset snd_hda_preset_sigmatel[] = { | ||
552 | { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 }, | ||
553 | { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x }, | ||
554 | { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x }, | ||
555 | { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x }, | ||
556 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, | ||
557 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, | ||
558 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, | ||
559 | {} /* terminator */ | ||
560 | }; | ||
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..9c5710daed50 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -2849,7 +2849,7 @@ static struct pci_driver driver = { | |||
2849 | 2849 | ||
2850 | static int __init alsa_card_intel8x0_init(void) | 2850 | static int __init alsa_card_intel8x0_init(void) |
2851 | { | 2851 | { |
2852 | return pci_module_init(&driver); | 2852 | return pci_register_driver(&driver); |
2853 | } | 2853 | } |
2854 | 2854 | ||
2855 | static void __exit alsa_card_intel8x0_exit(void) | 2855 | static void __exit alsa_card_intel8x0_exit(void) |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 67da096d659b..f655cf914060 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -500,6 +500,8 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97, | |||
500 | res = 0xffff; | 500 | res = 0xffff; |
501 | } | 501 | } |
502 | } | 502 | } |
503 | if (reg == AC97_GPIO_STATUS) | ||
504 | iagetword(chip, 0); /* clear semaphore */ | ||
503 | return res; | 505 | return res; |
504 | } | 506 | } |
505 | 507 | ||
@@ -1450,7 +1452,7 @@ static struct pci_driver driver = { | |||
1450 | 1452 | ||
1451 | static int __init alsa_card_intel8x0m_init(void) | 1453 | static int __init alsa_card_intel8x0m_init(void) |
1452 | { | 1454 | { |
1453 | return pci_module_init(&driver); | 1455 | return pci_register_driver(&driver); |
1454 | } | 1456 | } |
1455 | 1457 | ||
1456 | static void __exit alsa_card_intel8x0m_exit(void) | 1458 | 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..096f15132853 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,6 +980,71 @@ 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 |
@@ -1565,6 +1642,68 @@ static void snd_m3_update_ptr(m3_t *chip, m3_dma_t *s) | |||
1565 | } | 1642 | } |
1566 | } | 1643 | } |
1567 | 1644 | ||
1645 | static void snd_m3_update_hw_volume(unsigned long private_data) | ||
1646 | { | ||
1647 | m3_t *chip = (m3_t *) private_data; | ||
1648 | int x, val; | ||
1649 | unsigned long flags; | ||
1650 | |||
1651 | /* Figure out which volume control button was pushed, | ||
1652 | based on differences from the default register | ||
1653 | values. */ | ||
1654 | x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee; | ||
1655 | |||
1656 | /* Reset the volume control registers. */ | ||
1657 | outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE); | ||
1658 | outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE); | ||
1659 | outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER); | ||
1660 | outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER); | ||
1661 | |||
1662 | if (!chip->master_switch || !chip->master_volume) | ||
1663 | return; | ||
1664 | |||
1665 | /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ | ||
1666 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
1667 | |||
1668 | val = chip->ac97->regs[AC97_MASTER_VOL]; | ||
1669 | switch (x) { | ||
1670 | case 0x88: | ||
1671 | /* mute */ | ||
1672 | val ^= 0x8000; | ||
1673 | chip->ac97->regs[AC97_MASTER_VOL] = val; | ||
1674 | outw(val, chip->iobase + CODEC_DATA); | ||
1675 | outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | ||
1676 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1677 | &chip->master_switch->id); | ||
1678 | break; | ||
1679 | case 0xaa: | ||
1680 | /* volume up */ | ||
1681 | if ((val & 0x7f) > 0) | ||
1682 | val--; | ||
1683 | if ((val & 0x7f00) > 0) | ||
1684 | val -= 0x0100; | ||
1685 | chip->ac97->regs[AC97_MASTER_VOL] = val; | ||
1686 | outw(val, chip->iobase + CODEC_DATA); | ||
1687 | outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | ||
1688 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1689 | &chip->master_volume->id); | ||
1690 | break; | ||
1691 | case 0x66: | ||
1692 | /* volume down */ | ||
1693 | if ((val & 0x7f) < 0x1f) | ||
1694 | val++; | ||
1695 | if ((val & 0x7f00) < 0x1f00) | ||
1696 | val += 0x0100; | ||
1697 | chip->ac97->regs[AC97_MASTER_VOL] = val; | ||
1698 | outw(val, chip->iobase + CODEC_DATA); | ||
1699 | outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND); | ||
1700 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1701 | &chip->master_volume->id); | ||
1702 | break; | ||
1703 | } | ||
1704 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | ||
1705 | } | ||
1706 | |||
1568 | static irqreturn_t | 1707 | static irqreturn_t |
1569 | snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 1708 | snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
1570 | { | 1709 | { |
@@ -1576,7 +1715,10 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1576 | 1715 | ||
1577 | if (status == 0xff) | 1716 | if (status == 0xff) |
1578 | return IRQ_NONE; | 1717 | return IRQ_NONE; |
1579 | 1718 | ||
1719 | if (status & HV_INT_PENDING) | ||
1720 | tasklet_hi_schedule(&chip->hwvol_tq); | ||
1721 | |||
1580 | /* | 1722 | /* |
1581 | * ack an assp int if its running | 1723 | * ack an assp int if its running |
1582 | * and has an int pending | 1724 | * and has an int pending |
@@ -1605,7 +1747,7 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1605 | #endif | 1747 | #endif |
1606 | 1748 | ||
1607 | /* ack ints */ | 1749 | /* ack ints */ |
1608 | snd_m3_outw(chip, HOST_INT_STATUS, status); | 1750 | outb(status, chip->iobase + HOST_INT_STATUS); |
1609 | 1751 | ||
1610 | return IRQ_HANDLED; | 1752 | return IRQ_HANDLED; |
1611 | } | 1753 | } |
@@ -1842,24 +1984,32 @@ static unsigned short | |||
1842 | snd_m3_ac97_read(ac97_t *ac97, unsigned short reg) | 1984 | snd_m3_ac97_read(ac97_t *ac97, unsigned short reg) |
1843 | { | 1985 | { |
1844 | m3_t *chip = ac97->private_data; | 1986 | m3_t *chip = ac97->private_data; |
1987 | unsigned long flags; | ||
1988 | unsigned short data; | ||
1845 | 1989 | ||
1846 | if (snd_m3_ac97_wait(chip)) | 1990 | if (snd_m3_ac97_wait(chip)) |
1847 | return 0xffff; | 1991 | return 0xffff; |
1992 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
1848 | snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); | 1993 | snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND); |
1849 | if (snd_m3_ac97_wait(chip)) | 1994 | if (snd_m3_ac97_wait(chip)) |
1850 | return 0xffff; | 1995 | return 0xffff; |
1851 | return snd_m3_inw(chip, CODEC_DATA); | 1996 | data = snd_m3_inw(chip, CODEC_DATA); |
1997 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | ||
1998 | return data; | ||
1852 | } | 1999 | } |
1853 | 2000 | ||
1854 | static void | 2001 | static void |
1855 | snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) | 2002 | snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) |
1856 | { | 2003 | { |
1857 | m3_t *chip = ac97->private_data; | 2004 | m3_t *chip = ac97->private_data; |
2005 | unsigned long flags; | ||
1858 | 2006 | ||
1859 | if (snd_m3_ac97_wait(chip)) | 2007 | if (snd_m3_ac97_wait(chip)) |
1860 | return; | 2008 | return; |
2009 | spin_lock_irqsave(&chip->ac97_lock, flags); | ||
1861 | snd_m3_outw(chip, val, CODEC_DATA); | 2010 | snd_m3_outw(chip, val, CODEC_DATA); |
1862 | snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); | 2011 | snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND); |
2012 | spin_unlock_irqrestore(&chip->ac97_lock, flags); | ||
1863 | } | 2013 | } |
1864 | 2014 | ||
1865 | 2015 | ||
@@ -1968,6 +2118,7 @@ static int __devinit snd_m3_mixer(m3_t *chip) | |||
1968 | { | 2118 | { |
1969 | ac97_bus_t *pbus; | 2119 | ac97_bus_t *pbus; |
1970 | ac97_template_t ac97; | 2120 | ac97_template_t ac97; |
2121 | snd_ctl_elem_id_t id; | ||
1971 | int err; | 2122 | int err; |
1972 | static ac97_bus_ops_t ops = { | 2123 | static ac97_bus_ops_t ops = { |
1973 | .write = snd_m3_ac97_write, | 2124 | .write = snd_m3_ac97_write, |
@@ -1988,6 +2139,15 @@ static int __devinit snd_m3_mixer(m3_t *chip) | |||
1988 | schedule_timeout(HZ / 10); | 2139 | schedule_timeout(HZ / 10); |
1989 | snd_ac97_write(chip->ac97, AC97_PCM, 0); | 2140 | snd_ac97_write(chip->ac97, AC97_PCM, 0); |
1990 | 2141 | ||
2142 | memset(&id, 0, sizeof(id)); | ||
2143 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
2144 | strcpy(id.name, "Master Playback Switch"); | ||
2145 | chip->master_switch = snd_ctl_find_id(chip->card, &id); | ||
2146 | memset(&id, 0, sizeof(id)); | ||
2147 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
2148 | strcpy(id.name, "Master Playback Volume"); | ||
2149 | chip->master_volume = snd_ctl_find_id(chip->card, &id); | ||
2150 | |||
1991 | return 0; | 2151 | return 0; |
1992 | } | 2152 | } |
1993 | 2153 | ||
@@ -2293,6 +2453,7 @@ static int | |||
2293 | snd_m3_chip_init(m3_t *chip) | 2453 | snd_m3_chip_init(m3_t *chip) |
2294 | { | 2454 | { |
2295 | struct pci_dev *pcidev = chip->pci; | 2455 | struct pci_dev *pcidev = chip->pci; |
2456 | unsigned long io = chip->iobase; | ||
2296 | u32 n; | 2457 | u32 n; |
2297 | u16 w; | 2458 | u16 w; |
2298 | u8 t; /* makes as much sense as 'n', no? */ | 2459 | u8 t; /* makes as much sense as 'n', no? */ |
@@ -2303,8 +2464,27 @@ snd_m3_chip_init(m3_t *chip) | |||
2303 | DISABLE_LEGACY); | 2464 | DISABLE_LEGACY); |
2304 | pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); | 2465 | pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); |
2305 | 2466 | ||
2467 | if (chip->hv_quirk && chip->hv_quirk->is_omnibook) { | ||
2468 | /* | ||
2469 | * Volume buttons on some HP OmniBook laptops don't work | ||
2470 | * correctly. This makes them work for the most part. | ||
2471 | * | ||
2472 | * Volume up and down buttons on the laptop side work. | ||
2473 | * Fn+cursor_up (volme up) works. | ||
2474 | * Fn+cursor_down (volume down) doesn't work. | ||
2475 | * Fn+F7 (mute) works acts as volume up. | ||
2476 | */ | ||
2477 | outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK); | ||
2478 | outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION); | ||
2479 | outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA); | ||
2480 | outw(0xffff, io + GPIO_MASK); | ||
2481 | } | ||
2306 | pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); | 2482 | pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); |
2307 | n &= REDUCED_DEBOUNCE; | 2483 | n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD); |
2484 | if (chip->hv_quirk) | ||
2485 | n |= chip->hv_quirk->config; | ||
2486 | /* For some reason we must always use reduced debounce. */ | ||
2487 | n |= REDUCED_DEBOUNCE; | ||
2308 | n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; | 2488 | n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; |
2309 | pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n); | 2489 | pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n); |
2310 | 2490 | ||
@@ -2332,6 +2512,12 @@ snd_m3_chip_init(m3_t *chip) | |||
2332 | 2512 | ||
2333 | outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B); | 2513 | outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B); |
2334 | 2514 | ||
2515 | outb(0x00, io + HARDWARE_VOL_CTRL); | ||
2516 | outb(0x88, io + SHADOW_MIX_REG_VOICE); | ||
2517 | outb(0x88, io + HW_VOL_COUNTER_VOICE); | ||
2518 | outb(0x88, io + SHADOW_MIX_REG_MASTER); | ||
2519 | outb(0x88, io + HW_VOL_COUNTER_MASTER); | ||
2520 | |||
2335 | return 0; | 2521 | return 0; |
2336 | } | 2522 | } |
2337 | 2523 | ||
@@ -2341,7 +2527,7 @@ snd_m3_enable_ints(m3_t *chip) | |||
2341 | unsigned long io = chip->iobase; | 2527 | unsigned long io = chip->iobase; |
2342 | 2528 | ||
2343 | /* TODO: MPU401 not supported yet */ | 2529 | /* TODO: MPU401 not supported yet */ |
2344 | outw(ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL); | 2530 | outw(ASSP_INT_ENABLE | HV_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL); |
2345 | outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, | 2531 | outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, |
2346 | io + ASSP_CONTROL_C); | 2532 | io + ASSP_CONTROL_C); |
2347 | } | 2533 | } |
@@ -2367,7 +2553,7 @@ static int snd_m3_free(m3_t *chip) | |||
2367 | kfree(chip->substreams); | 2553 | kfree(chip->substreams); |
2368 | } | 2554 | } |
2369 | if (chip->iobase) { | 2555 | if (chip->iobase) { |
2370 | snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */ | 2556 | outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */ |
2371 | } | 2557 | } |
2372 | 2558 | ||
2373 | #ifdef CONFIG_PM | 2559 | #ifdef CONFIG_PM |
@@ -2486,7 +2672,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, | |||
2486 | m3_t *chip; | 2672 | m3_t *chip; |
2487 | int i, err; | 2673 | int i, err; |
2488 | struct m3_quirk *quirk; | 2674 | struct m3_quirk *quirk; |
2489 | u16 subsystem_vendor, subsystem_device; | 2675 | struct m3_hv_quirk *hv_quirk; |
2490 | static snd_device_ops_t ops = { | 2676 | static snd_device_ops_t ops = { |
2491 | .dev_free = snd_m3_dev_free, | 2677 | .dev_free = snd_m3_dev_free, |
2492 | }; | 2678 | }; |
@@ -2524,18 +2710,25 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, | |||
2524 | chip->pci = pci; | 2710 | chip->pci = pci; |
2525 | chip->irq = -1; | 2711 | chip->irq = -1; |
2526 | 2712 | ||
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++) { | 2713 | for (quirk = m3_quirk_list; quirk->vendor; quirk++) { |
2531 | if (subsystem_vendor == quirk->vendor && | 2714 | if (pci->subsystem_vendor == quirk->vendor && |
2532 | subsystem_device == quirk->device) { | 2715 | pci->subsystem_device == quirk->device) { |
2533 | printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name); | 2716 | printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name); |
2534 | chip->quirk = quirk; | 2717 | chip->quirk = quirk; |
2535 | break; | 2718 | break; |
2536 | } | 2719 | } |
2537 | } | 2720 | } |
2538 | 2721 | ||
2722 | for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) { | ||
2723 | if (pci->vendor == hv_quirk->vendor && | ||
2724 | pci->device == hv_quirk->device && | ||
2725 | pci->subsystem_vendor == hv_quirk->subsystem_vendor && | ||
2726 | pci->subsystem_device == hv_quirk->subsystem_device) { | ||
2727 | chip->hv_quirk = hv_quirk; | ||
2728 | break; | ||
2729 | } | ||
2730 | } | ||
2731 | |||
2539 | chip->external_amp = enable_amp; | 2732 | chip->external_amp = enable_amp; |
2540 | if (amp_gpio >= 0 && amp_gpio <= 0x0f) | 2733 | if (amp_gpio >= 0 && amp_gpio <= 0x0f) |
2541 | chip->amp_gpio = amp_gpio; | 2734 | chip->amp_gpio = amp_gpio; |
@@ -2593,6 +2786,9 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, | |||
2593 | return err; | 2786 | return err; |
2594 | } | 2787 | } |
2595 | 2788 | ||
2789 | spin_lock_init(&chip->ac97_lock); | ||
2790 | tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); | ||
2791 | |||
2596 | if ((err = snd_m3_mixer(chip)) < 0) | 2792 | if ((err = snd_m3_mixer(chip)) < 0) |
2597 | return err; | 2793 | return err; |
2598 | 2794 | ||
@@ -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..082c0d0f73d2 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -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..8a52091f8552 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -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/hdsp.c b/sound/pci/rme9652/hdsp.c index 12efbf0fab54..b35ed5f0c042 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -4912,19 +4912,9 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp) | |||
4912 | release_firmware(fw); | 4912 | release_firmware(fw); |
4913 | return -EINVAL; | 4913 | return -EINVAL; |
4914 | } | 4914 | } |
4915 | #ifdef SNDRV_BIG_ENDIAN | 4915 | |
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)); | 4916 | memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache)); |
4927 | #endif | 4917 | |
4928 | release_firmware(fw); | 4918 | release_firmware(fw); |
4929 | 4919 | ||
4930 | hdsp->state |= HDSP_FirmwareCached; | 4920 | hdsp->state |= HDSP_FirmwareCached; |
@@ -5194,7 +5184,7 @@ static struct pci_driver driver = { | |||
5194 | 5184 | ||
5195 | static int __init alsa_card_hdsp_init(void) | 5185 | static int __init alsa_card_hdsp_init(void) |
5196 | { | 5186 | { |
5197 | return pci_module_init(&driver); | 5187 | return pci_register_driver(&driver); |
5198 | } | 5188 | } |
5199 | 5189 | ||
5200 | static void __exit alsa_card_hdsp_exit(void) | 5190 | static void __exit alsa_card_hdsp_exit(void) |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 69cd81eaa111..5861f234af21 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -2664,7 +2664,7 @@ static struct pci_driver driver = { | |||
2664 | 2664 | ||
2665 | static int __init alsa_card_hammerfall_init(void) | 2665 | static int __init alsa_card_hammerfall_init(void) |
2666 | { | 2666 | { |
2667 | return pci_module_init(&driver); | 2667 | return pci_register_driver(&driver); |
2668 | } | 2668 | } |
2669 | 2669 | ||
2670 | static void __exit alsa_card_hammerfall_exit(void) | 2670 | 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..5d21cb811c8a 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -184,7 +184,7 @@ static struct pci_driver driver = { | |||
184 | 184 | ||
185 | static int __init alsa_card_trident_init(void) | 185 | static int __init alsa_card_trident_init(void) |
186 | { | 186 | { |
187 | return pci_module_init(&driver); | 187 | return pci_register_driver(&driver); |
188 | } | 188 | } |
189 | 189 | ||
190 | static void __exit alsa_card_trident_exit(void) | 190 | static void __exit alsa_card_trident_exit(void) |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 9b4d74d49f98..bb322de4777f 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]; |
@@ -924,15 +926,17 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream) | |||
924 | via82xx_t *chip = snd_pcm_substream_chip(substream); | 926 | via82xx_t *chip = snd_pcm_substream_chip(substream); |
925 | viadev_t *viadev = (viadev_t *)substream->runtime->private_data; | 927 | viadev_t *viadev = (viadev_t *)substream->runtime->private_data; |
926 | snd_pcm_runtime_t *runtime = substream->runtime; | 928 | snd_pcm_runtime_t *runtime = substream->runtime; |
929 | int ac97_rate = chip->dxs_src ? 48000 : runtime->rate; | ||
927 | int rate_changed; | 930 | int rate_changed; |
928 | u32 rbits; | 931 | u32 rbits; |
929 | 932 | ||
930 | if ((rate_changed = via_lock_rate(&chip->rates[0], runtime->rate)) < 0) | 933 | if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0) |
931 | return rate_changed; | 934 | return rate_changed; |
932 | if (rate_changed) { | 935 | if (rate_changed) { |
933 | snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, | 936 | snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, |
934 | chip->no_vra ? 48000 : runtime->rate); | 937 | chip->no_vra ? 48000 : runtime->rate); |
935 | snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate); | 938 | snd_ac97_set_rate(chip->ac97, AC97_SPDIF, |
939 | chip->no_vra ? 48000 : runtime->rate); | ||
936 | } | 940 | } |
937 | if (runtime->rate == 48000) | 941 | if (runtime->rate == 48000) |
938 | rbits = 0xfffff; | 942 | rbits = 0xfffff; |
@@ -1074,6 +1078,12 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst | |||
1074 | /* fixed DXS playback rate */ | 1078 | /* fixed DXS playback rate */ |
1075 | runtime->hw.rates = SNDRV_PCM_RATE_48000; | 1079 | runtime->hw.rates = SNDRV_PCM_RATE_48000; |
1076 | runtime->hw.rate_min = runtime->hw.rate_max = 48000; | 1080 | runtime->hw.rate_min = runtime->hw.rate_max = 48000; |
1081 | } else if (chip->dxs_src && viadev->reg_offset < 0x40) { | ||
1082 | /* use full SRC capabilities of DXS */ | ||
1083 | runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS | | ||
1084 | SNDRV_PCM_RATE_8000_48000); | ||
1085 | runtime->hw.rate_min = 8000; | ||
1086 | runtime->hw.rate_max = 48000; | ||
1077 | } else if (! ratep->rate) { | 1087 | } else if (! ratep->rate) { |
1078 | int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; | 1088 | int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC; |
1079 | runtime->hw.rates = chip->ac97->rates[idx]; | 1089 | runtime->hw.rates = chip->ac97->rates[idx]; |
@@ -2149,14 +2159,17 @@ static int __devinit check_dxs_list(struct pci_dev *pci) | |||
2149 | { .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/ | 2159 | { .vendor = 0x1043, .device = 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 */ | 2160 | { .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */ |
2151 | { .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ | 2161 | { .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ |
2162 | { .vendor = 0x1043, .device = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */ | ||
2152 | { .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ | 2163 | { .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */ |
2153 | { .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */ | 2164 | { .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */ |
2154 | { .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */ | 2165 | { .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */ |
2155 | { .vendor = 0x1106, .device = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */ | 2166 | { .vendor = 0x1106, .device = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */ |
2156 | { .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */ | 2167 | { .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */ |
2168 | { .vendor = 0x1106, .device = 0xc001, .action = VIA_DXS_SRC }, /* Insight P4-ITX */ | ||
2157 | { .vendor = 0x1297, .device = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */ | 2169 | { .vendor = 0x1297, .device = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */ |
2158 | { .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */ | 2170 | { .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */ |
2159 | { .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */ | 2171 | { .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */ |
2172 | { .vendor = 0x1462, .device = 0x0080, .action = VIA_DXS_SRC }, /* MSI K8T Neo-FIS2R */ | ||
2160 | { .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ | 2173 | { .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ |
2161 | { .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */ | 2174 | { .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */ |
2162 | { .vendor = 0x1462, .device = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */ | 2175 | { .vendor = 0x1462, .device = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */ |
@@ -2166,6 +2179,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) | |||
2166 | { .vendor = 0x147b, .device = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */ | 2179 | { .vendor = 0x147b, .device = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */ |
2167 | { .vendor = 0x147b, .device = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ | 2180 | { .vendor = 0x147b, .device = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ |
2168 | { .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ | 2181 | { .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ |
2182 | { .vendor = 0x14ff, .device = 0x0408, .action = VIA_DXS_NO_VRA }, /* Twinhead mobo */ | ||
2169 | { .vendor = 0x1584, .device = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ | 2183 | { .vendor = 0x1584, .device = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ |
2170 | { .vendor = 0x1584, .device = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ | 2184 | { .vendor = 0x1584, .device = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ |
2171 | { .vendor = 0x161f, .device = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ | 2185 | { .vendor = 0x161f, .device = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ |
@@ -2288,6 +2302,10 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci, | |||
2288 | chip->dxs_fixed = 1; | 2302 | chip->dxs_fixed = 1; |
2289 | else if (dxs_support[dev] == VIA_DXS_NO_VRA) | 2303 | else if (dxs_support[dev] == VIA_DXS_NO_VRA) |
2290 | chip->no_vra = 1; | 2304 | chip->no_vra = 1; |
2305 | else if (dxs_support[dev] == VIA_DXS_SRC) { | ||
2306 | chip->no_vra = 1; | ||
2307 | chip->dxs_src = 1; | ||
2308 | } | ||
2291 | } | 2309 | } |
2292 | if ((err = snd_via8233_init_misc(chip, dev)) < 0) | 2310 | if ((err = snd_via8233_init_misc(chip, dev)) < 0) |
2293 | goto __error; | 2311 | goto __error; |
@@ -2334,7 +2352,7 @@ static struct pci_driver driver = { | |||
2334 | 2352 | ||
2335 | static int __init alsa_card_via82xx_init(void) | 2353 | static int __init alsa_card_via82xx_init(void) |
2336 | { | 2354 | { |
2337 | return pci_module_init(&driver); | 2355 | return pci_register_driver(&driver); |
2338 | } | 2356 | } |
2339 | 2357 | ||
2340 | static void __exit alsa_card_via82xx_exit(void) | 2358 | static void __exit alsa_card_via82xx_exit(void) |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index ea5c6f640159..276ce5299684 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -938,7 +938,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip) | |||
938 | * | 938 | * |
939 | */ | 939 | */ |
940 | 940 | ||
941 | static int __devinit snd_via82xx_chip_init(via82xx_t *chip) | 941 | static int snd_via82xx_chip_init(via82xx_t *chip) |
942 | { | 942 | { |
943 | unsigned int val; | 943 | unsigned int val; |
944 | int max_count; | 944 | int max_count; |
@@ -1233,7 +1233,7 @@ static struct pci_driver driver = { | |||
1233 | 1233 | ||
1234 | static int __init alsa_card_via82xx_init(void) | 1234 | static int __init alsa_card_via82xx_init(void) |
1235 | { | 1235 | { |
1236 | return pci_module_init(&driver); | 1236 | return pci_register_driver(&driver); |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | static void __exit alsa_card_via82xx_exit(void) | 1239 | 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/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..997cf37cdddd 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -1421,17 +1421,15 @@ static snd_kcontrol_new_t snd_ymfpci_drec_source __devinitdata = { | |||
1421 | 1421 | ||
1422 | static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) | 1422 | static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) |
1423 | { | 1423 | { |
1424 | unsigned int mask = 1; | ||
1425 | |||
1426 | switch (kcontrol->private_value) { | 1424 | switch (kcontrol->private_value) { |
1427 | case YDSXGR_SPDIFOUTCTRL: break; | 1425 | case YDSXGR_SPDIFOUTCTRL: break; |
1428 | case YDSXGR_SPDIFINCTRL: break; | 1426 | case YDSXGR_SPDIFINCTRL: break; |
1429 | default: return -EINVAL; | 1427 | default: return -EINVAL; |
1430 | } | 1428 | } |
1431 | uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | 1429 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
1432 | uinfo->count = 1; | 1430 | uinfo->count = 1; |
1433 | uinfo->value.integer.min = 0; | 1431 | uinfo->value.integer.min = 0; |
1434 | uinfo->value.integer.max = mask; | 1432 | uinfo->value.integer.max = 1; |
1435 | return 0; | 1433 | return 0; |
1436 | } | 1434 | } |
1437 | 1435 | ||
@@ -1439,7 +1437,7 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1439 | { | 1437 | { |
1440 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); | 1438 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); |
1441 | int reg = kcontrol->private_value; | 1439 | int reg = kcontrol->private_value; |
1442 | unsigned int shift = 0, mask = 1, invert = 0; | 1440 | unsigned int shift = 0, mask = 1; |
1443 | 1441 | ||
1444 | switch (kcontrol->private_value) { | 1442 | switch (kcontrol->private_value) { |
1445 | case YDSXGR_SPDIFOUTCTRL: break; | 1443 | case YDSXGR_SPDIFOUTCTRL: break; |
@@ -1447,8 +1445,6 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1447 | default: return -EINVAL; | 1445 | default: return -EINVAL; |
1448 | } | 1446 | } |
1449 | ucontrol->value.integer.value[0] = (snd_ymfpci_readl(chip, reg) >> shift) & mask; | 1447 | 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; | 1448 | return 0; |
1453 | } | 1449 | } |
1454 | 1450 | ||
@@ -1456,7 +1452,7 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1456 | { | 1452 | { |
1457 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); | 1453 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); |
1458 | int reg = kcontrol->private_value; | 1454 | int reg = kcontrol->private_value; |
1459 | unsigned int shift = 0, mask = 1, invert = 0; | 1455 | unsigned int shift = 0, mask = 1; |
1460 | int change; | 1456 | int change; |
1461 | unsigned int val, oval; | 1457 | unsigned int val, oval; |
1462 | 1458 | ||
@@ -1466,8 +1462,6 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1466 | default: return -EINVAL; | 1462 | default: return -EINVAL; |
1467 | } | 1463 | } |
1468 | val = (ucontrol->value.integer.value[0] & mask); | 1464 | val = (ucontrol->value.integer.value[0] & mask); |
1469 | if (invert) | ||
1470 | val = mask - val; | ||
1471 | val <<= shift; | 1465 | val <<= shift; |
1472 | spin_lock_irq(&chip->reg_lock); | 1466 | spin_lock_irq(&chip->reg_lock); |
1473 | oval = snd_ymfpci_readl(chip, reg); | 1467 | oval = snd_ymfpci_readl(chip, reg); |
@@ -1487,14 +1481,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) | 1481 | static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) |
1488 | { | 1482 | { |
1489 | unsigned int reg = kcontrol->private_value; | 1483 | unsigned int reg = kcontrol->private_value; |
1490 | unsigned int mask = 16383; | ||
1491 | 1484 | ||
1492 | if (reg < 0x80 || reg >= 0xc0) | 1485 | if (reg < 0x80 || reg >= 0xc0) |
1493 | return -EINVAL; | 1486 | return -EINVAL; |
1494 | uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | 1487 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1495 | uinfo->count = 2; | 1488 | uinfo->count = 2; |
1496 | uinfo->value.integer.min = 0; | 1489 | uinfo->value.integer.min = 0; |
1497 | uinfo->value.integer.max = mask; | 1490 | uinfo->value.integer.max = 16383; |
1498 | return 0; | 1491 | return 0; |
1499 | } | 1492 | } |
1500 | 1493 | ||
@@ -1502,7 +1495,7 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1502 | { | 1495 | { |
1503 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); | 1496 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); |
1504 | unsigned int reg = kcontrol->private_value; | 1497 | unsigned int reg = kcontrol->private_value; |
1505 | unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0; | 1498 | unsigned int shift_left = 0, shift_right = 16, mask = 16383; |
1506 | unsigned int val; | 1499 | unsigned int val; |
1507 | 1500 | ||
1508 | if (reg < 0x80 || reg >= 0xc0) | 1501 | if (reg < 0x80 || reg >= 0xc0) |
@@ -1512,10 +1505,6 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1512 | spin_unlock_irq(&chip->reg_lock); | 1505 | spin_unlock_irq(&chip->reg_lock); |
1513 | ucontrol->value.integer.value[0] = (val >> shift_left) & mask; | 1506 | ucontrol->value.integer.value[0] = (val >> shift_left) & mask; |
1514 | ucontrol->value.integer.value[1] = (val >> shift_right) & mask; | 1507 | 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; | 1508 | return 0; |
1520 | } | 1509 | } |
1521 | 1510 | ||
@@ -1523,7 +1512,7 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1523 | { | 1512 | { |
1524 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); | 1513 | ymfpci_t *chip = snd_kcontrol_chip(kcontrol); |
1525 | unsigned int reg = kcontrol->private_value; | 1514 | unsigned int reg = kcontrol->private_value; |
1526 | unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0; | 1515 | unsigned int shift_left = 0, shift_right = 16, mask = 16383; |
1527 | int change; | 1516 | int change; |
1528 | unsigned int val1, val2, oval; | 1517 | unsigned int val1, val2, oval; |
1529 | 1518 | ||
@@ -1531,10 +1520,6 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1531 | return -EINVAL; | 1520 | return -EINVAL; |
1532 | val1 = ucontrol->value.integer.value[0] & mask; | 1521 | val1 = ucontrol->value.integer.value[0] & mask; |
1533 | val2 = ucontrol->value.integer.value[1] & mask; | 1522 | val2 = ucontrol->value.integer.value[1] & mask; |
1534 | if (invert) { | ||
1535 | val1 = mask - val1; | ||
1536 | val2 = mask - val2; | ||
1537 | } | ||
1538 | val1 <<= shift_left; | 1523 | val1 <<= shift_left; |
1539 | val2 <<= shift_right; | 1524 | val2 <<= shift_right; |
1540 | spin_lock_irq(&chip->reg_lock); | 1525 | spin_lock_irq(&chip->reg_lock); |
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 aae66144d411..a82412b8790d 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; |
@@ -177,7 +177,7 @@ struct snd_usb_substream { | |||
177 | unsigned int nurbs; /* # urbs */ | 177 | unsigned int nurbs; /* # urbs */ |
178 | snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */ | 178 | snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */ |
179 | snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */ | 179 | 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 */ | 180 | char syncbuf[SYNC_URBS * 4]; /* sync buffer; it's so small - let's get static */ |
181 | char *tmpbuf; /* temporary buffer for playback */ | 181 | char *tmpbuf; /* temporary buffer for playback */ |
182 | 182 | ||
183 | u64 formats; /* format bitmasks (all or'ed) */ | 183 | u64 formats; /* format bitmasks (all or'ed) */ |
@@ -251,17 +251,13 @@ static int prepare_capture_sync_urb(snd_usb_substream_t *subs, | |||
251 | { | 251 | { |
252 | unsigned char *cp = urb->transfer_buffer; | 252 | unsigned char *cp = urb->transfer_buffer; |
253 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | 253 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; |
254 | int i, offs; | ||
255 | 254 | ||
256 | urb->number_of_packets = ctx->packets; | ||
257 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 255 | 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) { | 256 | urb->iso_frame_desc[0].length = 3; |
259 | urb->iso_frame_desc[i].length = 3; | 257 | urb->iso_frame_desc[0].offset = 0; |
260 | urb->iso_frame_desc[i].offset = offs; | 258 | cp[0] = subs->freqn >> 2; |
261 | cp[0] = subs->freqn >> 2; | 259 | cp[1] = subs->freqn >> 10; |
262 | cp[1] = subs->freqn >> 10; | 260 | cp[2] = subs->freqn >> 18; |
263 | cp[2] = subs->freqn >> 18; | ||
264 | } | ||
265 | return 0; | 261 | return 0; |
266 | } | 262 | } |
267 | 263 | ||
@@ -277,18 +273,14 @@ static int prepare_capture_sync_urb_hs(snd_usb_substream_t *subs, | |||
277 | { | 273 | { |
278 | unsigned char *cp = urb->transfer_buffer; | 274 | unsigned char *cp = urb->transfer_buffer; |
279 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | 275 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; |
280 | int i, offs; | ||
281 | 276 | ||
282 | urb->number_of_packets = ctx->packets; | ||
283 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 277 | 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) { | 278 | urb->iso_frame_desc[0].length = 4; |
285 | urb->iso_frame_desc[i].length = 4; | 279 | urb->iso_frame_desc[0].offset = 0; |
286 | urb->iso_frame_desc[i].offset = offs; | 280 | cp[0] = subs->freqn; |
287 | cp[0] = subs->freqn; | 281 | cp[1] = subs->freqn >> 8; |
288 | cp[1] = subs->freqn >> 8; | 282 | cp[2] = subs->freqn >> 16; |
289 | cp[2] = subs->freqn >> 16; | 283 | cp[3] = subs->freqn >> 24; |
290 | cp[3] = subs->freqn >> 24; | ||
291 | } | ||
292 | return 0; | 284 | return 0; |
293 | } | 285 | } |
294 | 286 | ||
@@ -418,15 +410,11 @@ static int prepare_playback_sync_urb(snd_usb_substream_t *subs, | |||
418 | snd_pcm_runtime_t *runtime, | 410 | snd_pcm_runtime_t *runtime, |
419 | struct urb *urb) | 411 | struct urb *urb) |
420 | { | 412 | { |
421 | int i, offs; | ||
422 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | 413 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; |
423 | 414 | ||
424 | urb->number_of_packets = ctx->packets; | ||
425 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 415 | 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) { | 416 | urb->iso_frame_desc[0].length = 3; |
427 | urb->iso_frame_desc[i].length = 3; | 417 | urb->iso_frame_desc[0].offset = 0; |
428 | urb->iso_frame_desc[i].offset = offs; | ||
429 | } | ||
430 | return 0; | 418 | return 0; |
431 | } | 419 | } |
432 | 420 | ||
@@ -440,15 +428,11 @@ static int prepare_playback_sync_urb_hs(snd_usb_substream_t *subs, | |||
440 | snd_pcm_runtime_t *runtime, | 428 | snd_pcm_runtime_t *runtime, |
441 | struct urb *urb) | 429 | struct urb *urb) |
442 | { | 430 | { |
443 | int i, offs; | ||
444 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; | 431 | snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context; |
445 | 432 | ||
446 | urb->number_of_packets = ctx->packets; | ||
447 | urb->dev = ctx->subs->dev; /* we need to set this at each time */ | 433 | 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) { | 434 | urb->iso_frame_desc[0].length = 4; |
449 | urb->iso_frame_desc[i].length = 4; | 435 | urb->iso_frame_desc[0].offset = 0; |
450 | urb->iso_frame_desc[i].offset = offs; | ||
451 | } | ||
452 | return 0; | 436 | return 0; |
453 | } | 437 | } |
454 | 438 | ||
@@ -462,31 +446,17 @@ static int retire_playback_sync_urb(snd_usb_substream_t *subs, | |||
462 | snd_pcm_runtime_t *runtime, | 446 | snd_pcm_runtime_t *runtime, |
463 | struct urb *urb) | 447 | struct urb *urb) |
464 | { | 448 | { |
465 | int i; | 449 | unsigned int f; |
466 | unsigned int f, found; | ||
467 | unsigned char *cp = urb->transfer_buffer; | ||
468 | unsigned long flags; | 450 | unsigned long flags; |
469 | 451 | ||
470 | found = 0; | 452 | if (urb->iso_frame_desc[0].status == 0 && |
471 | for (i = 0; i < urb->number_of_packets; i++, cp += 4) { | 453 | urb->iso_frame_desc[0].actual_length == 3) { |
472 | if (urb->iso_frame_desc[i].status || | 454 | f = combine_triple((u8*)urb->transfer_buffer) << 2; |
473 | urb->iso_frame_desc[i].actual_length < 3) | 455 | if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) { |
474 | continue; | 456 | spin_lock_irqsave(&subs->lock, flags); |
475 | f = combine_triple(cp) << 2; | 457 | subs->freqm = f; |
476 | #if 0 | 458 | 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 | } | 459 | } |
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 | } | 460 | } |
491 | 461 | ||
492 | return 0; | 462 | return 0; |
@@ -502,22 +472,17 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs, | |||
502 | snd_pcm_runtime_t *runtime, | 472 | snd_pcm_runtime_t *runtime, |
503 | struct urb *urb) | 473 | struct urb *urb) |
504 | { | 474 | { |
505 | int i; | 475 | unsigned int f; |
506 | unsigned int found; | ||
507 | unsigned char *cp = urb->transfer_buffer; | ||
508 | unsigned long flags; | 476 | unsigned long flags; |
509 | 477 | ||
510 | found = 0; | 478 | if (urb->iso_frame_desc[0].status == 0 && |
511 | for (i = 0; i < urb->number_of_packets; i++, cp += 4) { | 479 | urb->iso_frame_desc[0].actual_length == 4) { |
512 | if (urb->iso_frame_desc[i].status || | 480 | f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff; |
513 | urb->iso_frame_desc[i].actual_length < 4) | 481 | if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) { |
514 | continue; | 482 | spin_lock_irqsave(&subs->lock, flags); |
515 | found = combine_quad(cp) & 0x0fffffff; | 483 | subs->freqm = f; |
516 | } | 484 | spin_unlock_irqrestore(&subs->lock, flags); |
517 | if (found) { | 485 | } |
518 | spin_lock_irqsave(&subs->lock, flags); | ||
519 | subs->freqm = found; | ||
520 | spin_unlock_irqrestore(&subs->lock, flags); | ||
521 | } | 486 | } |
522 | 487 | ||
523 | return 0; | 488 | return 0; |
@@ -600,6 +565,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs, | |||
600 | /* set the buffer pointer */ | 565 | /* set the buffer pointer */ |
601 | urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride; | 566 | urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride; |
602 | subs->hwptr += offs; | 567 | subs->hwptr += offs; |
568 | if (subs->hwptr == runtime->buffer_size) | ||
569 | subs->hwptr = 0; | ||
603 | } | 570 | } |
604 | spin_unlock_irqrestore(&subs->lock, flags); | 571 | spin_unlock_irqrestore(&subs->lock, flags); |
605 | urb->transfer_buffer_length = offs * stride; | 572 | urb->transfer_buffer_length = offs * stride; |
@@ -1039,22 +1006,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
1039 | snd_urb_ctx_t *u = &subs->syncurb[i]; | 1006 | snd_urb_ctx_t *u = &subs->syncurb[i]; |
1040 | u->index = i; | 1007 | u->index = i; |
1041 | u->subs = subs; | 1008 | u->subs = subs; |
1042 | u->packets = nrpacks; | 1009 | u->packets = 1; |
1043 | u->urb = usb_alloc_urb(u->packets, GFP_KERNEL); | 1010 | u->urb = usb_alloc_urb(1, GFP_KERNEL); |
1044 | if (! u->urb) { | 1011 | if (! u->urb) { |
1045 | release_substream_urbs(subs, 0); | 1012 | release_substream_urbs(subs, 0); |
1046 | return -ENOMEM; | 1013 | return -ENOMEM; |
1047 | } | 1014 | } |
1048 | u->urb->transfer_buffer = subs->syncbuf + i * nrpacks * 4; | 1015 | u->urb->transfer_buffer = subs->syncbuf + i * 4; |
1049 | u->urb->transfer_buffer_length = nrpacks * 4; | 1016 | u->urb->transfer_buffer_length = 4; |
1050 | u->urb->dev = subs->dev; | 1017 | u->urb->dev = subs->dev; |
1051 | u->urb->pipe = subs->syncpipe; | 1018 | u->urb->pipe = subs->syncpipe; |
1052 | u->urb->transfer_flags = URB_ISO_ASAP; | 1019 | u->urb->transfer_flags = URB_ISO_ASAP; |
1053 | u->urb->number_of_packets = u->packets; | 1020 | u->urb->number_of_packets = 1; |
1054 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) | 1021 | u->urb->interval = 1 << subs->syncinterval; |
1055 | u->urb->interval = 8; | ||
1056 | else | ||
1057 | u->urb->interval = 1; | ||
1058 | u->urb->context = u; | 1022 | u->urb->context = u; |
1059 | u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb); | 1023 | u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb); |
1060 | } | 1024 | } |
@@ -1272,7 +1236,17 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt) | |||
1272 | subs->syncpipe = usb_rcvisocpipe(dev, ep); | 1236 | subs->syncpipe = usb_rcvisocpipe(dev, ep); |
1273 | else | 1237 | else |
1274 | subs->syncpipe = usb_sndisocpipe(dev, ep); | 1238 | subs->syncpipe = usb_sndisocpipe(dev, ep); |
1275 | subs->syncinterval = get_endpoint(alts, 1)->bRefresh; | 1239 | if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE && |
1240 | get_endpoint(alts, 1)->bRefresh >= 1 && | ||
1241 | get_endpoint(alts, 1)->bRefresh <= 9) | ||
1242 | subs->syncinterval = get_endpoint(alts, 1)->bRefresh; | ||
1243 | else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | ||
1244 | subs->syncinterval = 1; | ||
1245 | else if (get_endpoint(alts, 1)->bInterval >= 1 && | ||
1246 | get_endpoint(alts, 1)->bInterval <= 16) | ||
1247 | subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1; | ||
1248 | else | ||
1249 | subs->syncinterval = 3; | ||
1276 | } | 1250 | } |
1277 | 1251 | ||
1278 | /* always fill max packet size */ | 1252 | /* always fill max packet size */ |
@@ -1990,10 +1964,11 @@ static void proc_dump_substream_status(snd_usb_substream_t *subs, snd_info_buffe | |||
1990 | snd_iprintf(buffer, "%d ", subs->dataurb[i].packets); | 1964 | snd_iprintf(buffer, "%d ", subs->dataurb[i].packets); |
1991 | snd_iprintf(buffer, "]\n"); | 1965 | snd_iprintf(buffer, "]\n"); |
1992 | snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize); | 1966 | snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize); |
1993 | snd_iprintf(buffer, " Momentary freq = %u Hz\n", | 1967 | snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", |
1994 | snd_usb_get_speed(subs->dev) == USB_SPEED_FULL | 1968 | snd_usb_get_speed(subs->dev) == USB_SPEED_FULL |
1995 | ? get_full_speed_hz(subs->freqm) | 1969 | ? get_full_speed_hz(subs->freqm) |
1996 | : get_high_speed_hz(subs->freqm)); | 1970 | : get_high_speed_hz(subs->freqm), |
1971 | subs->freqm >> 16, subs->freqm & 0xffff); | ||
1997 | } else { | 1972 | } else { |
1998 | snd_iprintf(buffer, " Status: Stop\n"); | 1973 | snd_iprintf(buffer, " Status: Stop\n"); |
1999 | } | 1974 | } |
@@ -2183,17 +2158,15 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor | |||
2183 | /* | 2158 | /* |
2184 | * check if the device uses big-endian samples | 2159 | * check if the device uses big-endian samples |
2185 | */ | 2160 | */ |
2186 | static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp) | 2161 | static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp) |
2187 | { | 2162 | { |
2188 | /* M-Audio */ | 2163 | switch (chip->usb_id) { |
2189 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763) { | 2164 | case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */ |
2190 | /* Quattro: captured data only */ | 2165 | 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; | 2166 | return 1; |
2167 | break; | ||
2168 | case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ | ||
2169 | return 1; | ||
2197 | } | 2170 | } |
2198 | return 0; | 2171 | return 0; |
2199 | } | 2172 | } |
@@ -2207,7 +2180,7 @@ static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp) | |||
2207 | * @format: the format tag (wFormatTag) | 2180 | * @format: the format tag (wFormatTag) |
2208 | * @fmt: the format type descriptor | 2181 | * @fmt: the format type descriptor |
2209 | */ | 2182 | */ |
2210 | static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat *fp, | 2183 | static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *fp, |
2211 | int format, unsigned char *fmt) | 2184 | int format, unsigned char *fmt) |
2212 | { | 2185 | { |
2213 | int pcm_format; | 2186 | int pcm_format; |
@@ -2220,12 +2193,12 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat | |||
2220 | switch (format) { | 2193 | switch (format) { |
2221 | case 0: /* some devices don't define this correctly... */ | 2194 | 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", | 2195 | snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n", |
2223 | dev->devnum, fp->iface, fp->altsetting); | 2196 | chip->dev->devnum, fp->iface, fp->altsetting); |
2224 | /* fall-through */ | 2197 | /* fall-through */ |
2225 | case USB_AUDIO_FORMAT_PCM: | 2198 | case USB_AUDIO_FORMAT_PCM: |
2226 | if (sample_width > sample_bytes * 8) { | 2199 | if (sample_width > sample_bytes * 8) { |
2227 | snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n", | 2200 | snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n", |
2228 | dev->devnum, fp->iface, fp->altsetting, | 2201 | chip->dev->devnum, fp->iface, fp->altsetting, |
2229 | sample_width, sample_bytes); | 2202 | sample_width, sample_bytes); |
2230 | } | 2203 | } |
2231 | /* check the format byte size */ | 2204 | /* check the format byte size */ |
@@ -2234,13 +2207,13 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat | |||
2234 | pcm_format = SNDRV_PCM_FORMAT_S8; | 2207 | pcm_format = SNDRV_PCM_FORMAT_S8; |
2235 | break; | 2208 | break; |
2236 | case 2: | 2209 | case 2: |
2237 | if (is_big_endian_format(dev, fp)) | 2210 | if (is_big_endian_format(chip, fp)) |
2238 | pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */ | 2211 | pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */ |
2239 | else | 2212 | else |
2240 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; | 2213 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; |
2241 | break; | 2214 | break; |
2242 | case 3: | 2215 | case 3: |
2243 | if (is_big_endian_format(dev, fp)) | 2216 | if (is_big_endian_format(chip, fp)) |
2244 | pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */ | 2217 | pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */ |
2245 | else | 2218 | else |
2246 | pcm_format = SNDRV_PCM_FORMAT_S24_3LE; | 2219 | pcm_format = SNDRV_PCM_FORMAT_S24_3LE; |
@@ -2250,14 +2223,14 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat | |||
2250 | break; | 2223 | break; |
2251 | default: | 2224 | default: |
2252 | snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n", | 2225 | 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); | 2226 | chip->dev->devnum, fp->iface, |
2227 | fp->altsetting, sample_width, sample_bytes); | ||
2254 | break; | 2228 | break; |
2255 | } | 2229 | } |
2256 | break; | 2230 | break; |
2257 | case USB_AUDIO_FORMAT_PCM8: | 2231 | case USB_AUDIO_FORMAT_PCM8: |
2258 | /* Dallas DS4201 workaround */ | 2232 | /* Dallas DS4201 workaround */ |
2259 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa && | 2233 | if (chip->usb_id == USB_ID(0x04fa, 0x4201)) |
2260 | le16_to_cpu(dev->descriptor.idProduct) == 0x4201) | ||
2261 | pcm_format = SNDRV_PCM_FORMAT_S8; | 2234 | pcm_format = SNDRV_PCM_FORMAT_S8; |
2262 | else | 2235 | else |
2263 | pcm_format = SNDRV_PCM_FORMAT_U8; | 2236 | pcm_format = SNDRV_PCM_FORMAT_U8; |
@@ -2273,7 +2246,7 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat | |||
2273 | break; | 2246 | break; |
2274 | default: | 2247 | default: |
2275 | snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n", | 2248 | snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n", |
2276 | dev->devnum, fp->iface, fp->altsetting, format); | 2249 | chip->dev->devnum, fp->iface, fp->altsetting, format); |
2277 | break; | 2250 | break; |
2278 | } | 2251 | } |
2279 | return pcm_format; | 2252 | return pcm_format; |
@@ -2290,13 +2263,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 | 2263 | * @offset: the start offset of descriptor pointing the rate type |
2291 | * (7 for type I and II, 8 for type II) | 2264 | * (7 for type I and II, 8 for type II) |
2292 | */ | 2265 | */ |
2293 | static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *fp, | 2266 | static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *fp, |
2294 | unsigned char *fmt, int offset) | 2267 | unsigned char *fmt, int offset) |
2295 | { | 2268 | { |
2296 | int nr_rates = fmt[offset]; | 2269 | int nr_rates = fmt[offset]; |
2297 | if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { | 2270 | if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { |
2298 | snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", | 2271 | snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", |
2299 | dev->devnum, fp->iface, fp->altsetting); | 2272 | chip->dev->devnum, fp->iface, fp->altsetting); |
2300 | return -1; | 2273 | return -1; |
2301 | } | 2274 | } |
2302 | 2275 | ||
@@ -2343,7 +2316,7 @@ static int parse_audio_format_rates(struct usb_device *dev, struct audioformat * | |||
2343 | /* | 2316 | /* |
2344 | * parse the format type I and III descriptors | 2317 | * parse the format type I and III descriptors |
2345 | */ | 2318 | */ |
2346 | static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp, | 2319 | static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp, |
2347 | int format, unsigned char *fmt) | 2320 | int format, unsigned char *fmt) |
2348 | { | 2321 | { |
2349 | int pcm_format; | 2322 | int pcm_format; |
@@ -2355,7 +2328,7 @@ static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp, | |||
2355 | */ | 2328 | */ |
2356 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; | 2329 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; |
2357 | } else { | 2330 | } else { |
2358 | pcm_format = parse_audio_format_i_type(dev, fp, format, fmt); | 2331 | pcm_format = parse_audio_format_i_type(chip, fp, format, fmt); |
2359 | if (pcm_format < 0) | 2332 | if (pcm_format < 0) |
2360 | return -1; | 2333 | return -1; |
2361 | } | 2334 | } |
@@ -2363,16 +2336,16 @@ static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp, | |||
2363 | fp->channels = fmt[4]; | 2336 | fp->channels = fmt[4]; |
2364 | if (fp->channels < 1) { | 2337 | if (fp->channels < 1) { |
2365 | snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", | 2338 | snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", |
2366 | dev->devnum, fp->iface, fp->altsetting, fp->channels); | 2339 | chip->dev->devnum, fp->iface, fp->altsetting, fp->channels); |
2367 | return -1; | 2340 | return -1; |
2368 | } | 2341 | } |
2369 | return parse_audio_format_rates(dev, fp, fmt, 7); | 2342 | return parse_audio_format_rates(chip, fp, fmt, 7); |
2370 | } | 2343 | } |
2371 | 2344 | ||
2372 | /* | 2345 | /* |
2373 | * prase the format type II descriptor | 2346 | * prase the format type II descriptor |
2374 | */ | 2347 | */ |
2375 | static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp, | 2348 | static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp, |
2376 | int format, unsigned char *fmt) | 2349 | int format, unsigned char *fmt) |
2377 | { | 2350 | { |
2378 | int brate, framesize; | 2351 | int brate, framesize; |
@@ -2387,7 +2360,7 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp, | |||
2387 | break; | 2360 | break; |
2388 | default: | 2361 | default: |
2389 | snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected. processed as MPEG.\n", | 2362 | 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); | 2363 | chip->dev->devnum, fp->iface, fp->altsetting, format); |
2391 | fp->format = SNDRV_PCM_FORMAT_MPEG; | 2364 | fp->format = SNDRV_PCM_FORMAT_MPEG; |
2392 | break; | 2365 | break; |
2393 | } | 2366 | } |
@@ -2396,10 +2369,10 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp, | |||
2396 | framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */ | 2369 | 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); | 2370 | snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); |
2398 | fp->frame_size = framesize; | 2371 | fp->frame_size = framesize; |
2399 | return parse_audio_format_rates(dev, fp, fmt, 8); /* fmt[8..] sample rates */ | 2372 | return parse_audio_format_rates(chip, fp, fmt, 8); /* fmt[8..] sample rates */ |
2400 | } | 2373 | } |
2401 | 2374 | ||
2402 | static int parse_audio_format(struct usb_device *dev, struct audioformat *fp, | 2375 | static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp, |
2403 | int format, unsigned char *fmt, int stream) | 2376 | int format, unsigned char *fmt, int stream) |
2404 | { | 2377 | { |
2405 | int err; | 2378 | int err; |
@@ -2407,29 +2380,30 @@ static int parse_audio_format(struct usb_device *dev, struct audioformat *fp, | |||
2407 | switch (fmt[3]) { | 2380 | switch (fmt[3]) { |
2408 | case USB_FORMAT_TYPE_I: | 2381 | case USB_FORMAT_TYPE_I: |
2409 | case USB_FORMAT_TYPE_III: | 2382 | case USB_FORMAT_TYPE_III: |
2410 | err = parse_audio_format_i(dev, fp, format, fmt); | 2383 | err = parse_audio_format_i(chip, fp, format, fmt); |
2411 | break; | 2384 | break; |
2412 | case USB_FORMAT_TYPE_II: | 2385 | case USB_FORMAT_TYPE_II: |
2413 | err = parse_audio_format_ii(dev, fp, format, fmt); | 2386 | err = parse_audio_format_ii(chip, fp, format, fmt); |
2414 | break; | 2387 | break; |
2415 | default: | 2388 | default: |
2416 | snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", | 2389 | snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", |
2417 | dev->devnum, fp->iface, fp->altsetting, fmt[3]); | 2390 | chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]); |
2418 | return -1; | 2391 | return -1; |
2419 | } | 2392 | } |
2420 | fp->fmt_type = fmt[3]; | 2393 | fp->fmt_type = fmt[3]; |
2421 | if (err < 0) | 2394 | if (err < 0) |
2422 | return err; | 2395 | return err; |
2423 | #if 1 | 2396 | #if 1 |
2424 | /* FIXME: temporary hack for extigy */ | 2397 | /* FIXME: temporary hack for extigy/audigy 2 nx */ |
2425 | /* extigy apparently supports sample rates other than 48k | 2398 | /* extigy apparently supports sample rates other than 48k |
2426 | * but not in ordinary way. so we enable only 48k atm. | 2399 | * but not in ordinary way. so we enable only 48k atm. |
2427 | */ | 2400 | */ |
2428 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && | 2401 | if (chip->usb_id == USB_ID(0x041e, 0x3000) || |
2429 | le16_to_cpu(dev->descriptor.idProduct) == 0x3000) { | 2402 | chip->usb_id == USB_ID(0x041e, 0x3020)) { |
2430 | if (fmt[3] == USB_FORMAT_TYPE_I && | 2403 | if (fmt[3] == USB_FORMAT_TYPE_I && |
2431 | stream == SNDRV_PCM_STREAM_PLAYBACK && | 2404 | stream == SNDRV_PCM_STREAM_PLAYBACK && |
2432 | fp->rates != SNDRV_PCM_RATE_48000) | 2405 | fp->rates != SNDRV_PCM_RATE_48000 && |
2406 | fp->rates != SNDRV_PCM_RATE_96000) | ||
2433 | return -1; /* use 48k only */ | 2407 | return -1; /* use 48k only */ |
2434 | } | 2408 | } |
2435 | #endif | 2409 | #endif |
@@ -2528,40 +2502,35 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) | |||
2528 | 2502 | ||
2529 | /* some quirks for attributes here */ | 2503 | /* some quirks for attributes here */ |
2530 | 2504 | ||
2531 | /* workaround for AudioTrak Optoplay */ | 2505 | switch (chip->usb_id) { |
2532 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x0a92 && | 2506 | case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */ |
2533 | le16_to_cpu(dev->descriptor.idProduct) == 0x0053) { | ||
2534 | /* Optoplay sets the sample rate attribute although | 2507 | /* Optoplay sets the sample rate attribute although |
2535 | * it seems not supporting it in fact. | 2508 | * it seems not supporting it in fact. |
2536 | */ | 2509 | */ |
2537 | fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE; | 2510 | fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE; |
2538 | } | 2511 | break; |
2539 | 2512 | case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */ | |
2540 | /* workaround for M-Audio Audiophile USB */ | 2513 | 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 */ | 2514 | /* doesn't set the sample rate attribute, but supports it */ |
2544 | fp->attributes |= EP_CS_ATTR_SAMPLE_RATE; | 2515 | fp->attributes |= EP_CS_ATTR_SAMPLE_RATE; |
2545 | } | 2516 | break; |
2546 | 2517 | case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ | |
2518 | case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is | ||
2519 | an older model 77d:223) */ | ||
2547 | /* | 2520 | /* |
2548 | * plantronics headset and Griffin iMic have set adaptive-in | 2521 | * plantronics headset and Griffin iMic have set adaptive-in |
2549 | * although it's really not... | 2522 | * although it's really not... |
2550 | */ | 2523 | */ |
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; | 2524 | fp->ep_attr &= ~EP_ATTR_MASK; |
2557 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | 2525 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) |
2558 | fp->ep_attr |= EP_ATTR_ADAPTIVE; | 2526 | fp->ep_attr |= EP_ATTR_ADAPTIVE; |
2559 | else | 2527 | else |
2560 | fp->ep_attr |= EP_ATTR_SYNC; | 2528 | fp->ep_attr |= EP_ATTR_SYNC; |
2529 | break; | ||
2561 | } | 2530 | } |
2562 | 2531 | ||
2563 | /* ok, let's parse further... */ | 2532 | /* ok, let's parse further... */ |
2564 | if (parse_audio_format(dev, fp, format, fmt, stream) < 0) { | 2533 | if (parse_audio_format(chip, fp, format, fmt, stream) < 0) { |
2565 | kfree(fp->rate_table); | 2534 | kfree(fp->rate_table); |
2566 | kfree(fp); | 2535 | kfree(fp); |
2567 | continue; | 2536 | continue; |
@@ -2587,7 +2556,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) | |||
2587 | * disconnect streams | 2556 | * disconnect streams |
2588 | * called from snd_usb_audio_disconnect() | 2557 | * called from snd_usb_audio_disconnect() |
2589 | */ | 2558 | */ |
2590 | static void snd_usb_stream_disconnect(struct list_head *head, struct usb_driver *driver) | 2559 | static void snd_usb_stream_disconnect(struct list_head *head) |
2591 | { | 2560 | { |
2592 | int idx; | 2561 | int idx; |
2593 | snd_usb_stream_t *as; | 2562 | snd_usb_stream_t *as; |
@@ -2796,7 +2765,7 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, | |||
2796 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 2765 | .type = QUIRK_MIDI_FIXED_ENDPOINT, |
2797 | .data = &ua25_ep | 2766 | .data = &ua25_ep |
2798 | }; | 2767 | }; |
2799 | if (le16_to_cpu(chip->dev->descriptor.idProduct) == 0x002b) | 2768 | if (chip->usb_id == USB_ID(0x0582, 0x002b)) |
2800 | return snd_usb_create_midi_interface(chip, iface, | 2769 | return snd_usb_create_midi_interface(chip, iface, |
2801 | &ua700_quirk); | 2770 | &ua700_quirk); |
2802 | else | 2771 | else |
@@ -2959,6 +2928,25 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac | |||
2959 | return 0; | 2928 | return 0; |
2960 | } | 2929 | } |
2961 | 2930 | ||
2931 | static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) | ||
2932 | { | ||
2933 | #if 0 | ||
2934 | /* TODO: enable this when high speed synchronization actually works */ | ||
2935 | u8 buf = 1; | ||
2936 | |||
2937 | snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a, | ||
2938 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
2939 | 0, 0, &buf, 1, 1000); | ||
2940 | if (buf == 0) { | ||
2941 | snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29, | ||
2942 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
2943 | 1, 2000, NULL, 0, 1000); | ||
2944 | return -ENODEV; | ||
2945 | } | ||
2946 | #endif | ||
2947 | return 0; | ||
2948 | } | ||
2949 | |||
2962 | 2950 | ||
2963 | /* | 2951 | /* |
2964 | * audio-interface quirks | 2952 | * audio-interface quirks |
@@ -3015,8 +3003,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; | 3003 | snd_usb_audio_t *chip = entry->private_data; |
3016 | if (! chip->shutdown) | 3004 | if (! chip->shutdown) |
3017 | snd_iprintf(buffer, "%04x:%04x\n", | 3005 | snd_iprintf(buffer, "%04x:%04x\n", |
3018 | le16_to_cpu(chip->dev->descriptor.idVendor), | 3006 | USB_ID_VENDOR(chip->usb_id), |
3019 | le16_to_cpu(chip->dev->descriptor.idProduct)); | 3007 | USB_ID_PRODUCT(chip->usb_id)); |
3020 | } | 3008 | } |
3021 | 3009 | ||
3022 | static void snd_usb_audio_create_proc(snd_usb_audio_t *chip) | 3010 | static void snd_usb_audio_create_proc(snd_usb_audio_t *chip) |
@@ -3086,8 +3074,11 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3086 | chip->index = idx; | 3074 | chip->index = idx; |
3087 | chip->dev = dev; | 3075 | chip->dev = dev; |
3088 | chip->card = card; | 3076 | chip->card = card; |
3077 | chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), | ||
3078 | le16_to_cpu(dev->descriptor.idProduct)); | ||
3089 | INIT_LIST_HEAD(&chip->pcm_list); | 3079 | INIT_LIST_HEAD(&chip->pcm_list); |
3090 | INIT_LIST_HEAD(&chip->midi_list); | 3080 | INIT_LIST_HEAD(&chip->midi_list); |
3081 | INIT_LIST_HEAD(&chip->mixer_list); | ||
3091 | 3082 | ||
3092 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 3083 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { |
3093 | snd_usb_audio_free(chip); | 3084 | snd_usb_audio_free(chip); |
@@ -3097,8 +3088,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3097 | 3088 | ||
3098 | strcpy(card->driver, "USB-Audio"); | 3089 | strcpy(card->driver, "USB-Audio"); |
3099 | sprintf(component, "USB%04x:%04x", | 3090 | sprintf(component, "USB%04x:%04x", |
3100 | le16_to_cpu(dev->descriptor.idVendor), | 3091 | 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); | 3092 | snd_component_add(card, component); |
3103 | 3093 | ||
3104 | /* retrieve the device string as shortname */ | 3094 | /* retrieve the device string as shortname */ |
@@ -3110,8 +3100,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3110 | card->shortname, sizeof(card->shortname)) <= 0) { | 3100 | card->shortname, sizeof(card->shortname)) <= 0) { |
3111 | /* no name available from anywhere, so use ID */ | 3101 | /* no name available from anywhere, so use ID */ |
3112 | sprintf(card->shortname, "USB Device %#04x:%#04x", | 3102 | sprintf(card->shortname, "USB Device %#04x:%#04x", |
3113 | le16_to_cpu(dev->descriptor.idVendor), | 3103 | USB_ID_VENDOR(chip->usb_id), |
3114 | le16_to_cpu(dev->descriptor.idProduct)); | 3104 | USB_ID_PRODUCT(chip->usb_id)); |
3115 | } | 3105 | } |
3116 | } | 3106 | } |
3117 | 3107 | ||
@@ -3142,8 +3132,6 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3142 | 3132 | ||
3143 | snd_usb_audio_create_proc(chip); | 3133 | snd_usb_audio_create_proc(chip); |
3144 | 3134 | ||
3145 | snd_card_set_dev(card, &dev->dev); | ||
3146 | |||
3147 | *rchip = chip; | 3135 | *rchip = chip; |
3148 | return 0; | 3136 | return 0; |
3149 | } | 3137 | } |
@@ -3169,21 +3157,28 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
3169 | snd_usb_audio_t *chip; | 3157 | snd_usb_audio_t *chip; |
3170 | struct usb_host_interface *alts; | 3158 | struct usb_host_interface *alts; |
3171 | int ifnum; | 3159 | int ifnum; |
3160 | u32 id; | ||
3172 | 3161 | ||
3173 | alts = &intf->altsetting[0]; | 3162 | alts = &intf->altsetting[0]; |
3174 | ifnum = get_iface_desc(alts)->bInterfaceNumber; | 3163 | ifnum = get_iface_desc(alts)->bInterfaceNumber; |
3164 | id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), | ||
3165 | le16_to_cpu(dev->descriptor.idProduct)); | ||
3175 | 3166 | ||
3176 | if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) | 3167 | if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) |
3177 | goto __err_val; | 3168 | goto __err_val; |
3178 | 3169 | ||
3179 | /* SB Extigy needs special boot-up sequence */ | 3170 | /* SB Extigy needs special boot-up sequence */ |
3180 | /* if more models come, this will go to the quirk list. */ | 3171 | /* if more models come, this will go to the quirk list. */ |
3181 | if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && | 3172 | if (id == USB_ID(0x041e, 0x3000)) { |
3182 | le16_to_cpu(dev->descriptor.idProduct) == 0x3000) { | ||
3183 | if (snd_usb_extigy_boot_quirk(dev, intf) < 0) | 3173 | if (snd_usb_extigy_boot_quirk(dev, intf) < 0) |
3184 | goto __err_val; | 3174 | goto __err_val; |
3185 | config = dev->actconfig; | 3175 | config = dev->actconfig; |
3186 | } | 3176 | } |
3177 | /* SB Audigy 2 NX needs its own boot-up magic, too */ | ||
3178 | if (id == USB_ID(0x041e, 0x3020)) { | ||
3179 | if (snd_usb_audigy2nx_boot_quirk(dev) < 0) | ||
3180 | goto __err_val; | ||
3181 | } | ||
3187 | 3182 | ||
3188 | /* | 3183 | /* |
3189 | * found a config. now register to ALSA | 3184 | * found a config. now register to ALSA |
@@ -3213,11 +3208,12 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
3213 | } | 3208 | } |
3214 | for (i = 0; i < SNDRV_CARDS; i++) | 3209 | for (i = 0; i < SNDRV_CARDS; i++) |
3215 | if (enable[i] && ! usb_chip[i] && | 3210 | if (enable[i] && ! usb_chip[i] && |
3216 | (vid[i] == -1 || vid[i] == le16_to_cpu(dev->descriptor.idVendor)) && | 3211 | (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) && |
3217 | (pid[i] == -1 || pid[i] == le16_to_cpu(dev->descriptor.idProduct))) { | 3212 | (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) { |
3218 | if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) { | 3213 | if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) { |
3219 | goto __error; | 3214 | goto __error; |
3220 | } | 3215 | } |
3216 | snd_card_set_dev(chip->card, &intf->dev); | ||
3221 | break; | 3217 | break; |
3222 | } | 3218 | } |
3223 | if (! chip) { | 3219 | if (! chip) { |
@@ -3281,11 +3277,15 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) | |||
3281 | snd_card_disconnect(card); | 3277 | snd_card_disconnect(card); |
3282 | /* release the pcm resources */ | 3278 | /* release the pcm resources */ |
3283 | list_for_each(p, &chip->pcm_list) { | 3279 | list_for_each(p, &chip->pcm_list) { |
3284 | snd_usb_stream_disconnect(p, &usb_audio_driver); | 3280 | snd_usb_stream_disconnect(p); |
3285 | } | 3281 | } |
3286 | /* release the midi resources */ | 3282 | /* release the midi resources */ |
3287 | list_for_each(p, &chip->midi_list) { | 3283 | list_for_each(p, &chip->midi_list) { |
3288 | snd_usbmidi_disconnect(p, &usb_audio_driver); | 3284 | snd_usbmidi_disconnect(p); |
3285 | } | ||
3286 | /* release mixer resources */ | ||
3287 | list_for_each(p, &chip->mixer_list) { | ||
3288 | snd_usb_mixer_disconnect(p); | ||
3289 | } | 3289 | } |
3290 | usb_chip[chip->index] = NULL; | 3290 | usb_chip[chip->index] = NULL; |
3291 | up(®ister_mutex); | 3291 | up(®ister_mutex); |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index eecbf19fcb6f..aedb42aaa749 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 | /* |
@@ -219,11 +225,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); | 225 | 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 | 226 | ||
221 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif); | 227 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif); |
228 | void snd_usb_mixer_disconnect(struct list_head *p); | ||
222 | 229 | ||
223 | int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk); | 230 | 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); | 231 | void snd_usbmidi_input_stop(struct list_head* p); |
225 | void snd_usbmidi_input_start(struct list_head* p); | 232 | void snd_usbmidi_input_start(struct list_head* p); |
226 | void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver); | 233 | void snd_usbmidi_disconnect(struct list_head *p); |
227 | 234 | ||
228 | /* | 235 | /* |
229 | * retrieve usb_interface descriptor from the host interface | 236 | * retrieve usb_interface descriptor from the host interface |
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 5d32857ff955..bee70068dce0 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c | |||
@@ -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; |
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 5f1906915aa6..83ba665e5c6e 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 | ||
@@ -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 | ||
@@ -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 | ||
@@ -608,7 +659,8 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min) | |||
608 | } | 659 | } |
609 | if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || | 660 | 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) { | 661 | 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); | 662 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", |
663 | cval->id, cval->mixer->ctrlif, cval->control, cval->id); | ||
612 | return -EINVAL; | 664 | return -EINVAL; |
613 | } | 665 | } |
614 | if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { | 666 | if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { |
@@ -668,7 +720,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
668 | if (cval->cmask & (1 << c)) { | 720 | if (cval->cmask & (1 << c)) { |
669 | err = get_cur_mix_value(cval, c + 1, &val); | 721 | err = get_cur_mix_value(cval, c + 1, &val); |
670 | if (err < 0) { | 722 | if (err < 0) { |
671 | if (cval->chip->ignore_ctl_error) { | 723 | if (cval->mixer->ignore_ctl_error) { |
672 | ucontrol->value.integer.value[0] = cval->min; | 724 | ucontrol->value.integer.value[0] = cval->min; |
673 | return 0; | 725 | return 0; |
674 | } | 726 | } |
@@ -684,7 +736,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
684 | /* master channel */ | 736 | /* master channel */ |
685 | err = get_cur_mix_value(cval, 0, &val); | 737 | err = get_cur_mix_value(cval, 0, &val); |
686 | if (err < 0) { | 738 | if (err < 0) { |
687 | if (cval->chip->ignore_ctl_error) { | 739 | if (cval->mixer->ignore_ctl_error) { |
688 | ucontrol->value.integer.value[0] = cval->min; | 740 | ucontrol->value.integer.value[0] = cval->min; |
689 | return 0; | 741 | return 0; |
690 | } | 742 | } |
@@ -710,7 +762,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
710 | if (cval->cmask & (1 << c)) { | 762 | if (cval->cmask & (1 << c)) { |
711 | err = get_cur_mix_value(cval, c + 1, &oval); | 763 | err = get_cur_mix_value(cval, c + 1, &oval); |
712 | if (err < 0) { | 764 | if (err < 0) { |
713 | if (cval->chip->ignore_ctl_error) | 765 | if (cval->mixer->ignore_ctl_error) |
714 | return 0; | 766 | return 0; |
715 | return err; | 767 | return err; |
716 | } | 768 | } |
@@ -727,7 +779,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
727 | } else { | 779 | } else { |
728 | /* master channel */ | 780 | /* master channel */ |
729 | err = get_cur_mix_value(cval, 0, &oval); | 781 | err = get_cur_mix_value(cval, 0, &oval); |
730 | if (err < 0 && cval->chip->ignore_ctl_error) | 782 | if (err < 0 && cval->mixer->ignore_ctl_error) |
731 | return 0; | 783 | return 0; |
732 | if (err < 0) | 784 | if (err < 0) |
733 | return err; | 785 | return err; |
@@ -779,8 +831,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, | |||
779 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 831 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
780 | return; | 832 | return; |
781 | } | 833 | } |
782 | cval->chip = state->chip; | 834 | cval->mixer = state->mixer; |
783 | cval->ctrlif = state->ctrlif; | ||
784 | cval->id = unitid; | 835 | cval->id = unitid; |
785 | cval->control = control; | 836 | cval->control = control; |
786 | cval->cmask = ctl_mask; | 837 | cval->cmask = ctl_mask; |
@@ -855,16 +906,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 */ | 906 | /* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */ |
856 | /* is not very clear from datasheets */ | 907 | /* is not very clear from datasheets */ |
857 | /* I hope that the min value is -15360 for newer firmware --jk */ | 908 | /* 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)) || | 909 | switch (state->chip->usb_id) { |
859 | (state->vendor == 0x672 && state->product == 0x1041)) && !strcmp(kctl->id.name, "PCM Playback Volume") && | 910 | case USB_ID(0x0471, 0x0101): |
860 | cval->min == -15616) { | 911 | case USB_ID(0x0471, 0x0104): |
861 | snd_printk("USB Audio: using volume control quirk for the UDA1321/N101 chip\n"); | 912 | case USB_ID(0x0471, 0x0105): |
862 | cval->max = -256; | 913 | case USB_ID(0x0672, 0x1041): |
914 | if (!strcmp(kctl->id.name, "PCM Playback Volume") && | ||
915 | cval->min == -15616) { | ||
916 | snd_printk("using volume control quirk for the UDA1321/N101 chip\n"); | ||
917 | cval->max = -256; | ||
918 | } | ||
863 | } | 919 | } |
864 | 920 | ||
865 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 921 | 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); | 922 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); |
867 | add_control_to_empty(state->chip->card, kctl); | 923 | add_control_to_empty(state, kctl); |
868 | } | 924 | } |
869 | 925 | ||
870 | 926 | ||
@@ -947,8 +1003,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, | |||
947 | if (! cval) | 1003 | if (! cval) |
948 | return; | 1004 | return; |
949 | 1005 | ||
950 | cval->chip = state->chip; | 1006 | cval->mixer = state->mixer; |
951 | cval->ctrlif = state->ctrlif; | ||
952 | cval->id = unitid; | 1007 | cval->id = unitid; |
953 | cval->control = in_ch + 1; /* based on 1 */ | 1008 | cval->control = in_ch + 1; /* based on 1 */ |
954 | cval->val_type = USB_MIXER_S16; | 1009 | cval->val_type = USB_MIXER_S16; |
@@ -979,7 +1034,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, | |||
979 | 1034 | ||
980 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", | 1035 | 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); | 1036 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
982 | add_control_to_empty(state->chip->card, kctl); | 1037 | add_control_to_empty(state, kctl); |
983 | } | 1038 | } |
984 | 1039 | ||
985 | 1040 | ||
@@ -1042,7 +1097,7 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1042 | int err, val; | 1097 | int err, val; |
1043 | 1098 | ||
1044 | err = get_cur_ctl_value(cval, cval->control << 8, &val); | 1099 | err = get_cur_ctl_value(cval, cval->control << 8, &val); |
1045 | if (err < 0 && cval->chip->ignore_ctl_error) { | 1100 | if (err < 0 && cval->mixer->ignore_ctl_error) { |
1046 | ucontrol->value.integer.value[0] = cval->min; | 1101 | ucontrol->value.integer.value[0] = cval->min; |
1047 | return 0; | 1102 | return 0; |
1048 | } | 1103 | } |
@@ -1061,7 +1116,7 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1061 | 1116 | ||
1062 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); | 1117 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); |
1063 | if (err < 0) { | 1118 | if (err < 0) { |
1064 | if (cval->chip->ignore_ctl_error) | 1119 | if (cval->mixer->ignore_ctl_error) |
1065 | return 0; | 1120 | return 0; |
1066 | return err; | 1121 | return err; |
1067 | } | 1122 | } |
@@ -1179,9 +1234,6 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1179 | } | 1234 | } |
1180 | 1235 | ||
1181 | type = combine_word(&dsc[4]); | 1236 | type = combine_word(&dsc[4]); |
1182 | if (! type) | ||
1183 | return 0; /* undefined? */ | ||
1184 | |||
1185 | for (info = list; info && info->type; info++) | 1237 | for (info = list; info && info->type; info++) |
1186 | if (info->type == type) | 1238 | if (info->type == type) |
1187 | break; | 1239 | break; |
@@ -1199,8 +1251,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1199 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1251 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1200 | return -ENOMEM; | 1252 | return -ENOMEM; |
1201 | } | 1253 | } |
1202 | cval->chip = state->chip; | 1254 | cval->mixer = state->mixer; |
1203 | cval->ctrlif = state->ctrlif; | ||
1204 | cval->id = unitid; | 1255 | cval->id = unitid; |
1205 | cval->control = valinfo->control; | 1256 | cval->control = valinfo->control; |
1206 | cval->val_type = valinfo->val_type; | 1257 | cval->val_type = valinfo->val_type; |
@@ -1241,7 +1292,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1241 | 1292 | ||
1242 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", | 1293 | 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); | 1294 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
1244 | if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) | 1295 | if ((err = add_control_to_empty(state, kctl)) < 0) |
1245 | return err; | 1296 | return err; |
1246 | } | 1297 | } |
1247 | return 0; | 1298 | return 0; |
@@ -1289,7 +1340,7 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1289 | 1340 | ||
1290 | err = get_cur_ctl_value(cval, 0, &val); | 1341 | err = get_cur_ctl_value(cval, 0, &val); |
1291 | if (err < 0) { | 1342 | if (err < 0) { |
1292 | if (cval->chip->ignore_ctl_error) { | 1343 | if (cval->mixer->ignore_ctl_error) { |
1293 | ucontrol->value.enumerated.item[0] = 0; | 1344 | ucontrol->value.enumerated.item[0] = 0; |
1294 | return 0; | 1345 | return 0; |
1295 | } | 1346 | } |
@@ -1308,7 +1359,7 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1308 | 1359 | ||
1309 | err = get_cur_ctl_value(cval, 0, &oval); | 1360 | err = get_cur_ctl_value(cval, 0, &oval); |
1310 | if (err < 0) { | 1361 | if (err < 0) { |
1311 | if (cval->chip->ignore_ctl_error) | 1362 | if (cval->mixer->ignore_ctl_error) |
1312 | return 0; | 1363 | return 0; |
1313 | return err; | 1364 | return err; |
1314 | } | 1365 | } |
@@ -1386,8 +1437,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1386 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1437 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1387 | return -ENOMEM; | 1438 | return -ENOMEM; |
1388 | } | 1439 | } |
1389 | cval->chip = state->chip; | 1440 | cval->mixer = state->mixer; |
1390 | cval->ctrlif = state->ctrlif; | ||
1391 | cval->id = unitid; | 1441 | cval->id = unitid; |
1392 | cval->val_type = USB_MIXER_U8; | 1442 | cval->val_type = USB_MIXER_U8; |
1393 | cval->channels = 1; | 1443 | cval->channels = 1; |
@@ -1415,7 +1465,9 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1415 | kfree(cval); | 1465 | kfree(cval); |
1416 | return -ENOMEM; | 1466 | return -ENOMEM; |
1417 | } | 1467 | } |
1418 | if (check_input_term(state, desc[5 + i], &iterm) >= 0) | 1468 | len = check_mapped_selector_name(state, unitid, i, namelist[i], |
1469 | MAX_ITEM_NAME_LEN); | ||
1470 | 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); | 1471 | len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); |
1420 | if (! len) | 1472 | if (! len) |
1421 | sprintf(namelist[i], "Input %d", i); | 1473 | sprintf(namelist[i], "Input %d", i); |
@@ -1450,7 +1502,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1450 | 1502 | ||
1451 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", | 1503 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", |
1452 | cval->id, kctl->id.name, num_ins); | 1504 | cval->id, kctl->id.name, num_ins); |
1453 | if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) | 1505 | if ((err = add_control_to_empty(state, kctl)) < 0) |
1454 | return err; | 1506 | return err; |
1455 | 1507 | ||
1456 | return 0; | 1508 | return 0; |
@@ -1493,41 +1545,55 @@ static int parse_audio_unit(mixer_build_t *state, int unitid) | |||
1493 | } | 1545 | } |
1494 | } | 1546 | } |
1495 | 1547 | ||
1548 | static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) | ||
1549 | { | ||
1550 | kfree(mixer->id_elems); | ||
1551 | if (mixer->urb) { | ||
1552 | kfree(mixer->urb->transfer_buffer); | ||
1553 | usb_free_urb(mixer->urb); | ||
1554 | } | ||
1555 | if (mixer->rc_urb) | ||
1556 | usb_free_urb(mixer->rc_urb); | ||
1557 | kfree(mixer->rc_setup_packet); | ||
1558 | kfree(mixer); | ||
1559 | } | ||
1560 | |||
1561 | static int snd_usb_mixer_dev_free(snd_device_t *device) | ||
1562 | { | ||
1563 | struct usb_mixer_interface *mixer = device->device_data; | ||
1564 | snd_usb_mixer_free(mixer); | ||
1565 | return 0; | ||
1566 | } | ||
1567 | |||
1496 | /* | 1568 | /* |
1497 | * create mixer controls | 1569 | * create mixer controls |
1498 | * | 1570 | * |
1499 | * walk through all OUTPUT_TERMINAL descriptors to search for mixers | 1571 | * walk through all OUTPUT_TERMINAL descriptors to search for mixers |
1500 | */ | 1572 | */ |
1501 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | 1573 | static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) |
1502 | { | 1574 | { |
1503 | unsigned char *desc; | 1575 | unsigned char *desc; |
1504 | mixer_build_t state; | 1576 | mixer_build_t state; |
1505 | int err; | 1577 | int err; |
1506 | const struct usbmix_ctl_map *map; | 1578 | const struct usbmix_ctl_map *map; |
1507 | struct usb_device_descriptor *dev = &chip->dev->descriptor; | 1579 | 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 | 1580 | ||
1581 | hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; | ||
1512 | memset(&state, 0, sizeof(state)); | 1582 | memset(&state, 0, sizeof(state)); |
1513 | state.chip = chip; | 1583 | state.chip = mixer->chip; |
1584 | state.mixer = mixer; | ||
1514 | state.buffer = hostif->extra; | 1585 | state.buffer = hostif->extra; |
1515 | state.buflen = hostif->extralen; | 1586 | 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 | 1587 | ||
1520 | /* check the mapping table */ | 1588 | /* check the mapping table */ |
1521 | for (map = usbmix_ctl_maps; map->vendor; map++) { | 1589 | for (map = usbmix_ctl_maps; map->id; map++) { |
1522 | if (map->vendor == state.vendor && map->product == state.product) { | 1590 | if (map->id == state.chip->usb_id) { |
1523 | state.map = map->map; | 1591 | state.map = map->map; |
1524 | chip->ignore_ctl_error = map->ignore_ctl_error; | 1592 | state.selector_map = map->selector_map; |
1593 | mixer->ignore_ctl_error = map->ignore_ctl_error; | ||
1525 | break; | 1594 | break; |
1526 | } | 1595 | } |
1527 | } | 1596 | } |
1528 | #ifdef IGNORE_CTL_ERROR | ||
1529 | chip->ignore_ctl_error = 1; | ||
1530 | #endif | ||
1531 | 1597 | ||
1532 | desc = NULL; | 1598 | desc = NULL; |
1533 | while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { | 1599 | while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { |
@@ -1543,3 +1609,393 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | |||
1543 | } | 1609 | } |
1544 | return 0; | 1610 | return 0; |
1545 | } | 1611 | } |
1612 | |||
1613 | static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, | ||
1614 | int unitid) | ||
1615 | { | ||
1616 | usb_mixer_elem_info_t *info; | ||
1617 | |||
1618 | for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) | ||
1619 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1620 | info->elem_id); | ||
1621 | } | ||
1622 | |||
1623 | static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, | ||
1624 | int unitid) | ||
1625 | { | ||
1626 | if (mixer->rc_type == RC_NONE) | ||
1627 | return; | ||
1628 | /* unit ids specific to Extigy/Audigy 2 NX: */ | ||
1629 | switch (unitid) { | ||
1630 | case 0: /* remote control */ | ||
1631 | mixer->rc_urb->dev = mixer->chip->dev; | ||
1632 | usb_submit_urb(mixer->rc_urb, GFP_ATOMIC); | ||
1633 | break; | ||
1634 | case 4: /* digital in jack */ | ||
1635 | case 7: /* line in jacks */ | ||
1636 | case 19: /* speaker out jacks */ | ||
1637 | case 20: /* headphones out jack */ | ||
1638 | break; | ||
1639 | default: | ||
1640 | snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid); | ||
1641 | break; | ||
1642 | } | ||
1643 | } | ||
1644 | |||
1645 | static void snd_usb_mixer_status_complete(struct urb *urb, struct pt_regs *regs) | ||
1646 | { | ||
1647 | struct usb_mixer_interface *mixer = urb->context; | ||
1648 | |||
1649 | if (urb->status == 0) { | ||
1650 | u8 *buf = urb->transfer_buffer; | ||
1651 | int i; | ||
1652 | |||
1653 | for (i = urb->actual_length; i >= 2; buf += 2, i -= 2) { | ||
1654 | snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n", | ||
1655 | buf[0], buf[1]); | ||
1656 | /* ignore any notifications not from the control interface */ | ||
1657 | if ((buf[0] & 0x0f) != 0) | ||
1658 | continue; | ||
1659 | if (!(buf[0] & 0x40)) | ||
1660 | snd_usb_mixer_notify_id(mixer, buf[1]); | ||
1661 | else | ||
1662 | snd_usb_mixer_memory_change(mixer, buf[1]); | ||
1663 | } | ||
1664 | } | ||
1665 | if (urb->status != -ENOENT && urb->status != -ECONNRESET) { | ||
1666 | urb->dev = mixer->chip->dev; | ||
1667 | usb_submit_urb(urb, GFP_ATOMIC); | ||
1668 | } | ||
1669 | } | ||
1670 | |||
1671 | /* create the handler for the optional status interrupt endpoint */ | ||
1672 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) | ||
1673 | { | ||
1674 | struct usb_host_interface *hostif; | ||
1675 | struct usb_endpoint_descriptor *ep; | ||
1676 | void *transfer_buffer; | ||
1677 | int buffer_length; | ||
1678 | unsigned int epnum; | ||
1679 | |||
1680 | hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; | ||
1681 | /* we need one interrupt input endpoint */ | ||
1682 | if (get_iface_desc(hostif)->bNumEndpoints < 1) | ||
1683 | return 0; | ||
1684 | ep = get_endpoint(hostif, 0); | ||
1685 | if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN || | ||
1686 | (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) | ||
1687 | return 0; | ||
1688 | |||
1689 | epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | ||
1690 | buffer_length = le16_to_cpu(ep->wMaxPacketSize); | ||
1691 | transfer_buffer = kmalloc(buffer_length, GFP_KERNEL); | ||
1692 | if (!transfer_buffer) | ||
1693 | return -ENOMEM; | ||
1694 | mixer->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1695 | if (!mixer->urb) { | ||
1696 | kfree(transfer_buffer); | ||
1697 | return -ENOMEM; | ||
1698 | } | ||
1699 | usb_fill_int_urb(mixer->urb, mixer->chip->dev, | ||
1700 | usb_rcvintpipe(mixer->chip->dev, epnum), | ||
1701 | transfer_buffer, buffer_length, | ||
1702 | snd_usb_mixer_status_complete, mixer, ep->bInterval); | ||
1703 | usb_submit_urb(mixer->urb, GFP_KERNEL); | ||
1704 | return 0; | ||
1705 | } | ||
1706 | |||
1707 | static void snd_usb_soundblaster_remote_complete(struct urb *urb, | ||
1708 | struct pt_regs *regs) | ||
1709 | { | ||
1710 | struct usb_mixer_interface *mixer = urb->context; | ||
1711 | /* | ||
1712 | * format of remote control data: | ||
1713 | * Extigy: xx 00 | ||
1714 | * Audigy 2 NX: 06 80 xx 00 00 00 | ||
1715 | */ | ||
1716 | int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2; | ||
1717 | u32 code; | ||
1718 | |||
1719 | if (urb->status < 0 || urb->actual_length <= offset) | ||
1720 | return; | ||
1721 | code = mixer->rc_buffer[offset]; | ||
1722 | /* the Mute button actually changes the mixer control */ | ||
1723 | if (code == 13) | ||
1724 | snd_usb_mixer_notify_id(mixer, 18); | ||
1725 | mixer->rc_code = code; | ||
1726 | wmb(); | ||
1727 | wake_up(&mixer->rc_waitq); | ||
1728 | } | ||
1729 | |||
1730 | static int snd_usb_sbrc_hwdep_open(snd_hwdep_t *hw, struct file *file) | ||
1731 | { | ||
1732 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1733 | |||
1734 | if (test_and_set_bit(0, &mixer->rc_hwdep_open)) | ||
1735 | return -EBUSY; | ||
1736 | return 0; | ||
1737 | } | ||
1738 | |||
1739 | static int snd_usb_sbrc_hwdep_release(snd_hwdep_t *hw, struct file *file) | ||
1740 | { | ||
1741 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1742 | |||
1743 | clear_bit(0, &mixer->rc_hwdep_open); | ||
1744 | smp_mb__after_clear_bit(); | ||
1745 | return 0; | ||
1746 | } | ||
1747 | |||
1748 | static long snd_usb_sbrc_hwdep_read(snd_hwdep_t *hw, char __user *buf, | ||
1749 | long count, loff_t *offset) | ||
1750 | { | ||
1751 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1752 | int err; | ||
1753 | u32 rc_code; | ||
1754 | |||
1755 | if (count != 1 && count != 4) | ||
1756 | return -EINVAL; | ||
1757 | err = wait_event_interruptible(mixer->rc_waitq, | ||
1758 | (rc_code = xchg(&mixer->rc_code, 0)) != 0); | ||
1759 | if (err == 0) { | ||
1760 | if (count == 1) | ||
1761 | err = put_user(rc_code, buf); | ||
1762 | else | ||
1763 | err = put_user(rc_code, (u32 __user *)buf); | ||
1764 | } | ||
1765 | return err < 0 ? err : count; | ||
1766 | } | ||
1767 | |||
1768 | static unsigned int snd_usb_sbrc_hwdep_poll(snd_hwdep_t *hw, struct file *file, | ||
1769 | poll_table *wait) | ||
1770 | { | ||
1771 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1772 | |||
1773 | poll_wait(file, &mixer->rc_waitq, wait); | ||
1774 | return mixer->rc_code ? POLLIN | POLLRDNORM : 0; | ||
1775 | } | ||
1776 | |||
1777 | static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) | ||
1778 | { | ||
1779 | snd_hwdep_t *hwdep; | ||
1780 | int err, len; | ||
1781 | |||
1782 | switch (mixer->chip->usb_id) { | ||
1783 | case USB_ID(0x041e, 0x3000): | ||
1784 | mixer->rc_type = RC_EXTIGY; | ||
1785 | len = 2; | ||
1786 | break; | ||
1787 | case USB_ID(0x041e, 0x3020): | ||
1788 | mixer->rc_type = RC_AUDIGY2NX; | ||
1789 | len = 6; | ||
1790 | break; | ||
1791 | default: | ||
1792 | return 0; | ||
1793 | } | ||
1794 | |||
1795 | init_waitqueue_head(&mixer->rc_waitq); | ||
1796 | err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); | ||
1797 | if (err < 0) | ||
1798 | return err; | ||
1799 | snprintf(hwdep->name, sizeof(hwdep->name), | ||
1800 | "%s remote control", mixer->chip->card->shortname); | ||
1801 | hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC; | ||
1802 | hwdep->private_data = mixer; | ||
1803 | hwdep->ops.read = snd_usb_sbrc_hwdep_read; | ||
1804 | hwdep->ops.open = snd_usb_sbrc_hwdep_open; | ||
1805 | hwdep->ops.release = snd_usb_sbrc_hwdep_release; | ||
1806 | hwdep->ops.poll = snd_usb_sbrc_hwdep_poll; | ||
1807 | |||
1808 | mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1809 | if (!mixer->rc_urb) | ||
1810 | return -ENOMEM; | ||
1811 | mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL); | ||
1812 | if (!mixer->rc_setup_packet) { | ||
1813 | usb_free_urb(mixer->rc_urb); | ||
1814 | mixer->rc_urb = NULL; | ||
1815 | return -ENOMEM; | ||
1816 | } | ||
1817 | mixer->rc_setup_packet->bRequestType = | ||
1818 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
1819 | mixer->rc_setup_packet->bRequest = GET_MEM; | ||
1820 | mixer->rc_setup_packet->wValue = cpu_to_le16(0); | ||
1821 | mixer->rc_setup_packet->wIndex = cpu_to_le16(0); | ||
1822 | mixer->rc_setup_packet->wLength = cpu_to_le16(len); | ||
1823 | usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev, | ||
1824 | usb_rcvctrlpipe(mixer->chip->dev, 0), | ||
1825 | (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len, | ||
1826 | snd_usb_soundblaster_remote_complete, mixer); | ||
1827 | return 0; | ||
1828 | } | ||
1829 | |||
1830 | static int snd_audigy2nx_led_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
1831 | { | ||
1832 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1833 | uinfo->count = 1; | ||
1834 | uinfo->value.integer.min = 0; | ||
1835 | uinfo->value.integer.max = 1; | ||
1836 | return 0; | ||
1837 | } | ||
1838 | |||
1839 | static int snd_audigy2nx_led_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1840 | { | ||
1841 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
1842 | int index = kcontrol->private_value; | ||
1843 | |||
1844 | ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index]; | ||
1845 | return 0; | ||
1846 | } | ||
1847 | |||
1848 | static int snd_audigy2nx_led_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1849 | { | ||
1850 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
1851 | int index = kcontrol->private_value; | ||
1852 | int value = ucontrol->value.integer.value[0]; | ||
1853 | int err, changed; | ||
1854 | |||
1855 | if (value > 1) | ||
1856 | return -EINVAL; | ||
1857 | changed = value != mixer->audigy2nx_leds[index]; | ||
1858 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
1859 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | ||
1860 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
1861 | value, index + 2, NULL, 0, 100); | ||
1862 | if (err < 0) | ||
1863 | return err; | ||
1864 | mixer->audigy2nx_leds[index] = value; | ||
1865 | return changed; | ||
1866 | } | ||
1867 | |||
1868 | static snd_kcontrol_new_t snd_audigy2nx_controls[] = { | ||
1869 | { | ||
1870 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1871 | .name = "CMSS LED Switch", | ||
1872 | .info = snd_audigy2nx_led_info, | ||
1873 | .get = snd_audigy2nx_led_get, | ||
1874 | .put = snd_audigy2nx_led_put, | ||
1875 | .private_value = 0, | ||
1876 | }, | ||
1877 | { | ||
1878 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1879 | .name = "Power LED Switch", | ||
1880 | .info = snd_audigy2nx_led_info, | ||
1881 | .get = snd_audigy2nx_led_get, | ||
1882 | .put = snd_audigy2nx_led_put, | ||
1883 | .private_value = 1, | ||
1884 | }, | ||
1885 | { | ||
1886 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1887 | .name = "Dolby Digital LED Switch", | ||
1888 | .info = snd_audigy2nx_led_info, | ||
1889 | .get = snd_audigy2nx_led_get, | ||
1890 | .put = snd_audigy2nx_led_put, | ||
1891 | .private_value = 2, | ||
1892 | }, | ||
1893 | }; | ||
1894 | |||
1895 | static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | ||
1896 | { | ||
1897 | int i, err; | ||
1898 | |||
1899 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { | ||
1900 | err = snd_ctl_add(mixer->chip->card, | ||
1901 | snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); | ||
1902 | if (err < 0) | ||
1903 | return err; | ||
1904 | } | ||
1905 | mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */ | ||
1906 | return 0; | ||
1907 | } | ||
1908 | |||
1909 | static void snd_audigy2nx_proc_read(snd_info_entry_t *entry, | ||
1910 | snd_info_buffer_t *buffer) | ||
1911 | { | ||
1912 | static const struct { | ||
1913 | int unitid; | ||
1914 | const char *name; | ||
1915 | } jacks[] = { | ||
1916 | {4, "dig in "}, | ||
1917 | {7, "line in"}, | ||
1918 | {19, "spk out"}, | ||
1919 | {20, "hph out"}, | ||
1920 | }; | ||
1921 | struct usb_mixer_interface *mixer = entry->private_data; | ||
1922 | int i, err; | ||
1923 | u8 buf[3]; | ||
1924 | |||
1925 | snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); | ||
1926 | for (i = 0; i < ARRAY_SIZE(jacks); ++i) { | ||
1927 | snd_iprintf(buffer, "%s: ", jacks[i].name); | ||
1928 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
1929 | usb_rcvctrlpipe(mixer->chip->dev, 0), | ||
1930 | GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | | ||
1931 | USB_RECIP_INTERFACE, 0, | ||
1932 | jacks[i].unitid << 8, buf, 3, 100); | ||
1933 | if (err == 3 && buf[0] == 3) | ||
1934 | snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); | ||
1935 | else | ||
1936 | snd_iprintf(buffer, "?\n"); | ||
1937 | } | ||
1938 | } | ||
1939 | |||
1940 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | ||
1941 | { | ||
1942 | static snd_device_ops_t dev_ops = { | ||
1943 | .dev_free = snd_usb_mixer_dev_free | ||
1944 | }; | ||
1945 | struct usb_mixer_interface *mixer; | ||
1946 | int err; | ||
1947 | |||
1948 | strcpy(chip->card->mixername, "USB Mixer"); | ||
1949 | |||
1950 | mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL); | ||
1951 | if (!mixer) | ||
1952 | return -ENOMEM; | ||
1953 | mixer->chip = chip; | ||
1954 | mixer->ctrlif = ctrlif; | ||
1955 | #ifdef IGNORE_CTL_ERROR | ||
1956 | mixer->ignore_ctl_error = 1; | ||
1957 | #endif | ||
1958 | mixer->id_elems = kcalloc(256, sizeof(*mixer->id_elems), GFP_KERNEL); | ||
1959 | if (!mixer->id_elems) { | ||
1960 | kfree(mixer); | ||
1961 | return -ENOMEM; | ||
1962 | } | ||
1963 | |||
1964 | if ((err = snd_usb_mixer_controls(mixer)) < 0 || | ||
1965 | (err = snd_usb_mixer_status_create(mixer)) < 0) | ||
1966 | goto _error; | ||
1967 | |||
1968 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) | ||
1969 | goto _error; | ||
1970 | |||
1971 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) { | ||
1972 | snd_info_entry_t *entry; | ||
1973 | |||
1974 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | ||
1975 | goto _error; | ||
1976 | if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) | ||
1977 | snd_info_set_text_ops(entry, mixer, 1024, | ||
1978 | snd_audigy2nx_proc_read); | ||
1979 | } | ||
1980 | |||
1981 | err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); | ||
1982 | if (err < 0) | ||
1983 | goto _error; | ||
1984 | list_add(&mixer->list, &chip->mixer_list); | ||
1985 | return 0; | ||
1986 | |||
1987 | _error: | ||
1988 | snd_usb_mixer_free(mixer); | ||
1989 | return err; | ||
1990 | } | ||
1991 | |||
1992 | void snd_usb_mixer_disconnect(struct list_head *p) | ||
1993 | { | ||
1994 | struct usb_mixer_interface *mixer; | ||
1995 | |||
1996 | mixer = list_entry(p, struct usb_mixer_interface, list); | ||
1997 | if (mixer->urb) | ||
1998 | usb_kill_urb(mixer->urb); | ||
1999 | if (mixer->rc_urb) | ||
2000 | usb_kill_urb(mixer->rc_urb); | ||
2001 | } | ||
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..f5135641b3e2 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h | |||
@@ -203,11 +203,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
203 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 203 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
204 | .vendor_name = "EDIROL", | 204 | .vendor_name = "EDIROL", |
205 | .product_name = "UM-4", | 205 | .product_name = "UM-4", |
206 | .ifnum = 2, | 206 | .ifnum = QUIRK_ANY_INTERFACE, |
207 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 207 | .type = QUIRK_COMPOSITE, |
208 | .data = & (const snd_usb_midi_endpoint_info_t) { | 208 | .data = (const snd_usb_audio_quirk_t[]) { |
209 | .out_cables = 0x000f, | 209 | { |
210 | .in_cables = 0x000f | 210 | .ifnum = 0, |
211 | .type = QUIRK_IGNORE_INTERFACE | ||
212 | }, | ||
213 | { | ||
214 | .ifnum = 1, | ||
215 | .type = QUIRK_IGNORE_INTERFACE | ||
216 | }, | ||
217 | { | ||
218 | .ifnum = 2, | ||
219 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
220 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
221 | .out_cables = 0x000f, | ||
222 | .in_cables = 0x000f | ||
223 | } | ||
224 | }, | ||
225 | { | ||
226 | .ifnum = -1 | ||
227 | } | ||
211 | } | 228 | } |
212 | } | 229 | } |
213 | }, | 230 | }, |
@@ -216,11 +233,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
216 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 233 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
217 | .vendor_name = "Roland", | 234 | .vendor_name = "Roland", |
218 | .product_name = "SC-8850", | 235 | .product_name = "SC-8850", |
219 | .ifnum = 2, | 236 | .ifnum = QUIRK_ANY_INTERFACE, |
220 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 237 | .type = QUIRK_COMPOSITE, |
221 | .data = & (const snd_usb_midi_endpoint_info_t) { | 238 | .data = (const snd_usb_audio_quirk_t[]) { |
222 | .out_cables = 0x003f, | 239 | { |
223 | .in_cables = 0x003f | 240 | .ifnum = 0, |
241 | .type = QUIRK_IGNORE_INTERFACE | ||
242 | }, | ||
243 | { | ||
244 | .ifnum = 1, | ||
245 | .type = QUIRK_IGNORE_INTERFACE | ||
246 | }, | ||
247 | { | ||
248 | .ifnum = 2, | ||
249 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
250 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
251 | .out_cables = 0x003f, | ||
252 | .in_cables = 0x003f | ||
253 | } | ||
254 | }, | ||
255 | { | ||
256 | .ifnum = -1 | ||
257 | } | ||
224 | } | 258 | } |
225 | } | 259 | } |
226 | }, | 260 | }, |
@@ -229,11 +263,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
229 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 263 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
230 | .vendor_name = "Roland", | 264 | .vendor_name = "Roland", |
231 | .product_name = "U-8", | 265 | .product_name = "U-8", |
232 | .ifnum = 2, | 266 | .ifnum = QUIRK_ANY_INTERFACE, |
233 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 267 | .type = QUIRK_COMPOSITE, |
234 | .data = & (const snd_usb_midi_endpoint_info_t) { | 268 | .data = (const snd_usb_audio_quirk_t[]) { |
235 | .out_cables = 0x0005, | 269 | { |
236 | .in_cables = 0x0005 | 270 | .ifnum = 0, |
271 | .type = QUIRK_IGNORE_INTERFACE | ||
272 | }, | ||
273 | { | ||
274 | .ifnum = 1, | ||
275 | .type = QUIRK_IGNORE_INTERFACE | ||
276 | }, | ||
277 | { | ||
278 | .ifnum = 2, | ||
279 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
280 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
281 | .out_cables = 0x0005, | ||
282 | .in_cables = 0x0005 | ||
283 | } | ||
284 | }, | ||
285 | { | ||
286 | .ifnum = -1 | ||
287 | } | ||
237 | } | 288 | } |
238 | } | 289 | } |
239 | }, | 290 | }, |
@@ -242,11 +293,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
242 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 293 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
243 | .vendor_name = "EDIROL", | 294 | .vendor_name = "EDIROL", |
244 | .product_name = "UM-2", | 295 | .product_name = "UM-2", |
245 | .ifnum = 2, | 296 | .ifnum = QUIRK_ANY_INTERFACE, |
246 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 297 | .type = QUIRK_COMPOSITE, |
247 | .data = & (const snd_usb_midi_endpoint_info_t) { | 298 | .data = (const snd_usb_audio_quirk_t[]) { |
248 | .out_cables = 0x0003, | 299 | { |
249 | .in_cables = 0x0003 | 300 | .ifnum = 0, |
301 | .type = QUIRK_IGNORE_INTERFACE | ||
302 | }, | ||
303 | { | ||
304 | .ifnum = 1, | ||
305 | .type = QUIRK_IGNORE_INTERFACE | ||
306 | }, | ||
307 | { | ||
308 | .ifnum = 2, | ||
309 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
310 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
311 | .out_cables = 0x0003, | ||
312 | .in_cables = 0x0003 | ||
313 | } | ||
314 | }, | ||
315 | { | ||
316 | .ifnum = -1 | ||
317 | } | ||
250 | } | 318 | } |
251 | } | 319 | } |
252 | }, | 320 | }, |
@@ -255,11 +323,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
255 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 323 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
256 | .vendor_name = "Roland", | 324 | .vendor_name = "Roland", |
257 | .product_name = "SC-8820", | 325 | .product_name = "SC-8820", |
258 | .ifnum = 2, | 326 | .ifnum = QUIRK_ANY_INTERFACE, |
259 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 327 | .type = QUIRK_COMPOSITE, |
260 | .data = & (const snd_usb_midi_endpoint_info_t) { | 328 | .data = (const snd_usb_audio_quirk_t[]) { |
261 | .out_cables = 0x0013, | 329 | { |
262 | .in_cables = 0x0013 | 330 | .ifnum = 0, |
331 | .type = QUIRK_IGNORE_INTERFACE | ||
332 | }, | ||
333 | { | ||
334 | .ifnum = 1, | ||
335 | .type = QUIRK_IGNORE_INTERFACE | ||
336 | }, | ||
337 | { | ||
338 | .ifnum = 2, | ||
339 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
340 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
341 | .out_cables = 0x0013, | ||
342 | .in_cables = 0x0013 | ||
343 | } | ||
344 | }, | ||
345 | { | ||
346 | .ifnum = -1 | ||
347 | } | ||
263 | } | 348 | } |
264 | } | 349 | } |
265 | }, | 350 | }, |
@@ -268,11 +353,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
268 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 353 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
269 | .vendor_name = "Roland", | 354 | .vendor_name = "Roland", |
270 | .product_name = "PC-300", | 355 | .product_name = "PC-300", |
271 | .ifnum = 2, | 356 | .ifnum = QUIRK_ANY_INTERFACE, |
272 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 357 | .type = QUIRK_COMPOSITE, |
273 | .data = & (const snd_usb_midi_endpoint_info_t) { | 358 | .data = (const snd_usb_audio_quirk_t[]) { |
274 | .out_cables = 0x0001, | 359 | { |
275 | .in_cables = 0x0001 | 360 | .ifnum = 0, |
361 | .type = QUIRK_IGNORE_INTERFACE | ||
362 | }, | ||
363 | { | ||
364 | .ifnum = 1, | ||
365 | .type = QUIRK_IGNORE_INTERFACE | ||
366 | }, | ||
367 | { | ||
368 | .ifnum = 2, | ||
369 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
370 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
371 | .out_cables = 0x0001, | ||
372 | .in_cables = 0x0001 | ||
373 | } | ||
374 | }, | ||
375 | { | ||
376 | .ifnum = -1 | ||
377 | } | ||
276 | } | 378 | } |
277 | } | 379 | } |
278 | }, | 380 | }, |
@@ -281,11 +383,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
281 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 383 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
282 | .vendor_name = "EDIROL", | 384 | .vendor_name = "EDIROL", |
283 | .product_name = "UM-1", | 385 | .product_name = "UM-1", |
284 | .ifnum = 2, | 386 | .ifnum = QUIRK_ANY_INTERFACE, |
285 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 387 | .type = QUIRK_COMPOSITE, |
286 | .data = & (const snd_usb_midi_endpoint_info_t) { | 388 | .data = (const snd_usb_audio_quirk_t[]) { |
287 | .out_cables = 0x0001, | 389 | { |
288 | .in_cables = 0x0001 | 390 | .ifnum = 0, |
391 | .type = QUIRK_IGNORE_INTERFACE | ||
392 | }, | ||
393 | { | ||
394 | .ifnum = 1, | ||
395 | .type = QUIRK_IGNORE_INTERFACE | ||
396 | }, | ||
397 | { | ||
398 | .ifnum = 2, | ||
399 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
400 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
401 | .out_cables = 0x0001, | ||
402 | .in_cables = 0x0001 | ||
403 | } | ||
404 | }, | ||
405 | { | ||
406 | .ifnum = -1 | ||
407 | } | ||
289 | } | 408 | } |
290 | } | 409 | } |
291 | }, | 410 | }, |
@@ -294,11 +413,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
294 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 413 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
295 | .vendor_name = "Roland", | 414 | .vendor_name = "Roland", |
296 | .product_name = "SK-500", | 415 | .product_name = "SK-500", |
297 | .ifnum = 2, | 416 | .ifnum = QUIRK_ANY_INTERFACE, |
298 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 417 | .type = QUIRK_COMPOSITE, |
299 | .data = & (const snd_usb_midi_endpoint_info_t) { | 418 | .data = (const snd_usb_audio_quirk_t[]) { |
300 | .out_cables = 0x0013, | 419 | { |
301 | .in_cables = 0x0013 | 420 | .ifnum = 0, |
421 | .type = QUIRK_IGNORE_INTERFACE | ||
422 | }, | ||
423 | { | ||
424 | .ifnum = 1, | ||
425 | .type = QUIRK_IGNORE_INTERFACE | ||
426 | }, | ||
427 | { | ||
428 | .ifnum = 2, | ||
429 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
430 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
431 | .out_cables = 0x0013, | ||
432 | .in_cables = 0x0013 | ||
433 | } | ||
434 | }, | ||
435 | { | ||
436 | .ifnum = -1 | ||
437 | } | ||
302 | } | 438 | } |
303 | } | 439 | } |
304 | }, | 440 | }, |
@@ -421,11 +557,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
421 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 557 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
422 | .vendor_name = "EDIROL", | 558 | .vendor_name = "EDIROL", |
423 | .product_name = "SD-90", | 559 | .product_name = "SD-90", |
424 | .ifnum = 2, | 560 | .ifnum = QUIRK_ANY_INTERFACE, |
425 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 561 | .type = QUIRK_COMPOSITE, |
426 | .data = & (const snd_usb_midi_endpoint_info_t) { | 562 | .data = (const snd_usb_audio_quirk_t[]) { |
427 | .out_cables = 0x000f, | 563 | { |
428 | .in_cables = 0x000f | 564 | .ifnum = 0, |
565 | .type = QUIRK_IGNORE_INTERFACE | ||
566 | }, | ||
567 | { | ||
568 | .ifnum = 1, | ||
569 | .type = QUIRK_IGNORE_INTERFACE | ||
570 | }, | ||
571 | { | ||
572 | .ifnum = 2, | ||
573 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
574 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
575 | .out_cables = 0x000f, | ||
576 | .in_cables = 0x000f | ||
577 | } | ||
578 | }, | ||
579 | { | ||
580 | .ifnum = -1 | ||
581 | } | ||
429 | } | 582 | } |
430 | } | 583 | } |
431 | }, | 584 | }, |
@@ -434,11 +587,28 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
434 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 587 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
435 | .vendor_name = "Roland", | 588 | .vendor_name = "Roland", |
436 | .product_name = "MMP-2", | 589 | .product_name = "MMP-2", |
437 | .ifnum = 2, | 590 | .ifnum = QUIRK_ANY_INTERFACE, |
438 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 591 | .type = QUIRK_COMPOSITE, |
439 | .data = & (const snd_usb_midi_endpoint_info_t) { | 592 | .data = (const snd_usb_audio_quirk_t[]) { |
440 | .out_cables = 0x0001, | 593 | { |
441 | .in_cables = 0x0001 | 594 | .ifnum = 0, |
595 | .type = QUIRK_IGNORE_INTERFACE | ||
596 | }, | ||
597 | { | ||
598 | .ifnum = 1, | ||
599 | .type = QUIRK_IGNORE_INTERFACE | ||
600 | }, | ||
601 | { | ||
602 | .ifnum = 2, | ||
603 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
604 | .data = & (const snd_usb_midi_endpoint_info_t) { | ||
605 | .out_cables = 0x0001, | ||
606 | .in_cables = 0x0001 | ||
607 | } | ||
608 | }, | ||
609 | { | ||
610 | .ifnum = -1 | ||
611 | } | ||
442 | } | 612 | } |
443 | } | 613 | } |
444 | }, | 614 | }, |
@@ -609,15 +779,33 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
609 | } | 779 | } |
610 | }, | 780 | }, |
611 | { | 781 | { |
782 | /* | ||
783 | * This quirk is for the "Advanced Driver" mode. If off, the GS-10 | ||
784 | * has ID 0x003c and is standard compliant, but has only 16-bit PCM | ||
785 | * and no MIDI. | ||
786 | */ | ||
612 | USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b), | 787 | USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b), |
613 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 788 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
614 | .vendor_name = "BOSS", | 789 | .vendor_name = "BOSS", |
615 | .product_name = "GS-10", | 790 | .product_name = "GS-10", |
616 | .ifnum = 3, | 791 | .ifnum = QUIRK_ANY_INTERFACE, |
617 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 792 | .type = QUIRK_COMPOSITE, |
618 | .data = & (const snd_usb_midi_endpoint_info_t) { | 793 | .data = & (const snd_usb_audio_quirk_t[]) { |
619 | .out_cables = 0x0003, | 794 | { |
620 | .in_cables = 0x0003 | 795 | .ifnum = 1, |
796 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
797 | }, | ||
798 | { | ||
799 | .ifnum = 2, | ||
800 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
801 | }, | ||
802 | { | ||
803 | .ifnum = 3, | ||
804 | .type = QUIRK_MIDI_STANDARD_INTERFACE | ||
805 | }, | ||
806 | { | ||
807 | .ifnum = -1 | ||
808 | } | ||
621 | } | 809 | } |
622 | } | 810 | } |
623 | }, | 811 | }, |
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 89ee8b732013..e6e6da159671 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c | |||
@@ -442,7 +442,7 @@ static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr) | |||
442 | snd_card_disconnect((snd_card_t*)ptr); | 442 | snd_card_disconnect((snd_card_t*)ptr); |
443 | /* release the midi resources */ | 443 | /* release the midi resources */ |
444 | list_for_each(p, &usX2Y->chip.midi_list) { | 444 | list_for_each(p, &usX2Y->chip.midi_list) { |
445 | snd_usbmidi_disconnect(p, &snd_usX2Y_usb_driver); | 445 | snd_usbmidi_disconnect(p); |
446 | } | 446 | } |
447 | if (usX2Y->us428ctls_sharedmem) | 447 | if (usX2Y->us428ctls_sharedmem) |
448 | wake_up(&usX2Y->us428ctls_wait_queue_head); | 448 | wake_up(&usX2Y->us428ctls_wait_queue_head); |