diff options
Diffstat (limited to 'sound')
60 files changed, 5012 insertions, 1074 deletions
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig index 34c1740aa6e9..2e4a5e0d16db 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig | |||
@@ -20,5 +20,17 @@ config SND_ARMAACI | |||
20 | select SND_PCM | 20 | select SND_PCM |
21 | select SND_AC97_CODEC | 21 | select SND_AC97_CODEC |
22 | 22 | ||
23 | endmenu | 23 | config SND_PXA2XX_PCM |
24 | tristate | ||
25 | select SND_PCM | ||
26 | |||
27 | config SND_PXA2XX_AC97 | ||
28 | tristate "AC97 driver for the Intel PXA2xx chip" | ||
29 | depends on ARCH_PXA && SND | ||
30 | select SND_PXA2XX_PCM | ||
31 | select SND_AC97_CODEC | ||
32 | help | ||
33 | Say Y or M if you want to support any AC97 codec attached to | ||
34 | the PXA2xx AC97 interface. | ||
24 | 35 | ||
36 | endmenu | ||
diff --git a/sound/arm/Makefile b/sound/arm/Makefile index f74ec28e1068..103f136926d9 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile | |||
@@ -3,9 +3,11 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | snd-sa11xx-uda1341-objs := sa11xx-uda1341.o | 5 | snd-sa11xx-uda1341-objs := sa11xx-uda1341.o |
6 | snd-aaci-objs := aaci.o devdma.o | ||
7 | snd-pxa2xx-pcm-objs := pxa2xx-pcm.o | ||
8 | snd-pxa2xx-ac97-objs := pxa2xx-ac97.o | ||
6 | 9 | ||
7 | # Toplevel Module Dependency | ||
8 | obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o | 10 | obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o |
9 | |||
10 | obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o | 11 | obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o |
11 | snd-aaci-objs := aaci.o devdma.o | 12 | obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o |
13 | obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o | ||
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c new file mode 100644 index 000000000000..46052304e230 --- /dev/null +++ b/sound/arm/pxa2xx-ac97.c | |||
@@ -0,0 +1,410 @@ | |||
1 | /* | ||
2 | * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip. | ||
3 | * | ||
4 | * Author: Nicolas Pitre | ||
5 | * Created: Dec 02, 2004 | ||
6 | * Copyright: MontaVista Software Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/wait.h> | ||
19 | #include <linux/delay.h> | ||
20 | |||
21 | #include <sound/driver.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/ac97_codec.h> | ||
25 | #include <sound/initval.h> | ||
26 | |||
27 | #include <asm/irq.h> | ||
28 | #include <asm/semaphore.h> | ||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/arch/pxa-regs.h> | ||
31 | #include <asm/arch/audio.h> | ||
32 | |||
33 | #include "pxa2xx-pcm.h" | ||
34 | |||
35 | |||
36 | static DECLARE_MUTEX(car_mutex); | ||
37 | static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); | ||
38 | static volatile long gsr_bits; | ||
39 | |||
40 | static unsigned short pxa2xx_ac97_read(ac97_t *ac97, unsigned short reg) | ||
41 | { | ||
42 | unsigned short val = -1; | ||
43 | volatile u32 *reg_addr; | ||
44 | |||
45 | down(&car_mutex); | ||
46 | if (CAR & CAR_CAIP) { | ||
47 | printk(KERN_CRIT"%s: CAR_CAIP already set\n", __FUNCTION__); | ||
48 | goto out; | ||
49 | } | ||
50 | |||
51 | /* set up primary or secondary codec space */ | ||
52 | reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; | ||
53 | reg_addr += (reg >> 1); | ||
54 | |||
55 | /* start read access across the ac97 link */ | ||
56 | gsr_bits = 0; | ||
57 | val = *reg_addr; | ||
58 | if (reg == AC97_GPIO_STATUS) | ||
59 | goto out; | ||
60 | wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1); | ||
61 | if (!gsr_bits & GSR_SDONE) { | ||
62 | printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", | ||
63 | __FUNCTION__, reg, gsr_bits); | ||
64 | val = -1; | ||
65 | goto out; | ||
66 | } | ||
67 | |||
68 | /* valid data now */ | ||
69 | gsr_bits = 0; | ||
70 | val = *reg_addr; | ||
71 | /* but we've just started another cycle... */ | ||
72 | wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1); | ||
73 | |||
74 | out: up(&car_mutex); | ||
75 | return val; | ||
76 | } | ||
77 | |||
78 | static void pxa2xx_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) | ||
79 | { | ||
80 | volatile u32 *reg_addr; | ||
81 | |||
82 | down(&car_mutex); | ||
83 | |||
84 | if (CAR & CAR_CAIP) { | ||
85 | printk(KERN_CRIT "%s: CAR_CAIP already set\n", __FUNCTION__); | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | /* set up primary or secondary codec space */ | ||
90 | reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; | ||
91 | reg_addr += (reg >> 1); | ||
92 | gsr_bits = 0; | ||
93 | *reg_addr = val; | ||
94 | wait_event_timeout(gsr_wq, gsr_bits & GSR_CDONE, 1); | ||
95 | if (!gsr_bits & GSR_SDONE) | ||
96 | printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n", | ||
97 | __FUNCTION__, reg, gsr_bits); | ||
98 | |||
99 | out: up(&car_mutex); | ||
100 | } | ||
101 | |||
102 | static void pxa2xx_ac97_reset(ac97_t *ac97) | ||
103 | { | ||
104 | /* First, try cold reset */ | ||
105 | GCR &= GCR_COLD_RST; /* clear everything but nCRST */ | ||
106 | GCR &= ~GCR_COLD_RST; /* then assert nCRST */ | ||
107 | |||
108 | gsr_bits = 0; | ||
109 | #ifdef CONFIG_PXA27x | ||
110 | /* PXA27x Developers Manual section 13.5.2.2.1 */ | ||
111 | pxa_set_cken(1 << 31, 1); | ||
112 | udelay(5); | ||
113 | pxa_set_cken(1 << 31, 0); | ||
114 | GCR = GCR_COLD_RST; | ||
115 | udelay(50); | ||
116 | #else | ||
117 | GCR = GCR_COLD_RST; | ||
118 | GCR |= GCR_CDONE_IE|GCR_SDONE_IE; | ||
119 | wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); | ||
120 | #endif | ||
121 | |||
122 | if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { | ||
123 | printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", | ||
124 | __FUNCTION__, gsr_bits); | ||
125 | |||
126 | /* let's try warm reset */ | ||
127 | gsr_bits = 0; | ||
128 | #ifdef CONFIG_PXA27x | ||
129 | /* warm reset broken on Bulverde, | ||
130 | so manually keep AC97 reset high */ | ||
131 | pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); | ||
132 | udelay(10); | ||
133 | GCR |= GCR_WARM_RST; | ||
134 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | ||
135 | udelay(50); | ||
136 | #else | ||
137 | GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;; | ||
138 | wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); | ||
139 | #endif | ||
140 | |||
141 | if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) | ||
142 | printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", | ||
143 | __FUNCTION__, gsr_bits); | ||
144 | } | ||
145 | |||
146 | GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); | ||
147 | GCR |= GCR_SDONE_IE|GCR_CDONE_IE; | ||
148 | } | ||
149 | |||
150 | static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id, struct pt_regs *regs) | ||
151 | { | ||
152 | long status; | ||
153 | |||
154 | status = GSR; | ||
155 | if (status) { | ||
156 | GSR = status; | ||
157 | gsr_bits |= status; | ||
158 | wake_up(&gsr_wq); | ||
159 | |||
160 | #ifdef CONFIG_PXA27x | ||
161 | /* Although we don't use those we still need to clear them | ||
162 | since they tend to spuriously trigger when MMC is used | ||
163 | (hardware bug? go figure)... */ | ||
164 | MISR = MISR_EOC; | ||
165 | PISR = PISR_EOC; | ||
166 | MCSR = MCSR_EOC; | ||
167 | #endif | ||
168 | |||
169 | return IRQ_HANDLED; | ||
170 | } | ||
171 | |||
172 | return IRQ_NONE; | ||
173 | } | ||
174 | |||
175 | static ac97_bus_ops_t pxa2xx_ac97_ops = { | ||
176 | .read = pxa2xx_ac97_read, | ||
177 | .write = pxa2xx_ac97_write, | ||
178 | .reset = pxa2xx_ac97_reset, | ||
179 | }; | ||
180 | |||
181 | static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_out = { | ||
182 | .name = "AC97 PCM out", | ||
183 | .dev_addr = __PREG(PCDR), | ||
184 | .drcmr = &DRCMRTXPCDR, | ||
185 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | ||
186 | DCMD_BURST32 | DCMD_WIDTH4, | ||
187 | }; | ||
188 | |||
189 | static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_in = { | ||
190 | .name = "AC97 PCM in", | ||
191 | .dev_addr = __PREG(PCDR), | ||
192 | .drcmr = &DRCMRRXPCDR, | ||
193 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | ||
194 | DCMD_BURST32 | DCMD_WIDTH4, | ||
195 | }; | ||
196 | |||
197 | static snd_pcm_t *pxa2xx_ac97_pcm; | ||
198 | static ac97_t *pxa2xx_ac97_ac97; | ||
199 | |||
200 | static int pxa2xx_ac97_pcm_startup(snd_pcm_substream_t *substream) | ||
201 | { | ||
202 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
203 | pxa2xx_audio_ops_t *platform_ops; | ||
204 | int r; | ||
205 | |||
206 | runtime->hw.channels_min = 2; | ||
207 | runtime->hw.channels_max = 2; | ||
208 | |||
209 | r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
210 | AC97_RATES_FRONT_DAC : AC97_RATES_ADC; | ||
211 | runtime->hw.rates = pxa2xx_ac97_ac97->rates[r]; | ||
212 | snd_pcm_limit_hw_rates(runtime); | ||
213 | |||
214 | platform_ops = substream->pcm->card->dev->platform_data; | ||
215 | if (platform_ops && platform_ops->startup) | ||
216 | return platform_ops->startup(substream, platform_ops->priv); | ||
217 | else | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static void pxa2xx_ac97_pcm_shutdown(snd_pcm_substream_t *substream) | ||
222 | { | ||
223 | pxa2xx_audio_ops_t *platform_ops; | ||
224 | |||
225 | platform_ops = substream->pcm->card->dev->platform_data; | ||
226 | if (platform_ops && platform_ops->shutdown) | ||
227 | platform_ops->shutdown(substream, platform_ops->priv); | ||
228 | } | ||
229 | |||
230 | static int pxa2xx_ac97_pcm_prepare(snd_pcm_substream_t *substream) | ||
231 | { | ||
232 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
233 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
234 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; | ||
235 | return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate); | ||
236 | } | ||
237 | |||
238 | static pxa2xx_pcm_client_t pxa2xx_ac97_pcm_client = { | ||
239 | .playback_params = &pxa2xx_ac97_pcm_out, | ||
240 | .capture_params = &pxa2xx_ac97_pcm_in, | ||
241 | .startup = pxa2xx_ac97_pcm_startup, | ||
242 | .shutdown = pxa2xx_ac97_pcm_shutdown, | ||
243 | .prepare = pxa2xx_ac97_pcm_prepare, | ||
244 | }; | ||
245 | |||
246 | #ifdef CONFIG_PM | ||
247 | |||
248 | static int pxa2xx_ac97_do_suspend(snd_card_t *card, unsigned int state) | ||
249 | { | ||
250 | if (card->power_state != SNDRV_CTL_POWER_D3cold) { | ||
251 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; | ||
252 | snd_pcm_suspend_all(pxa2xx_ac97_pcm); | ||
253 | snd_ac97_suspend(pxa2xx_ac97_ac97); | ||
254 | snd_power_change_state(card, SNDRV_CTL_POWER_D3cold); | ||
255 | if (platform_ops && platform_ops->suspend) | ||
256 | platform_ops->suspend(platform_ops->priv); | ||
257 | GCR |= GCR_ACLINK_OFF; | ||
258 | pxa_set_cken(CKEN2_AC97, 0); | ||
259 | } | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int pxa2xx_ac97_do_resume(snd_card_t *card, unsigned int state) | ||
265 | { | ||
266 | if (card->power_state != SNDRV_CTL_POWER_D0) { | ||
267 | pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; | ||
268 | pxa_set_cken(CKEN2_AC97, 1); | ||
269 | if (platform_ops && platform_ops->resume) | ||
270 | platform_ops->resume(platform_ops->priv); | ||
271 | snd_ac97_resume(pxa2xx_ac97_ac97); | ||
272 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
273 | } | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int pxa2xx_ac97_suspend(struct device *_dev, u32 state, u32 level) | ||
279 | { | ||
280 | snd_card_t *card = dev_get_drvdata(_dev); | ||
281 | int ret = 0; | ||
282 | |||
283 | if (card && level == SUSPEND_DISABLE) | ||
284 | ret = pxa2xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold); | ||
285 | |||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | static int pxa2xx_ac97_resume(struct device *_dev, u32 level) | ||
290 | { | ||
291 | snd_card_t *card = dev_get_drvdata(_dev); | ||
292 | int ret = 0; | ||
293 | |||
294 | if (card && level == RESUME_ENABLE) | ||
295 | ret = pxa2xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0); | ||
296 | |||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | #else | ||
301 | #define pxa2xx_ac97_suspend NULL | ||
302 | #define pxa2xx_ac97_resume NULL | ||
303 | #endif | ||
304 | |||
305 | static int pxa2xx_ac97_probe(struct device *dev) | ||
306 | { | ||
307 | snd_card_t *card; | ||
308 | ac97_bus_t *ac97_bus; | ||
309 | ac97_template_t ac97_template; | ||
310 | int ret; | ||
311 | |||
312 | ret = -ENOMEM; | ||
313 | card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | ||
314 | THIS_MODULE, 0); | ||
315 | if (!card) | ||
316 | goto err; | ||
317 | |||
318 | card->dev = dev; | ||
319 | strncpy(card->driver, dev->driver->name, sizeof(card->driver)); | ||
320 | |||
321 | ret = pxa2xx_pcm_new(card, &pxa2xx_ac97_pcm_client, &pxa2xx_ac97_pcm); | ||
322 | if (ret) | ||
323 | goto err; | ||
324 | |||
325 | ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL); | ||
326 | if (ret < 0) | ||
327 | goto err; | ||
328 | |||
329 | pxa_gpio_mode(GPIO31_SYNC_AC97_MD); | ||
330 | pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); | ||
331 | pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); | ||
332 | pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); | ||
333 | #ifdef CONFIG_PXA27x | ||
334 | /* Use GPIO 113 as AC97 Reset on Bulverde */ | ||
335 | pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); | ||
336 | #endif | ||
337 | pxa_set_cken(CKEN2_AC97, 1); | ||
338 | |||
339 | ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus); | ||
340 | if (ret) | ||
341 | goto err; | ||
342 | memset(&ac97_template, 0, sizeof(ac97_template)); | ||
343 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97); | ||
344 | if (ret) | ||
345 | goto err; | ||
346 | |||
347 | snprintf(card->shortname, sizeof(card->shortname), | ||
348 | "%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97)); | ||
349 | snprintf(card->longname, sizeof(card->longname), | ||
350 | "%s (%s)", dev->driver->name, card->mixername); | ||
351 | |||
352 | snd_card_set_pm_callback(card, pxa2xx_ac97_do_suspend, | ||
353 | pxa2xx_ac97_do_resume, NULL); | ||
354 | ret = snd_card_register(card); | ||
355 | if (ret == 0) { | ||
356 | dev_set_drvdata(dev, card); | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | err: | ||
361 | if (card) | ||
362 | snd_card_free(card); | ||
363 | if (CKEN & CKEN2_AC97) { | ||
364 | GCR |= GCR_ACLINK_OFF; | ||
365 | free_irq(IRQ_AC97, NULL); | ||
366 | pxa_set_cken(CKEN2_AC97, 0); | ||
367 | } | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | static int pxa2xx_ac97_remove(struct device *dev) | ||
372 | { | ||
373 | snd_card_t *card = dev_get_drvdata(dev); | ||
374 | |||
375 | if (card) { | ||
376 | snd_card_free(card); | ||
377 | dev_set_drvdata(dev, NULL); | ||
378 | GCR |= GCR_ACLINK_OFF; | ||
379 | free_irq(IRQ_AC97, NULL); | ||
380 | pxa_set_cken(CKEN2_AC97, 0); | ||
381 | } | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static struct device_driver pxa2xx_ac97_driver = { | ||
387 | .name = "pxa2xx-ac97", | ||
388 | .bus = &platform_bus_type, | ||
389 | .probe = pxa2xx_ac97_probe, | ||
390 | .remove = pxa2xx_ac97_remove, | ||
391 | .suspend = pxa2xx_ac97_suspend, | ||
392 | .resume = pxa2xx_ac97_resume, | ||
393 | }; | ||
394 | |||
395 | static int __init pxa2xx_ac97_init(void) | ||
396 | { | ||
397 | return driver_register(&pxa2xx_ac97_driver); | ||
398 | } | ||
399 | |||
400 | static void __exit pxa2xx_ac97_exit(void) | ||
401 | { | ||
402 | driver_unregister(&pxa2xx_ac97_driver); | ||
403 | } | ||
404 | |||
405 | module_init(pxa2xx_ac97_init); | ||
406 | module_exit(pxa2xx_ac97_exit); | ||
407 | |||
408 | MODULE_AUTHOR("Nicolas Pitre"); | ||
409 | MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); | ||
410 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c new file mode 100644 index 000000000000..b1eb53b02eae --- /dev/null +++ b/sound/arm/pxa2xx-pcm.c | |||
@@ -0,0 +1,367 @@ | |||
1 | /* | ||
2 | * linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip | ||
3 | * | ||
4 | * Author: Nicolas Pitre | ||
5 | * Created: Nov 30, 2004 | ||
6 | * Copyright: (C) 2004 MontaVista Software, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/dma-mapping.h> | ||
18 | |||
19 | #include <sound/driver.h> | ||
20 | #include <sound/core.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | |||
24 | #include <asm/dma.h> | ||
25 | #include <asm/hardware.h> | ||
26 | #include <asm/arch/pxa-regs.h> | ||
27 | |||
28 | #include "pxa2xx-pcm.h" | ||
29 | |||
30 | |||
31 | static const snd_pcm_hardware_t pxa2xx_pcm_hardware = { | ||
32 | .info = SNDRV_PCM_INFO_MMAP | | ||
33 | SNDRV_PCM_INFO_MMAP_VALID | | ||
34 | SNDRV_PCM_INFO_INTERLEAVED | | ||
35 | SNDRV_PCM_INFO_PAUSE, | ||
36 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
37 | .period_bytes_min = 32, | ||
38 | .period_bytes_max = 8192 - 32, | ||
39 | .periods_min = 1, | ||
40 | .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc), | ||
41 | .buffer_bytes_max = 128 * 1024, | ||
42 | .fifo_size = 32, | ||
43 | }; | ||
44 | |||
45 | struct pxa2xx_runtime_data { | ||
46 | int dma_ch; | ||
47 | pxa2xx_pcm_dma_params_t *params; | ||
48 | pxa_dma_desc *dma_desc_array; | ||
49 | dma_addr_t dma_desc_array_phys; | ||
50 | }; | ||
51 | |||
52 | static int pxa2xx_pcm_hw_params(snd_pcm_substream_t *substream, | ||
53 | snd_pcm_hw_params_t *params) | ||
54 | { | ||
55 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
56 | struct pxa2xx_runtime_data *rtd = runtime->private_data; | ||
57 | size_t totsize = params_buffer_bytes(params); | ||
58 | size_t period = params_period_bytes(params); | ||
59 | pxa_dma_desc *dma_desc; | ||
60 | dma_addr_t dma_buff_phys, next_desc_phys; | ||
61 | |||
62 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
63 | runtime->dma_bytes = totsize; | ||
64 | |||
65 | dma_desc = rtd->dma_desc_array; | ||
66 | next_desc_phys = rtd->dma_desc_array_phys; | ||
67 | dma_buff_phys = runtime->dma_addr; | ||
68 | do { | ||
69 | next_desc_phys += sizeof(pxa_dma_desc); | ||
70 | dma_desc->ddadr = next_desc_phys; | ||
71 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
72 | dma_desc->dsadr = dma_buff_phys; | ||
73 | dma_desc->dtadr = rtd->params->dev_addr; | ||
74 | } else { | ||
75 | dma_desc->dsadr = rtd->params->dev_addr; | ||
76 | dma_desc->dtadr = dma_buff_phys; | ||
77 | } | ||
78 | if (period > totsize) | ||
79 | period = totsize; | ||
80 | dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN; | ||
81 | dma_desc++; | ||
82 | dma_buff_phys += period; | ||
83 | } while (totsize -= period); | ||
84 | dma_desc[-1].ddadr = rtd->dma_desc_array_phys; | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int pxa2xx_pcm_hw_free(snd_pcm_substream_t *substream) | ||
90 | { | ||
91 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; | ||
92 | |||
93 | *rtd->params->drcmr = 0; | ||
94 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int pxa2xx_pcm_prepare(snd_pcm_substream_t *substream) | ||
99 | { | ||
100 | pxa2xx_pcm_client_t *client = substream->private_data; | ||
101 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
102 | struct pxa2xx_runtime_data *rtd = runtime->private_data; | ||
103 | |||
104 | DCSR(rtd->dma_ch) &= ~DCSR_RUN; | ||
105 | DCSR(rtd->dma_ch) = 0; | ||
106 | DCMD(rtd->dma_ch) = 0; | ||
107 | *rtd->params->drcmr = rtd->dma_ch | DRCMR_MAPVLD; | ||
108 | |||
109 | return client->prepare(substream); | ||
110 | } | ||
111 | |||
112 | static int pxa2xx_pcm_trigger(snd_pcm_substream_t *substream, int cmd) | ||
113 | { | ||
114 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; | ||
115 | int ret = 0; | ||
116 | |||
117 | switch (cmd) { | ||
118 | case SNDRV_PCM_TRIGGER_START: | ||
119 | DDADR(rtd->dma_ch) = rtd->dma_desc_array_phys; | ||
120 | DCSR(rtd->dma_ch) = DCSR_RUN; | ||
121 | break; | ||
122 | |||
123 | case SNDRV_PCM_TRIGGER_STOP: | ||
124 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
125 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
126 | DCSR(rtd->dma_ch) &= ~DCSR_RUN; | ||
127 | break; | ||
128 | |||
129 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
130 | DCSR(rtd->dma_ch) |= DCSR_RUN; | ||
131 | break; | ||
132 | |||
133 | default: | ||
134 | ret = -EINVAL; | ||
135 | } | ||
136 | |||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id, struct pt_regs *regs) | ||
141 | { | ||
142 | snd_pcm_substream_t *substream = dev_id; | ||
143 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; | ||
144 | int dcsr; | ||
145 | |||
146 | dcsr = DCSR(dma_ch); | ||
147 | DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN; | ||
148 | |||
149 | if (dcsr & DCSR_ENDINTR) { | ||
150 | snd_pcm_period_elapsed(substream); | ||
151 | } else { | ||
152 | printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n", | ||
153 | rtd->params->name, dma_ch, dcsr ); | ||
154 | snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); | ||
155 | } | ||
156 | } | ||
157 | |||
158 | static snd_pcm_uframes_t pxa2xx_pcm_pointer(snd_pcm_substream_t *substream) | ||
159 | { | ||
160 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
161 | struct pxa2xx_runtime_data *rtd = runtime->private_data; | ||
162 | dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
163 | DSADR(rtd->dma_ch) : DTADR(rtd->dma_ch); | ||
164 | snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr); | ||
165 | if (x == runtime->buffer_size) | ||
166 | x = 0; | ||
167 | return x; | ||
168 | } | ||
169 | |||
170 | static int | ||
171 | pxa2xx_pcm_hw_rule_mult32(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule) | ||
172 | { | ||
173 | snd_interval_t *i = hw_param_interval(params, rule->var); | ||
174 | int changed = 0; | ||
175 | |||
176 | if (i->min & 31) { | ||
177 | i->min = (i->min & ~31) + 32; | ||
178 | i->openmin = 0; | ||
179 | changed = 1; | ||
180 | } | ||
181 | |||
182 | if (i->max & 31) { | ||
183 | i->max &= ~31; | ||
184 | i->openmax = 0; | ||
185 | changed = 1; | ||
186 | } | ||
187 | |||
188 | return changed; | ||
189 | } | ||
190 | |||
191 | static int pxa2xx_pcm_open(snd_pcm_substream_t *substream) | ||
192 | { | ||
193 | pxa2xx_pcm_client_t *client = substream->private_data; | ||
194 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
195 | struct pxa2xx_runtime_data *rtd; | ||
196 | int ret; | ||
197 | |||
198 | runtime->hw = pxa2xx_pcm_hardware; | ||
199 | |||
200 | /* | ||
201 | * For mysterious reasons (and despite what the manual says) | ||
202 | * playback samples are lost if the DMA count is not a multiple | ||
203 | * of the DMA burst size. Let's add a rule to enforce that. | ||
204 | */ | ||
205 | ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, | ||
206 | pxa2xx_pcm_hw_rule_mult32, NULL, | ||
207 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -1); | ||
208 | if (ret) | ||
209 | goto out; | ||
210 | ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | ||
211 | pxa2xx_pcm_hw_rule_mult32, NULL, | ||
212 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1); | ||
213 | if (ret) | ||
214 | goto out; | ||
215 | |||
216 | ret = -ENOMEM; | ||
217 | rtd = kmalloc(sizeof(*rtd), GFP_KERNEL); | ||
218 | if (!rtd) | ||
219 | goto out; | ||
220 | rtd->dma_desc_array = | ||
221 | dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE, | ||
222 | &rtd->dma_desc_array_phys, GFP_KERNEL); | ||
223 | if (!rtd->dma_desc_array) | ||
224 | goto err1; | ||
225 | |||
226 | rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
227 | client->playback_params : client->capture_params; | ||
228 | ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW, | ||
229 | pxa2xx_pcm_dma_irq, substream); | ||
230 | if (ret < 0) | ||
231 | goto err2; | ||
232 | rtd->dma_ch = ret; | ||
233 | |||
234 | runtime->private_data = rtd; | ||
235 | ret = client->startup(substream); | ||
236 | if (!ret) | ||
237 | goto out; | ||
238 | |||
239 | pxa_free_dma(rtd->dma_ch); | ||
240 | err2: | ||
241 | dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, | ||
242 | rtd->dma_desc_array, rtd->dma_desc_array_phys); | ||
243 | err1: | ||
244 | kfree(rtd); | ||
245 | out: | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | static int pxa2xx_pcm_close(snd_pcm_substream_t *substream) | ||
250 | { | ||
251 | pxa2xx_pcm_client_t *client = substream->private_data; | ||
252 | struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; | ||
253 | |||
254 | pxa_free_dma(rtd->dma_ch); | ||
255 | client->shutdown(substream); | ||
256 | dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, | ||
257 | rtd->dma_desc_array, rtd->dma_desc_array_phys); | ||
258 | kfree(rtd); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static int | ||
263 | pxa2xx_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma) | ||
264 | { | ||
265 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
266 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
267 | runtime->dma_area, | ||
268 | runtime->dma_addr, | ||
269 | runtime->dma_bytes); | ||
270 | } | ||
271 | |||
272 | static snd_pcm_ops_t pxa2xx_pcm_ops = { | ||
273 | .open = pxa2xx_pcm_open, | ||
274 | .close = pxa2xx_pcm_close, | ||
275 | .ioctl = snd_pcm_lib_ioctl, | ||
276 | .hw_params = pxa2xx_pcm_hw_params, | ||
277 | .hw_free = pxa2xx_pcm_hw_free, | ||
278 | .prepare = pxa2xx_pcm_prepare, | ||
279 | .trigger = pxa2xx_pcm_trigger, | ||
280 | .pointer = pxa2xx_pcm_pointer, | ||
281 | .mmap = pxa2xx_pcm_mmap, | ||
282 | }; | ||
283 | |||
284 | static int pxa2xx_pcm_preallocate_dma_buffer(snd_pcm_t *pcm, int stream) | ||
285 | { | ||
286 | snd_pcm_substream_t *substream = pcm->streams[stream].substream; | ||
287 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
288 | size_t size = pxa2xx_pcm_hardware.buffer_bytes_max; | ||
289 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
290 | buf->dev.dev = pcm->card->dev; | ||
291 | buf->private_data = NULL; | ||
292 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
293 | &buf->addr, GFP_KERNEL); | ||
294 | if (!buf->area) | ||
295 | return -ENOMEM; | ||
296 | buf->bytes = size; | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static void pxa2xx_pcm_free_dma_buffers(snd_pcm_t *pcm) | ||
301 | { | ||
302 | snd_pcm_substream_t *substream; | ||
303 | struct snd_dma_buffer *buf; | ||
304 | int stream; | ||
305 | |||
306 | for (stream = 0; stream < 2; stream++) { | ||
307 | substream = pcm->streams[stream].substream; | ||
308 | if (!substream) | ||
309 | continue; | ||
310 | buf = &substream->dma_buffer; | ||
311 | if (!buf->area) | ||
312 | continue; | ||
313 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
314 | buf->area, buf->addr); | ||
315 | buf->area = NULL; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | static u64 pxa2xx_pcm_dmamask = 0xffffffff; | ||
320 | |||
321 | int pxa2xx_pcm_new(snd_card_t *card, pxa2xx_pcm_client_t *client, snd_pcm_t **rpcm) | ||
322 | { | ||
323 | snd_pcm_t *pcm; | ||
324 | int play = client->playback_params ? 1 : 0; | ||
325 | int capt = client->capture_params ? 1 : 0; | ||
326 | int ret; | ||
327 | |||
328 | ret = snd_pcm_new(card, "PXA2xx-PCM", 0, play, capt, &pcm); | ||
329 | if (ret) | ||
330 | goto out; | ||
331 | |||
332 | pcm->private_data = client; | ||
333 | pcm->private_free = pxa2xx_pcm_free_dma_buffers; | ||
334 | |||
335 | if (!card->dev->dma_mask) | ||
336 | card->dev->dma_mask = &pxa2xx_pcm_dmamask; | ||
337 | if (!card->dev->coherent_dma_mask) | ||
338 | card->dev->coherent_dma_mask = 0xffffffff; | ||
339 | |||
340 | if (play) { | ||
341 | int stream = SNDRV_PCM_STREAM_PLAYBACK; | ||
342 | snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops); | ||
343 | ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream); | ||
344 | if (ret) | ||
345 | goto out; | ||
346 | } | ||
347 | if (capt) { | ||
348 | int stream = SNDRV_PCM_STREAM_CAPTURE; | ||
349 | snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops); | ||
350 | ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream); | ||
351 | if (ret) | ||
352 | goto out; | ||
353 | } | ||
354 | |||
355 | if (rpcm) | ||
356 | *rpcm = pcm; | ||
357 | ret = 0; | ||
358 | |||
359 | out: | ||
360 | return ret; | ||
361 | } | ||
362 | |||
363 | EXPORT_SYMBOL(pxa2xx_pcm_new); | ||
364 | |||
365 | MODULE_AUTHOR("Nicolas Pitre"); | ||
366 | MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); | ||
367 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h new file mode 100644 index 000000000000..43517597cab9 --- /dev/null +++ b/sound/arm/pxa2xx-pcm.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip | ||
3 | * | ||
4 | * Author: Nicolas Pitre | ||
5 | * Created: Nov 30, 2004 | ||
6 | * Copyright: MontaVista Software, Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | typedef struct { | ||
14 | char *name; /* stream identifier */ | ||
15 | u32 dcmd; /* DMA descriptor dcmd field */ | ||
16 | volatile u32 *drcmr; /* the DMA request channel to use */ | ||
17 | u32 dev_addr; /* device physical address for DMA */ | ||
18 | } pxa2xx_pcm_dma_params_t; | ||
19 | |||
20 | typedef struct { | ||
21 | pxa2xx_pcm_dma_params_t *playback_params; | ||
22 | pxa2xx_pcm_dma_params_t *capture_params; | ||
23 | int (*startup)(snd_pcm_substream_t *); | ||
24 | void (*shutdown)(snd_pcm_substream_t *); | ||
25 | int (*prepare)(snd_pcm_substream_t *); | ||
26 | } pxa2xx_pcm_client_t; | ||
27 | |||
28 | extern int pxa2xx_pcm_new(snd_card_t *, pxa2xx_pcm_client_t *, snd_pcm_t **); | ||
29 | |||
diff --git a/sound/core/device.c b/sound/core/device.c index 18c71f913d2a..ca00ad7740c9 100644 --- a/sound/core/device.c +++ b/sound/core/device.c | |||
@@ -28,7 +28,7 @@ | |||
28 | /** | 28 | /** |
29 | * snd_device_new - create an ALSA device component | 29 | * snd_device_new - create an ALSA device component |
30 | * @card: the card instance | 30 | * @card: the card instance |
31 | * @type: the device type, SNDRV_DEV_TYPE_XXX | 31 | * @type: the device type, SNDRV_DEV_XXX |
32 | * @device_data: the data pointer of this device | 32 | * @device_data: the data pointer of this device |
33 | * @ops: the operator table | 33 | * @ops: the operator table |
34 | * | 34 | * |
@@ -46,7 +46,9 @@ int snd_device_new(snd_card_t *card, snd_device_type_t type, | |||
46 | { | 46 | { |
47 | snd_device_t *dev; | 47 | snd_device_t *dev; |
48 | 48 | ||
49 | snd_assert(card != NULL && device_data != NULL && ops != NULL, return -ENXIO); | 49 | snd_assert(card != NULL, return -ENXIO); |
50 | snd_assert(device_data != NULL, return -ENXIO); | ||
51 | snd_assert(ops != NULL, return -ENXIO); | ||
50 | dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); | 52 | dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); |
51 | if (dev == NULL) | 53 | if (dev == NULL) |
52 | return -ENOMEM; | 54 | return -ENOMEM; |
@@ -102,7 +104,7 @@ int snd_device_free(snd_card_t *card, void *device_data) | |||
102 | } | 104 | } |
103 | 105 | ||
104 | /** | 106 | /** |
105 | * snd_device_free - disconnect the device | 107 | * snd_device_disconnect - disconnect the device |
106 | * @card: the card instance | 108 | * @card: the card instance |
107 | * @device_data: the data pointer to disconnect | 109 | * @device_data: the data pointer to disconnect |
108 | * | 110 | * |
@@ -118,7 +120,7 @@ int snd_device_disconnect(snd_card_t *card, void *device_data) | |||
118 | { | 120 | { |
119 | struct list_head *list; | 121 | struct list_head *list; |
120 | snd_device_t *dev; | 122 | snd_device_t *dev; |
121 | 123 | ||
122 | snd_assert(card != NULL, return -ENXIO); | 124 | snd_assert(card != NULL, return -ENXIO); |
123 | snd_assert(device_data != NULL, return -ENXIO); | 125 | snd_assert(device_data != NULL, return -ENXIO); |
124 | list_for_each(list, &card->devices) { | 126 | list_for_each(list, &card->devices) { |
@@ -154,8 +156,9 @@ int snd_device_register(snd_card_t *card, void *device_data) | |||
154 | struct list_head *list; | 156 | struct list_head *list; |
155 | snd_device_t *dev; | 157 | snd_device_t *dev; |
156 | int err; | 158 | int err; |
157 | 159 | ||
158 | snd_assert(card != NULL && device_data != NULL, return -ENXIO); | 160 | snd_assert(card != NULL, return -ENXIO); |
161 | snd_assert(device_data != NULL, return -ENXIO); | ||
159 | list_for_each(list, &card->devices) { | 162 | list_for_each(list, &card->devices) { |
160 | dev = snd_device(list); | 163 | dev = snd_device(list); |
161 | if (dev->device_data != device_data) | 164 | if (dev->device_data != device_data) |
diff --git a/sound/core/info.c b/sound/core/info.c index 5e122bbe7c92..7f8bdf7b0058 100644 --- a/sound/core/info.c +++ b/sound/core/info.c | |||
@@ -702,7 +702,7 @@ int snd_info_get_line(snd_info_buffer_t * buffer, char *line, int len) | |||
702 | } | 702 | } |
703 | 703 | ||
704 | /** | 704 | /** |
705 | * snd_info_get_line - parse a string token | 705 | * snd_info_get_str - parse a string token |
706 | * @dest: the buffer to store the string token | 706 | * @dest: the buffer to store the string token |
707 | * @src: the original string | 707 | * @src: the original string |
708 | * @len: the max. length of token - 1 | 708 | * @len: the max. length of token - 1 |
@@ -939,7 +939,8 @@ int snd_info_unregister(snd_info_entry_t * entry) | |||
939 | { | 939 | { |
940 | struct proc_dir_entry *root; | 940 | struct proc_dir_entry *root; |
941 | 941 | ||
942 | snd_assert(entry != NULL && entry->p != NULL, return -ENXIO); | 942 | snd_assert(entry != NULL, return -ENXIO); |
943 | snd_assert(entry->p != NULL, return -ENXIO); | ||
943 | root = entry->parent == NULL ? snd_proc_root : entry->parent->p; | 944 | root = entry->parent == NULL ? snd_proc_root : entry->parent->p; |
944 | snd_assert(root, return -ENXIO); | 945 | snd_assert(root, return -ENXIO); |
945 | down(&info_mutex); | 946 | down(&info_mutex); |
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index dbc23e35fa06..02132561c3f8 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c | |||
@@ -105,7 +105,8 @@ struct snd_mem_list { | |||
105 | */ | 105 | */ |
106 | 106 | ||
107 | static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size, | 107 | static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size, |
108 | dma_addr_t *dma_handle, int flags) | 108 | dma_addr_t *dma_handle, |
109 | unsigned int __nocast flags) | ||
109 | { | 110 | { |
110 | void *ret; | 111 | void *ret; |
111 | u64 dma_mask, coherent_dma_mask; | 112 | u64 dma_mask, coherent_dma_mask; |
diff --git a/sound/core/memory.c b/sound/core/memory.c index c1fb28e84330..f6895577bf86 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c | |||
@@ -89,7 +89,7 @@ void snd_memory_done(void) | |||
89 | } | 89 | } |
90 | } | 90 | } |
91 | 91 | ||
92 | static void *__snd_kmalloc(size_t size, int flags, void *caller) | 92 | static void *__snd_kmalloc(size_t size, unsigned int __nocast flags, void *caller) |
93 | { | 93 | { |
94 | unsigned long cpu_flags; | 94 | unsigned long cpu_flags; |
95 | struct snd_alloc_track *t; | 95 | struct snd_alloc_track *t; |
@@ -111,12 +111,12 @@ static void *__snd_kmalloc(size_t size, int flags, void *caller) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | #define _snd_kmalloc(size, flags) __snd_kmalloc((size), (flags), __builtin_return_address(0)); | 113 | #define _snd_kmalloc(size, flags) __snd_kmalloc((size), (flags), __builtin_return_address(0)); |
114 | void *snd_hidden_kmalloc(size_t size, int flags) | 114 | void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags) |
115 | { | 115 | { |
116 | return _snd_kmalloc(size, flags); | 116 | return _snd_kmalloc(size, flags); |
117 | } | 117 | } |
118 | 118 | ||
119 | void *snd_hidden_kcalloc(size_t n, size_t size, int flags) | 119 | void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags) |
120 | { | 120 | { |
121 | void *ret = NULL; | 121 | void *ret = NULL; |
122 | if (n != 0 && size > INT_MAX / n) | 122 | if (n != 0 && size > INT_MAX / n) |
@@ -184,7 +184,7 @@ void snd_hidden_vfree(void *obj) | |||
184 | snd_wrapper_vfree(obj); | 184 | snd_wrapper_vfree(obj); |
185 | } | 185 | } |
186 | 186 | ||
187 | char *snd_hidden_kstrdup(const char *s, int flags) | 187 | char *snd_hidden_kstrdup(const char *s, unsigned int __nocast flags) |
188 | { | 188 | { |
189 | int len; | 189 | int len; |
190 | char *buf; | 190 | char *buf; |
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile index 64cb50d7b589..402e2b4a34c6 100644 --- a/sound/core/seq/Makefile +++ b/sound/core/seq/Makefile | |||
@@ -38,7 +38,7 @@ obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o | |||
38 | obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o | 38 | obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o |
39 | obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o | 39 | obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o |
40 | obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o | 40 | obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o |
41 | obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-instr.o | 41 | obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-seq-midi-emul.o snd-seq-instr.o |
42 | obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o | 42 | obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o |
43 | obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o | 43 | obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o |
44 | obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o | 44 | obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o |
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c index 0779c41ca037..32e91c6b25fe 100644 --- a/sound/core/seq/instr/ainstr_gf1.c +++ b/sound/core/seq/instr/ainstr_gf1.c | |||
@@ -50,7 +50,8 @@ static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops, | |||
50 | { | 50 | { |
51 | gf1_wave_t *wp, *prev; | 51 | gf1_wave_t *wp, *prev; |
52 | gf1_xwave_t xp; | 52 | gf1_xwave_t xp; |
53 | int err, gfp_mask; | 53 | int err; |
54 | unsigned int gfp_mask; | ||
54 | unsigned int real_size; | 55 | unsigned int real_size; |
55 | 56 | ||
56 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; | 57 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; |
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c index 39ff72b2aab3..2622b8679ca7 100644 --- a/sound/core/seq/instr/ainstr_iw.c +++ b/sound/core/seq/instr/ainstr_iw.c | |||
@@ -58,7 +58,7 @@ static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype, | |||
58 | iwffff_xenv_t *ex, | 58 | iwffff_xenv_t *ex, |
59 | char __user **data, | 59 | char __user **data, |
60 | long *len, | 60 | long *len, |
61 | int gfp_mask) | 61 | unsigned int __nocast gfp_mask) |
62 | { | 62 | { |
63 | __u32 stype; | 63 | __u32 stype; |
64 | iwffff_env_record_t *rp, *rp_last; | 64 | iwffff_env_record_t *rp, *rp_last; |
@@ -128,7 +128,8 @@ static int snd_seq_iwffff_copy_wave_from_stream(snd_iwffff_ops_t *ops, | |||
128 | { | 128 | { |
129 | iwffff_wave_t *wp, *prev; | 129 | iwffff_wave_t *wp, *prev; |
130 | iwffff_xwave_t xp; | 130 | iwffff_xwave_t xp; |
131 | int err, gfp_mask; | 131 | int err; |
132 | unsigned int gfp_mask; | ||
132 | unsigned int real_size; | 133 | unsigned int real_size; |
133 | 134 | ||
134 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; | 135 | gfp_mask = atomic ? GFP_ATOMIC : GFP_KERNEL; |
@@ -234,7 +235,8 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr, | |||
234 | iwffff_xinstrument_t ix; | 235 | iwffff_xinstrument_t ix; |
235 | iwffff_layer_t *lp, *prev_lp; | 236 | iwffff_layer_t *lp, *prev_lp; |
236 | iwffff_xlayer_t lx; | 237 | iwffff_xlayer_t lx; |
237 | int err, gfp_mask; | 238 | int err; |
239 | unsigned int gfp_mask; | ||
238 | 240 | ||
239 | if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE) | 241 | if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE) |
240 | return -EINVAL; | 242 | return -EINVAL; |
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 57be9155eb62..4374829ea770 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c | |||
@@ -134,7 +134,7 @@ static int event_process_midi(snd_seq_event_t * ev, int direct, | |||
134 | seq_midisynth_t *msynth = (seq_midisynth_t *) private_data; | 134 | seq_midisynth_t *msynth = (seq_midisynth_t *) private_data; |
135 | unsigned char msg[10]; /* buffer for constructing midi messages */ | 135 | unsigned char msg[10]; /* buffer for constructing midi messages */ |
136 | snd_rawmidi_substream_t *substream; | 136 | snd_rawmidi_substream_t *substream; |
137 | int res; | 137 | int len; |
138 | 138 | ||
139 | snd_assert(msynth != NULL, return -EINVAL); | 139 | snd_assert(msynth != NULL, return -EINVAL); |
140 | substream = msynth->output_rfile.output; | 140 | substream = msynth->output_rfile.output; |
@@ -146,20 +146,16 @@ static int event_process_midi(snd_seq_event_t * ev, int direct, | |||
146 | snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); | 146 | snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags); |
147 | return 0; | 147 | return 0; |
148 | } | 148 | } |
149 | res = snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream); | 149 | snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream); |
150 | snd_midi_event_reset_decode(msynth->parser); | 150 | snd_midi_event_reset_decode(msynth->parser); |
151 | if (res < 0) | ||
152 | return res; | ||
153 | } else { | 151 | } else { |
154 | if (msynth->parser == NULL) | 152 | if (msynth->parser == NULL) |
155 | return -EIO; | 153 | return -EIO; |
156 | res = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev); | 154 | len = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev); |
157 | if (res < 0) | 155 | if (len < 0) |
158 | return res; | 156 | return 0; |
159 | if ((res = dump_midi(substream, msg, res)) < 0) { | 157 | if (dump_midi(substream, msg, len) < 0) |
160 | snd_midi_event_reset_decode(msynth->parser); | 158 | snd_midi_event_reset_decode(msynth->parser); |
161 | return res; | ||
162 | } | ||
163 | } | 159 | } |
164 | return 0; | 160 | return 0; |
165 | } | 161 | } |
diff --git a/sound/core/wrappers.c b/sound/core/wrappers.c index 9f393023c327..508e6d67ee19 100644 --- a/sound/core/wrappers.c +++ b/sound/core/wrappers.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | 28 | ||
29 | #ifdef CONFIG_SND_DEBUG_MEMORY | 29 | #ifdef CONFIG_SND_DEBUG_MEMORY |
30 | void *snd_wrapper_kmalloc(size_t size, int flags) | 30 | void *snd_wrapper_kmalloc(size_t size, unsigned int __nocast flags) |
31 | { | 31 | { |
32 | return kmalloc(size, flags); | 32 | return kmalloc(size, flags); |
33 | } | 33 | } |
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c index 18114713c3b3..4fc38bde34f4 100644 --- a/sound/drivers/vx/vx_uer.c +++ b/sound/drivers/vx/vx_uer.c | |||
@@ -162,34 +162,24 @@ static int vx_read_uer_status(vx_core_t *chip, int *mode) | |||
162 | 162 | ||
163 | static int vx_calc_clock_from_freq(vx_core_t *chip, int freq) | 163 | static int vx_calc_clock_from_freq(vx_core_t *chip, int freq) |
164 | { | 164 | { |
165 | #define XX_FECH48000 0x0000004B | 165 | int hexfreq; |
166 | #define XX_FECH32000 0x00000171 | 166 | |
167 | #define XX_FECH24000 0x0000024B | 167 | snd_assert(freq > 0, return 0); |
168 | #define XX_FECH16000 0x00000371 | 168 | |
169 | #define XX_FECH12000 0x0000044B | 169 | hexfreq = (28224000 * 10) / freq; |
170 | #define XX_FECH8000 0x00000571 | 170 | hexfreq = (hexfreq + 5) / 10; |
171 | #define XX_FECH44100 0x0000007F | 171 | |
172 | #define XX_FECH29400 0x0000016F | 172 | /* max freq = 55125 Hz */ |
173 | #define XX_FECH22050 0x0000027F | 173 | snd_assert(hexfreq > 0x00000200, return 0); |
174 | #define XX_FECH14000 0x000003EF | 174 | |
175 | #define XX_FECH11025 0x0000047F | 175 | if (hexfreq <= 0x03ff) |
176 | #define XX_FECH7350 0x000005BF | 176 | return hexfreq - 0x00000201; |
177 | 177 | if (hexfreq <= 0x07ff) | |
178 | switch (freq) { | 178 | return (hexfreq / 2) - 1; |
179 | case 48000: return XX_FECH48000; | 179 | if (hexfreq <= 0x0fff) |
180 | case 44100: return XX_FECH44100; | 180 | return (hexfreq / 4) + 0x000001ff; |
181 | case 32000: return XX_FECH32000; | 181 | |
182 | case 29400: return XX_FECH29400; | 182 | return 0x5fe; /* min freq = 6893 Hz */ |
183 | case 24000: return XX_FECH24000; | ||
184 | case 22050: return XX_FECH22050; | ||
185 | case 16000: return XX_FECH16000; | ||
186 | case 14000: return XX_FECH14000; | ||
187 | case 12000: return XX_FECH12000; | ||
188 | case 11025: return XX_FECH11025; | ||
189 | case 8000: return XX_FECH8000; | ||
190 | case 7350: return XX_FECH7350; | ||
191 | default: return freq; /* The value is already correct */ | ||
192 | } | ||
193 | } | 183 | } |
194 | 184 | ||
195 | 185 | ||
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index f5e6018ea3f4..5adde308a00f 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c | |||
@@ -554,7 +554,6 @@ int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags) | |||
554 | if (snd_pcm_running(ak4114->capture_substream)) { | 554 | if (snd_pcm_running(ak4114->capture_substream)) { |
555 | // printk("rate changed (%i <- %i)\n", runtime->rate, res); | 555 | // printk("rate changed (%i <- %i)\n", runtime->rate, res); |
556 | snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING); | 556 | snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING); |
557 | wake_up(&runtime->sleep); | ||
558 | res = 1; | 557 | res = 1; |
559 | } | 558 | } |
560 | snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags); | 559 | snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags); |
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 94bbd344be5e..a636d9ce3502 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c | |||
@@ -417,11 +417,13 @@ static int snd_gus_check_version(snd_gus_card_t * gus) | |||
417 | return 0; | 417 | return 0; |
418 | } | 418 | } |
419 | 419 | ||
420 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
420 | static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev) | 421 | static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev) |
421 | { | 422 | { |
422 | snd_gus_card_t *gus = seq_dev->private_data; | 423 | snd_gus_card_t *gus = seq_dev->private_data; |
423 | gus->seq_dev = NULL; | 424 | gus->seq_dev = NULL; |
424 | } | 425 | } |
426 | #endif | ||
425 | 427 | ||
426 | int snd_gus_initialize(snd_gus_card_t *gus) | 428 | int snd_gus_initialize(snd_gus_card_t *gus) |
427 | { | 429 | { |
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c index 0e13623f69f0..32379688eed4 100644 --- a/sound/isa/wavefront/wavefront_fx.c +++ b/sound/isa/wavefront/wavefront_fx.c | |||
@@ -34,7 +34,7 @@ | |||
34 | 34 | ||
35 | /* weird stuff, derived from port I/O tracing with dosemu */ | 35 | /* weird stuff, derived from port I/O tracing with dosemu */ |
36 | 36 | ||
37 | unsigned char page_zero[] __initdata = { | 37 | static unsigned char page_zero[] __initdata = { |
38 | 0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00, | 38 | 0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00, |
39 | 0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00, | 39 | 0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00, |
40 | 0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00, | 40 | 0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00, |
@@ -61,7 +61,7 @@ unsigned char page_zero[] __initdata = { | |||
61 | 0x1d, 0x02, 0xdf | 61 | 0x1d, 0x02, 0xdf |
62 | }; | 62 | }; |
63 | 63 | ||
64 | unsigned char page_one[] __initdata = { | 64 | static unsigned char page_one[] __initdata = { |
65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00, | 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00, |
66 | 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00, | 66 | 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00, |
67 | 0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, | 67 | 0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, |
@@ -88,7 +88,7 @@ unsigned char page_one[] __initdata = { | |||
88 | 0x60, 0x00, 0x1b | 88 | 0x60, 0x00, 0x1b |
89 | }; | 89 | }; |
90 | 90 | ||
91 | unsigned char page_two[] __initdata = { | 91 | static unsigned char page_two[] __initdata = { |
92 | 0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4, | 92 | 0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4, |
93 | 0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, | 93 | 0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, |
94 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 94 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -103,7 +103,7 @@ unsigned char page_two[] __initdata = { | |||
103 | 0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44 | 103 | 0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44 |
104 | }; | 104 | }; |
105 | 105 | ||
106 | unsigned char page_three[] __initdata = { | 106 | static unsigned char page_three[] __initdata = { |
107 | 0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06, | 107 | 0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06, |
108 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 108 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -118,7 +118,7 @@ unsigned char page_three[] __initdata = { | |||
118 | 0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40 | 118 | 0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40 |
119 | }; | 119 | }; |
120 | 120 | ||
121 | unsigned char page_four[] __initdata = { | 121 | static unsigned char page_four[] __initdata = { |
122 | 0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02, | 122 | 0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02, |
123 | 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 123 | 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
124 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 124 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -133,7 +133,7 @@ unsigned char page_four[] __initdata = { | |||
133 | 0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01 | 133 | 0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01 |
134 | }; | 134 | }; |
135 | 135 | ||
136 | unsigned char page_six[] __initdata = { | 136 | static unsigned char page_six[] __initdata = { |
137 | 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, | 137 | 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, |
138 | 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e, | 138 | 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e, |
139 | 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00, | 139 | 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00, |
@@ -154,7 +154,7 @@ unsigned char page_six[] __initdata = { | |||
154 | 0x80, 0x00, 0x7e, 0x80, 0x80 | 154 | 0x80, 0x00, 0x7e, 0x80, 0x80 |
155 | }; | 155 | }; |
156 | 156 | ||
157 | unsigned char page_seven[] __initdata = { | 157 | static unsigned char page_seven[] __initdata = { |
158 | 0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, | 158 | 0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, |
159 | 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, | 159 | 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, |
160 | 0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, | 160 | 0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, |
@@ -181,7 +181,7 @@ unsigned char page_seven[] __initdata = { | |||
181 | 0x00, 0x02, 0x00 | 181 | 0x00, 0x02, 0x00 |
182 | }; | 182 | }; |
183 | 183 | ||
184 | unsigned char page_zero_v2[] __initdata = { | 184 | static unsigned char page_zero_v2[] __initdata = { |
185 | 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 185 | 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
186 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 186 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
187 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 187 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -193,7 +193,7 @@ unsigned char page_zero_v2[] __initdata = { | |||
193 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 193 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
194 | }; | 194 | }; |
195 | 195 | ||
196 | unsigned char page_one_v2[] __initdata = { | 196 | static unsigned char page_one_v2[] __initdata = { |
197 | 0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, | 197 | 0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, |
198 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 198 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
199 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 199 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -205,21 +205,21 @@ unsigned char page_one_v2[] __initdata = { | |||
205 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 205 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
206 | }; | 206 | }; |
207 | 207 | ||
208 | unsigned char page_two_v2[] __initdata = { | 208 | static unsigned char page_two_v2[] __initdata = { |
209 | 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 209 | 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
210 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 210 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
211 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 211 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
212 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 212 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
213 | 0x00, 0x00, 0x00, 0x00 | 213 | 0x00, 0x00, 0x00, 0x00 |
214 | }; | 214 | }; |
215 | unsigned char page_three_v2[] __initdata = { | 215 | static unsigned char page_three_v2[] __initdata = { |
216 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 216 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
217 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 217 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
218 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 218 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
219 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 219 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
220 | 0x00, 0x00, 0x00, 0x00 | 220 | 0x00, 0x00, 0x00, 0x00 |
221 | }; | 221 | }; |
222 | unsigned char page_four_v2[] __initdata = { | 222 | static unsigned char page_four_v2[] __initdata = { |
223 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 223 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
224 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 224 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
225 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 225 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -227,7 +227,7 @@ unsigned char page_four_v2[] __initdata = { | |||
227 | 0x00, 0x00, 0x00, 0x00 | 227 | 0x00, 0x00, 0x00, 0x00 |
228 | }; | 228 | }; |
229 | 229 | ||
230 | unsigned char page_seven_v2[] __initdata = { | 230 | static unsigned char page_seven_v2[] __initdata = { |
231 | 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 231 | 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
232 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 232 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
233 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 233 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -239,7 +239,7 @@ unsigned char page_seven_v2[] __initdata = { | |||
239 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 239 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
240 | }; | 240 | }; |
241 | 241 | ||
242 | unsigned char mod_v2[] __initdata = { | 242 | static unsigned char mod_v2[] __initdata = { |
243 | 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, | 243 | 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, |
244 | 0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05, | 244 | 0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05, |
245 | 0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0, | 245 | 0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0, |
@@ -269,7 +269,7 @@ unsigned char mod_v2[] __initdata = { | |||
269 | 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01, | 269 | 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01, |
270 | 0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01 | 270 | 0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01 |
271 | }; | 271 | }; |
272 | unsigned char coefficients[] __initdata = { | 272 | static unsigned char coefficients[] __initdata = { |
273 | 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03, | 273 | 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03, |
274 | 0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, | 274 | 0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, |
275 | 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01, | 275 | 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01, |
@@ -305,14 +305,14 @@ unsigned char coefficients[] __initdata = { | |||
305 | 0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02, | 305 | 0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02, |
306 | 0xba | 306 | 0xba |
307 | }; | 307 | }; |
308 | unsigned char coefficients2[] __initdata = { | 308 | static unsigned char coefficients2[] __initdata = { |
309 | 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f, | 309 | 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f, |
310 | 0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d, | 310 | 0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d, |
311 | 0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07, | 311 | 0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07, |
312 | 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, | 312 | 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, |
313 | 0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00 | 313 | 0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00 |
314 | }; | 314 | }; |
315 | unsigned char coefficients3[] __initdata = { | 315 | static unsigned char coefficients3[] __initdata = { |
316 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00, | 316 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00, |
317 | 0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc, | 317 | 0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc, |
318 | 0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01, | 318 | 0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01, |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index a4b72cd2eea0..6983eea226da 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -367,6 +367,7 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value) | |||
367 | ac97->regs[reg] = value; | 367 | ac97->regs[reg] = value; |
368 | ac97->bus->ops->write(ac97, reg, value); | 368 | ac97->bus->ops->write(ac97, reg, value); |
369 | } | 369 | } |
370 | set_bit(reg, ac97->reg_accessed); | ||
370 | up(&ac97->reg_mutex); | 371 | up(&ac97->reg_mutex); |
371 | return change; | 372 | return change; |
372 | } | 373 | } |
@@ -410,6 +411,7 @@ int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg, | |||
410 | ac97->regs[reg] = new; | 411 | ac97->regs[reg] = new; |
411 | ac97->bus->ops->write(ac97, reg, new); | 412 | ac97->bus->ops->write(ac97, reg, new); |
412 | } | 413 | } |
414 | set_bit(reg, ac97->reg_accessed); | ||
413 | return change; | 415 | return change; |
414 | } | 416 | } |
415 | 417 | ||
@@ -1076,6 +1078,11 @@ static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max | |||
1076 | for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { | 1078 | for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { |
1077 | unsigned short val; | 1079 | unsigned short val; |
1078 | snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8)); | 1080 | snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8)); |
1081 | /* Do the read twice due to buffers on some ac97 codecs. | ||
1082 | * e.g. The STAC9704 returns exactly what you wrote the the register | ||
1083 | * if you read it immediately. This causes the detect routine to fail. | ||
1084 | */ | ||
1085 | val = snd_ac97_read(ac97, reg); | ||
1079 | val = snd_ac97_read(ac97, reg); | 1086 | val = snd_ac97_read(ac97, reg); |
1080 | if (! *lo_max && (val & 0x7f) == cbit[i]) | 1087 | if (! *lo_max && (val & 0x7f) == cbit[i]) |
1081 | *lo_max = max[i]; | 1088 | *lo_max = max[i]; |
@@ -2224,7 +2231,7 @@ void snd_ac97_restore_iec958(ac97_t *ac97) | |||
2224 | */ | 2231 | */ |
2225 | void snd_ac97_resume(ac97_t *ac97) | 2232 | void snd_ac97_resume(ac97_t *ac97) |
2226 | { | 2233 | { |
2227 | int i; | 2234 | unsigned long end_time; |
2228 | 2235 | ||
2229 | if (ac97->bus->ops->reset) { | 2236 | if (ac97->bus->ops->reset) { |
2230 | ac97->bus->ops->reset(ac97); | 2237 | ac97->bus->ops->reset(ac97); |
@@ -2242,26 +2249,26 @@ void snd_ac97_resume(ac97_t *ac97) | |||
2242 | snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]); | 2249 | snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]); |
2243 | if (ac97_is_audio(ac97)) { | 2250 | if (ac97_is_audio(ac97)) { |
2244 | ac97->bus->ops->write(ac97, AC97_MASTER, 0x8101); | 2251 | ac97->bus->ops->write(ac97, AC97_MASTER, 0x8101); |
2245 | for (i = HZ/10; i >= 0; i--) { | 2252 | end_time = jiffies + msecs_to_jiffies(100); |
2253 | do { | ||
2246 | if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101) | 2254 | if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101) |
2247 | break; | 2255 | break; |
2248 | set_current_state(TASK_UNINTERRUPTIBLE); | 2256 | set_current_state(TASK_UNINTERRUPTIBLE); |
2249 | schedule_timeout(1); | 2257 | schedule_timeout(1); |
2250 | } | 2258 | } while (time_after_eq(end_time, jiffies)); |
2251 | /* FIXME: extra delay */ | 2259 | /* FIXME: extra delay */ |
2252 | ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000); | 2260 | ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000); |
2253 | if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) { | 2261 | if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) |
2254 | set_current_state(TASK_UNINTERRUPTIBLE); | 2262 | msleep(250); |
2255 | schedule_timeout(HZ/4); | ||
2256 | } | ||
2257 | } else { | 2263 | } else { |
2258 | for (i = HZ/10; i >= 0; i--) { | 2264 | end_time = jiffies + msecs_to_jiffies(100); |
2265 | do { | ||
2259 | unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID); | 2266 | unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID); |
2260 | if (val != 0xffff && (val & 1) != 0) | 2267 | if (val != 0xffff && (val & 1) != 0) |
2261 | break; | 2268 | break; |
2262 | set_current_state(TASK_UNINTERRUPTIBLE); | 2269 | set_current_state(TASK_UNINTERRUPTIBLE); |
2263 | schedule_timeout(1); | 2270 | schedule_timeout(1); |
2264 | } | 2271 | } while (time_after_eq(end_time, jiffies)); |
2265 | } | 2272 | } |
2266 | __reset_ready: | 2273 | __reset_ready: |
2267 | 2274 | ||
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index a15eb8522b7c..66edc857d3e6 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -1528,6 +1528,9 @@ static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = { | |||
1528 | }, | 1528 | }, |
1529 | AC97_SURROUND_JACK_MODE_CTL, | 1529 | AC97_SURROUND_JACK_MODE_CTL, |
1530 | AC97_CHANNEL_MODE_CTL, | 1530 | AC97_CHANNEL_MODE_CTL, |
1531 | |||
1532 | AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0), | ||
1533 | AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0), | ||
1531 | }; | 1534 | }; |
1532 | 1535 | ||
1533 | static int patch_ad1888_specific(ac97_t *ac97) | 1536 | static int patch_ad1888_specific(ac97_t *ac97) |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index eb5c36d31a52..f08ae71f902d 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -399,7 +399,7 @@ static int snd_ali_codec_ready( ali_t *codec, | |||
399 | unsigned long end_time; | 399 | unsigned long end_time; |
400 | unsigned int res; | 400 | unsigned int res; |
401 | 401 | ||
402 | end_time = jiffies + 10 * (HZ >> 2); | 402 | end_time = jiffies + 10 * msecs_to_jiffies(250); |
403 | do { | 403 | do { |
404 | res = snd_ali_5451_peek(codec,port); | 404 | res = snd_ali_5451_peek(codec,port); |
405 | if (! (res & 0x8000)) | 405 | if (! (res & 0x8000)) |
@@ -422,7 +422,7 @@ static int snd_ali_stimer_ready(ali_t *codec, int sched) | |||
422 | dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER); | 422 | dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER); |
423 | dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); | 423 | dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); |
424 | 424 | ||
425 | end_time = jiffies + 10 * (HZ >> 2); | 425 | end_time = jiffies + 10 * msecs_to_jiffies(250); |
426 | do { | 426 | do { |
427 | dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); | 427 | dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER); |
428 | if (dwChk2 != dwChk1) | 428 | if (dwChk2 != dwChk1) |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index a6b4b8d589fd..8d2002951bd7 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -265,6 +265,7 @@ struct snd_atiixp { | |||
265 | */ | 265 | */ |
266 | static struct pci_device_id snd_atiixp_ids[] = { | 266 | static struct pci_device_id snd_atiixp_ids[] = { |
267 | { 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */ | 267 | { 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */ |
268 | { 0x1002, 0x4378, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */ | ||
268 | { 0, } | 269 | { 0, } |
269 | }; | 270 | }; |
270 | 271 | ||
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 4725b4a010be..f5a4ac1ceef9 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -306,7 +306,7 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
306 | #define CM_REG_FM_PCI 0x50 | 306 | #define CM_REG_FM_PCI 0x50 |
307 | 307 | ||
308 | /* | 308 | /* |
309 | * for CMI-8338 .. this is not valid for CMI-8738. | 309 | * access from SB-mixer port |
310 | */ | 310 | */ |
311 | #define CM_REG_EXTENT_IND 0xf0 | 311 | #define CM_REG_EXTENT_IND 0xf0 |
312 | #define CM_VPHONE_MASK 0xe0 /* Phone volume control (0-3) << 5 */ | 312 | #define CM_VPHONE_MASK 0xe0 /* Phone volume control (0-3) << 5 */ |
@@ -315,6 +315,7 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); | |||
315 | #define CM_VSPKM 0x08 /* Speaker mute control, default high */ | 315 | #define CM_VSPKM 0x08 /* Speaker mute control, default high */ |
316 | #define CM_RLOOPREN 0x04 /* Rec. R-channel enable */ | 316 | #define CM_RLOOPREN 0x04 /* Rec. R-channel enable */ |
317 | #define CM_RLOOPLEN 0x02 /* Rec. L-channel enable */ | 317 | #define CM_RLOOPLEN 0x02 /* Rec. L-channel enable */ |
318 | #define CM_VADMIC3 0x01 /* Mic record boost */ | ||
318 | 319 | ||
319 | /* | 320 | /* |
320 | * CMI-8338 spec ver 0.5 (this is not valid for CMI-8738): | 321 | * CMI-8338 spec ver 0.5 (this is not valid for CMI-8738): |
@@ -2135,8 +2136,12 @@ static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = { | |||
2135 | CMIPCI_MIXER_VOL_STEREO("Aux Playback Volume", CM_REG_AUX_VOL, 4, 0, 15), | 2136 | CMIPCI_MIXER_VOL_STEREO("Aux Playback Volume", CM_REG_AUX_VOL, 4, 0, 15), |
2136 | CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 0), | 2137 | CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 0), |
2137 | CMIPCI_MIXER_SW_STEREO("Aux Capture Switch", CM_REG_MIXER2, CM_RAUXLEN_SHIFT, CM_RAUXREN_SHIFT, 0), | 2138 | CMIPCI_MIXER_SW_STEREO("Aux Capture Switch", CM_REG_MIXER2, CM_RAUXLEN_SHIFT, CM_RAUXREN_SHIFT, 0), |
2138 | CMIPCI_MIXER_SW_MONO("Mic Boost", CM_REG_MIXER2, CM_MICGAINZ_SHIFT, 1), | 2139 | CMIPCI_MIXER_SW_MONO("Mic Boost Playback Switch", CM_REG_MIXER2, CM_MICGAINZ_SHIFT, 1), |
2139 | CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), | 2140 | CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), |
2141 | CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7), | ||
2142 | CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0), | ||
2143 | CMIPCI_DOUBLE("PC Speaker Playnack Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), | ||
2144 | CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0), | ||
2140 | }; | 2145 | }; |
2141 | 2146 | ||
2142 | /* | 2147 | /* |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index fd4c50c88bc9..ff28af1f658e 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -2400,8 +2400,7 @@ static void snd_cs46xx_codec_reset (ac97_t * ac97) | |||
2400 | if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05) | 2400 | if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05) |
2401 | return; | 2401 | return; |
2402 | 2402 | ||
2403 | set_current_state(TASK_UNINTERRUPTIBLE); | 2403 | msleep(10); |
2404 | schedule_timeout(HZ/100); | ||
2405 | } while (time_after_eq(end_time, jiffies)); | 2404 | } while (time_after_eq(end_time, jiffies)); |
2406 | 2405 | ||
2407 | snd_printk("CS46xx secondary codec dont respond!\n"); | 2406 | snd_printk("CS46xx secondary codec dont respond!\n"); |
@@ -2435,8 +2434,7 @@ static int __devinit cs46xx_detect_codec(cs46xx_t *chip, int codec) | |||
2435 | err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]); | 2434 | err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]); |
2436 | return err; | 2435 | return err; |
2437 | } | 2436 | } |
2438 | set_current_state(TASK_INTERRUPTIBLE); | 2437 | msleep(10); |
2439 | schedule_timeout(HZ/100); | ||
2440 | } | 2438 | } |
2441 | snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec); | 2439 | snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec); |
2442 | return -ENXIO; | 2440 | return -ENXIO; |
@@ -3018,8 +3016,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip) | |||
3018 | /* | 3016 | /* |
3019 | * Wait until the PLL has stabilized. | 3017 | * Wait until the PLL has stabilized. |
3020 | */ | 3018 | */ |
3021 | set_current_state(TASK_UNINTERRUPTIBLE); | 3019 | msleep(100); |
3022 | schedule_timeout(HZ/10); /* 100ms */ | ||
3023 | 3020 | ||
3024 | /* | 3021 | /* |
3025 | * Turn on clocking of the core so that we can setup the serial ports. | 3022 | * Turn on clocking of the core so that we can setup the serial ports. |
@@ -3072,8 +3069,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip) | |||
3072 | */ | 3069 | */ |
3073 | if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY) | 3070 | if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY) |
3074 | goto ok1; | 3071 | goto ok1; |
3075 | set_current_state(TASK_UNINTERRUPTIBLE); | 3072 | msleep(10); |
3076 | schedule_timeout((HZ+99)/100); | ||
3077 | } | 3073 | } |
3078 | 3074 | ||
3079 | 3075 | ||
@@ -3122,8 +3118,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip) | |||
3122 | */ | 3118 | */ |
3123 | if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) | 3119 | if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4)) |
3124 | goto ok2; | 3120 | goto ok2; |
3125 | set_current_state(TASK_UNINTERRUPTIBLE); | 3121 | msleep(10); |
3126 | schedule_timeout((HZ+99)/100); | ||
3127 | } | 3122 | } |
3128 | 3123 | ||
3129 | #ifndef CONFIG_SND_CS46XX_NEW_DSP | 3124 | #ifndef CONFIG_SND_CS46XX_NEW_DSP |
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 2085a998eaeb..b17142cabead 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -52,6 +52,7 @@ static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; | |||
52 | static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; | 52 | static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; |
53 | static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; | 53 | static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; |
54 | static int enable_ir[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 54 | static int enable_ir[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; |
55 | static uint subsystem[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* Force card subsystem model */ | ||
55 | 56 | ||
56 | module_param_array(index, int, NULL, 0444); | 57 | module_param_array(index, int, NULL, 0444); |
57 | MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); | 58 | MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); |
@@ -71,7 +72,8 @@ module_param_array(max_buffer_size, int, NULL, 0444); | |||
71 | MODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB."); | 72 | MODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB."); |
72 | module_param_array(enable_ir, bool, NULL, 0444); | 73 | module_param_array(enable_ir, bool, NULL, 0444); |
73 | MODULE_PARM_DESC(enable_ir, "Enable IR."); | 74 | MODULE_PARM_DESC(enable_ir, "Enable IR."); |
74 | 75 | module_param_array(subsystem, uint, NULL, 0444); | |
76 | MODULE_PARM_DESC(subsystem, "Force card subsystem model."); | ||
75 | /* | 77 | /* |
76 | * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 | 78 | * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 |
77 | */ | 79 | */ |
@@ -122,7 +124,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, | |||
122 | max_buffer_size[dev] = 1024; | 124 | max_buffer_size[dev] = 1024; |
123 | if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], | 125 | if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], |
124 | (long)max_buffer_size[dev] * 1024 * 1024, | 126 | (long)max_buffer_size[dev] * 1024 * 1024, |
125 | enable_ir[dev], | 127 | enable_ir[dev], subsystem[dev], |
126 | &emu)) < 0) { | 128 | &emu)) < 0) { |
127 | snd_card_free(card); | 129 | snd_card_free(card); |
128 | return err; | 130 | return err; |
@@ -140,7 +142,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, | |||
140 | return err; | 142 | return err; |
141 | } | 143 | } |
142 | /* This stores the periods table. */ | 144 | /* This stores the periods table. */ |
143 | if (emu->audigy && emu->revision == 4) { /* P16V */ | 145 | if (emu->card_capabilities->ca0151_chip) { /* P16V */ |
144 | if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &emu->p16v_buffer) < 0) { | 146 | if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &emu->p16v_buffer) < 0) { |
145 | snd_p16v_free(emu); | 147 | snd_p16v_free(emu); |
146 | return -ENOMEM; | 148 | return -ENOMEM; |
@@ -161,7 +163,7 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci, | |||
161 | snd_card_free(card); | 163 | snd_card_free(card); |
162 | return err; | 164 | return err; |
163 | } | 165 | } |
164 | if (emu->audigy && emu->revision == 4) { /* P16V */ | 166 | if (emu->card_capabilities->ca0151_chip) { /* P16V */ |
165 | if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) { | 167 | if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) { |
166 | snd_card_free(card); | 168 | snd_card_free(card); |
167 | return err; | 169 | return err; |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index a341e758acde..746b51ef3966 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -191,7 +191,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) | |||
191 | /* Set playback routing. */ | 191 | /* Set playback routing. */ |
192 | snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4); | 192 | snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4); |
193 | } | 193 | } |
194 | if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */ | 194 | if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ |
195 | /* Hacks for Alice3 to work independent of haP16V driver */ | 195 | /* Hacks for Alice3 to work independent of haP16V driver */ |
196 | u32 tmp; | 196 | u32 tmp; |
197 | 197 | ||
@@ -253,6 +253,8 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) | |||
253 | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); | 253 | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); |
254 | else | 254 | else |
255 | outl(HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); | 255 | outl(HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); |
256 | /* FIXME: Remove all these emu->model and replace it with a card recognition parameter, | ||
257 | * e.g. card_capabilities->joystick */ | ||
256 | } else if (emu->model == 0x20 || | 258 | } else if (emu->model == 0x20 || |
257 | emu->model == 0xc400 || | 259 | emu->model == 0xc400 || |
258 | (emu->model == 0x21 && emu->revision < 6)) | 260 | (emu->model == 0x21 && emu->revision < 6)) |
@@ -299,12 +301,12 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir) | |||
299 | if (emu->audigy) { | 301 | if (emu->audigy) { |
300 | outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); | 302 | outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); |
301 | 303 | ||
302 | if (emu->revision == 4) { /* audigy2 */ | 304 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ |
303 | /* Unmute Analog now. Set GPO6 to 1 for Apollo. | 305 | /* Unmute Analog now. Set GPO6 to 1 for Apollo. |
304 | * This has to be done after init ALice3 I2SOut beyond 48KHz. | 306 | * This has to be done after init ALice3 I2SOut beyond 48KHz. |
305 | * So, sequence is important. */ | 307 | * So, sequence is important. */ |
306 | outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); | 308 | outl(inl(emu->port + A_IOCFG) | 0x0040, emu->port + A_IOCFG); |
307 | } else if (emu->serial == 0x10011102) { /* audigy2 value */ | 309 | } else if (emu->card_capabilities->ca0108_chip) { /* audigy2 value */ |
308 | /* Unmute Analog now. */ | 310 | /* Unmute Analog now. */ |
309 | outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); | 311 | outl(inl(emu->port + A_IOCFG) | 0x0060, emu->port + A_IOCFG); |
310 | } else { | 312 | } else { |
@@ -614,6 +616,7 @@ static int snd_emu10k1_dev_free(snd_device_t *device) | |||
614 | 616 | ||
615 | static emu_chip_details_t emu_chip_details[] = { | 617 | static emu_chip_details_t emu_chip_details[] = { |
616 | /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ | 618 | /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ |
619 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | ||
617 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, | 620 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, |
618 | .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", | 621 | .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", |
619 | .id = "Audigy2", | 622 | .id = "Audigy2", |
@@ -627,6 +630,14 @@ static emu_chip_details_t emu_chip_details[] = { | |||
627 | .emu10k2_chip = 1, | 630 | .emu10k2_chip = 1, |
628 | .ca0108_chip = 1, | 631 | .ca0108_chip = 1, |
629 | .ac97_chip = 1} , | 632 | .ac97_chip = 1} , |
633 | /* Tested by James@superbug.co.uk 8th July 2005. No sound available yet. */ | ||
634 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, | ||
635 | .driver = "Audigy2", .name = "E-mu 1212m [4001]", | ||
636 | .id = "EMU1212m", | ||
637 | .emu10k2_chip = 1, | ||
638 | .ca0102_chip = 1, | ||
639 | .ecard = 1} , | ||
640 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | ||
630 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, | 641 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, |
631 | .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", | 642 | .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", |
632 | .id = "Audigy2", | 643 | .id = "Audigy2", |
@@ -687,18 +698,18 @@ static emu_chip_details_t emu_chip_details[] = { | |||
687 | .ca0151_chip = 1, | 698 | .ca0151_chip = 1, |
688 | .spdif_bug = 1, | 699 | .spdif_bug = 1, |
689 | .ac97_chip = 1} , | 700 | .ac97_chip = 1} , |
690 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10020052, | 701 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102, |
691 | .driver = "Audigy", .name = "Audigy 1 ES [SB0160]", | 702 | .driver = "Audigy", .name = "Audigy 1 [SB0090]", |
692 | .id = "Audigy", | 703 | .id = "Audigy", |
693 | .emu10k2_chip = 1, | 704 | .emu10k2_chip = 1, |
694 | .ca0102_chip = 1, | 705 | .ca0102_chip = 1, |
695 | .spdif_bug = 1, | ||
696 | .ac97_chip = 1} , | 706 | .ac97_chip = 1} , |
697 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102, | 707 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102, |
698 | .driver = "Audigy", .name = "Audigy 1 [SB0090]", | 708 | .driver = "Audigy", .name = "Audigy 1 ES [SB0160]", |
699 | .id = "Audigy", | 709 | .id = "Audigy", |
700 | .emu10k2_chip = 1, | 710 | .emu10k2_chip = 1, |
701 | .ca0102_chip = 1, | 711 | .ca0102_chip = 1, |
712 | .spdif_bug = 1, | ||
702 | .ac97_chip = 1} , | 713 | .ac97_chip = 1} , |
703 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102, | 714 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102, |
704 | .driver = "Audigy", .name = "Audigy 1 [SB0090]", | 715 | .driver = "Audigy", .name = "Audigy 1 [SB0090]", |
@@ -712,54 +723,49 @@ static emu_chip_details_t emu_chip_details[] = { | |||
712 | .emu10k2_chip = 1, | 723 | .emu10k2_chip = 1, |
713 | .ca0102_chip = 1, | 724 | .ca0102_chip = 1, |
714 | .ac97_chip = 1} , | 725 | .ac97_chip = 1} , |
715 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, | 726 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102, |
716 | .driver = "EMU10K1", .name = "E-mu APS [4001]", | 727 | .driver = "EMU10K1", .name = "SBLive! [SB0105]", |
717 | .id = "APS", | ||
718 | .emu10k1_chip = 1, | ||
719 | .ecard = 1} , | ||
720 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, | ||
721 | .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]", | ||
722 | .id = "Live", | 728 | .id = "Live", |
723 | .emu10k1_chip = 1, | 729 | .emu10k1_chip = 1, |
724 | .ac97_chip = 1, | 730 | .ac97_chip = 1, |
725 | .sblive51 = 1} , | 731 | .sblive51 = 1} , |
726 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, | 732 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102, |
727 | .driver = "EMU10K1", .name = "SB Live 5.1", | 733 | .driver = "EMU10K1", .name = "SBLive! Value [SB0103]", |
728 | .id = "Live", | 734 | .id = "Live", |
729 | .emu10k1_chip = 1, | 735 | .emu10k1_chip = 1, |
730 | .ac97_chip = 1, | 736 | .ac97_chip = 1, |
731 | .sblive51 = 1} , | 737 | .sblive51 = 1} , |
732 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, | 738 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102, |
733 | .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]", | 739 | .driver = "EMU10K1", .name = "SBLive! Value [SB0101]", |
734 | .id = "Live", | ||
735 | .emu10k1_chip = 1, | ||
736 | .ac97_chip = 1} , | ||
737 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102, | ||
738 | .driver = "EMU10K1", .name = "SBLive! [CT4620]", | ||
739 | .id = "Live", | 740 | .id = "Live", |
740 | .emu10k1_chip = 1, | 741 | .emu10k1_chip = 1, |
741 | .ac97_chip = 1, | 742 | .ac97_chip = 1, |
742 | .sblive51 = 1} , | 743 | .sblive51 = 1} , |
743 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102, | 744 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, |
744 | .driver = "EMU10K1", .name = "SBLive! Value [CT4670]", | 745 | .driver = "EMU10K1", .name = "SB Live 5.1", |
745 | .id = "Live", | 746 | .id = "Live", |
746 | .emu10k1_chip = 1, | 747 | .emu10k1_chip = 1, |
747 | .ac97_chip = 1, | 748 | .ac97_chip = 1, |
748 | .sblive51 = 1} , | 749 | .sblive51 = 1} , |
749 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102, | 750 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, |
750 | .driver = "EMU10K1", .name = "SBLive! Value [CT4780]", | 751 | .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]", |
751 | .id = "Live", | 752 | .id = "Live", |
752 | .emu10k1_chip = 1, | 753 | .emu10k1_chip = 1, |
753 | .ac97_chip = 1, | 754 | .ac97_chip = 1, |
754 | .sblive51 = 1} , | 755 | .sblive51 = 1} , |
755 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102, | 756 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102, |
756 | .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", | 757 | .driver = "EMU10K1", .name = "SBLive! Value [CT4850]", |
757 | .id = "Live", | 758 | .id = "Live", |
758 | .emu10k1_chip = 1, | 759 | .emu10k1_chip = 1, |
759 | .ac97_chip = 1, | 760 | .ac97_chip = 1, |
760 | .sblive51 = 1} , | 761 | .sblive51 = 1} , |
761 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102, | 762 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, |
762 | .driver = "EMU10K1", .name = "SBLive! Value [CT4830]", | 763 | .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]", |
764 | .id = "Live", | ||
765 | .emu10k1_chip = 1, | ||
766 | .ac97_chip = 1} , | ||
767 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102, | ||
768 | .driver = "EMU10K1", .name = "SBLive! Value [CT4871]", | ||
763 | .id = "Live", | 769 | .id = "Live", |
764 | .emu10k1_chip = 1, | 770 | .emu10k1_chip = 1, |
765 | .ac97_chip = 1, | 771 | .ac97_chip = 1, |
@@ -770,50 +776,50 @@ static emu_chip_details_t emu_chip_details[] = { | |||
770 | .emu10k1_chip = 1, | 776 | .emu10k1_chip = 1, |
771 | .ac97_chip = 1, | 777 | .ac97_chip = 1, |
772 | .sblive51 = 1} , | 778 | .sblive51 = 1} , |
773 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102, | 779 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102, |
774 | .driver = "EMU10K1", .name = "SBLive! Value [CT4832]", | 780 | .driver = "EMU10K1", .name = "SBLive! Value [CT4870]", |
775 | .id = "Live", | 781 | .id = "Live", |
776 | .emu10k1_chip = 1, | 782 | .emu10k1_chip = 1, |
777 | .ac97_chip = 1, | 783 | .ac97_chip = 1, |
778 | .sblive51 = 1} , | 784 | .sblive51 = 1} , |
779 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102, | 785 | /* Tested by James@superbug.co.uk 3rd July 2005 */ |
780 | .driver = "EMU10K1", .name = "SBLive! Value [CT4850]", | 786 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102, |
787 | .driver = "EMU10K1", .name = "SBLive! Value [CT4832]", | ||
781 | .id = "Live", | 788 | .id = "Live", |
782 | .emu10k1_chip = 1, | 789 | .emu10k1_chip = 1, |
783 | .ac97_chip = 1, | 790 | .ac97_chip = 1, |
784 | .sblive51 = 1} , | 791 | .sblive51 = 1} , |
785 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102, | 792 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102, |
786 | .driver = "EMU10K1", .name = "SBLive! Value [CT4870]", | 793 | .driver = "EMU10K1", .name = "SBLive! Value [CT4830]", |
787 | .id = "Live", | 794 | .id = "Live", |
788 | .emu10k1_chip = 1, | 795 | .emu10k1_chip = 1, |
789 | .ac97_chip = 1, | 796 | .ac97_chip = 1, |
790 | .sblive51 = 1} , | 797 | .sblive51 = 1} , |
791 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102, | 798 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102, |
792 | .driver = "EMU10K1", .name = "SBLive! Value [CT4871]", | 799 | .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", |
793 | .id = "Live", | 800 | .id = "Live", |
794 | .emu10k1_chip = 1, | 801 | .emu10k1_chip = 1, |
795 | .ac97_chip = 1, | 802 | .ac97_chip = 1, |
796 | .sblive51 = 1} , | 803 | .sblive51 = 1} , |
797 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, | 804 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102, |
798 | .driver = "EMU10K1", .name = "SBLive! Value [SB0060]", | 805 | .driver = "EMU10K1", .name = "SBLive! Value [CT4780]", |
799 | .id = "Live", | 806 | .id = "Live", |
800 | .emu10k1_chip = 1, | 807 | .emu10k1_chip = 1, |
801 | .ac97_chip = 1, | 808 | .ac97_chip = 1, |
802 | .sblive51 = 1} , | 809 | .sblive51 = 1} , |
803 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102, | 810 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, |
804 | .driver = "EMU10K1", .name = "SBLive! Value [SB0101]", | 811 | .driver = "EMU10K1", .name = "E-mu APS [4001]", |
805 | .id = "Live", | 812 | .id = "APS", |
806 | .emu10k1_chip = 1, | 813 | .emu10k1_chip = 1, |
807 | .ac97_chip = 1, | 814 | .ecard = 1} , |
808 | .sblive51 = 1} , | 815 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102, |
809 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102, | 816 | .driver = "EMU10K1", .name = "SBLive! [CT4620]", |
810 | .driver = "EMU10K1", .name = "SBLive! Value [SB0103]", | ||
811 | .id = "Live", | 817 | .id = "Live", |
812 | .emu10k1_chip = 1, | 818 | .emu10k1_chip = 1, |
813 | .ac97_chip = 1, | 819 | .ac97_chip = 1, |
814 | .sblive51 = 1} , | 820 | .sblive51 = 1} , |
815 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102, | 821 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102, |
816 | .driver = "EMU10K1", .name = "SBLive! [SB0105]", | 822 | .driver = "EMU10K1", .name = "SBLive! Value [CT4670]", |
817 | .id = "Live", | 823 | .id = "Live", |
818 | .emu10k1_chip = 1, | 824 | .emu10k1_chip = 1, |
819 | .ac97_chip = 1, | 825 | .ac97_chip = 1, |
@@ -833,6 +839,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
833 | unsigned short extout_mask, | 839 | unsigned short extout_mask, |
834 | long max_cache_bytes, | 840 | long max_cache_bytes, |
835 | int enable_ir, | 841 | int enable_ir, |
842 | uint subsystem, | ||
836 | emu10k1_t ** remu) | 843 | emu10k1_t ** remu) |
837 | { | 844 | { |
838 | emu10k1_t *emu; | 845 | emu10k1_t *emu; |
@@ -878,10 +885,16 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
878 | 885 | ||
879 | for (c = emu_chip_details; c->vendor; c++) { | 886 | for (c = emu_chip_details; c->vendor; c++) { |
880 | if (c->vendor == pci->vendor && c->device == pci->device) { | 887 | if (c->vendor == pci->vendor && c->device == pci->device) { |
881 | if (c->subsystem && c->subsystem != emu->serial) | 888 | if (subsystem) { |
882 | continue; | 889 | if (c->subsystem && (c->subsystem == subsystem) ) { |
883 | if (c->revision && c->revision != emu->revision) | 890 | break; |
884 | continue; | 891 | } else continue; |
892 | } else { | ||
893 | if (c->subsystem && (c->subsystem != emu->serial) ) | ||
894 | continue; | ||
895 | if (c->revision && c->revision != emu->revision) | ||
896 | continue; | ||
897 | } | ||
885 | break; | 898 | break; |
886 | } | 899 | } |
887 | } | 900 | } |
@@ -892,10 +905,14 @@ int __devinit snd_emu10k1_create(snd_card_t * card, | |||
892 | return -ENOENT; | 905 | return -ENOENT; |
893 | } | 906 | } |
894 | emu->card_capabilities = c; | 907 | emu->card_capabilities = c; |
895 | if (c->subsystem != 0) | 908 | if (c->subsystem && !subsystem) |
896 | snd_printdd("Sound card name=%s\n", c->name); | 909 | snd_printdd("Sound card name=%s\n", c->name); |
897 | else | 910 | else if (subsystem) |
898 | snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial); | 911 | snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x. Forced to subsytem=0x%x\n", |
912 | c->name, pci->vendor, pci->device, emu->serial, c->subsystem); | ||
913 | else | ||
914 | snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x.\n", | ||
915 | c->name, pci->vendor, pci->device, emu->serial); | ||
899 | 916 | ||
900 | if (!*card->id && c->id) { | 917 | if (!*card->id && c->id) { |
901 | int i, n = 0; | 918 | int i, n = 0; |
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index 98f980189892..a1691330d3b6 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c | |||
@@ -822,7 +822,7 @@ static int snd_p16v_volume_put_analog_unknown(snd_kcontrol_t * kcontrol, | |||
822 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_front = | 822 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_front = |
823 | { | 823 | { |
824 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 824 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
825 | .name = "HD Analog Front Volume", | 825 | .name = "HD Analog Front Playback Volume", |
826 | .info = snd_p16v_volume_info, | 826 | .info = snd_p16v_volume_info, |
827 | .get = snd_p16v_volume_get_analog_front, | 827 | .get = snd_p16v_volume_get_analog_front, |
828 | .put = snd_p16v_volume_put_analog_front | 828 | .put = snd_p16v_volume_put_analog_front |
@@ -831,7 +831,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_front = | |||
831 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe = | 831 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe = |
832 | { | 832 | { |
833 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 833 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
834 | .name = "HD Analog Center/LFE Volume", | 834 | .name = "HD Analog Center/LFE Playback Volume", |
835 | .info = snd_p16v_volume_info, | 835 | .info = snd_p16v_volume_info, |
836 | .get = snd_p16v_volume_get_analog_center_lfe, | 836 | .get = snd_p16v_volume_get_analog_center_lfe, |
837 | .put = snd_p16v_volume_put_analog_center_lfe | 837 | .put = snd_p16v_volume_put_analog_center_lfe |
@@ -840,7 +840,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe = | |||
840 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown = | 840 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown = |
841 | { | 841 | { |
842 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 842 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
843 | .name = "HD Analog Unknown Volume", | 843 | .name = "HD Analog Unknown Playback Volume", |
844 | .info = snd_p16v_volume_info, | 844 | .info = snd_p16v_volume_info, |
845 | .get = snd_p16v_volume_get_analog_unknown, | 845 | .get = snd_p16v_volume_get_analog_unknown, |
846 | .put = snd_p16v_volume_put_analog_unknown | 846 | .put = snd_p16v_volume_put_analog_unknown |
@@ -849,7 +849,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown = | |||
849 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear = | 849 | static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear = |
850 | { | 850 | { |
851 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 851 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
852 | .name = "HD Analog Rear Volume", | 852 | .name = "HD Analog Rear Playback Volume", |
853 | .info = snd_p16v_volume_info, | 853 | .info = snd_p16v_volume_info, |
854 | .get = snd_p16v_volume_get_analog_rear, | 854 | .get = snd_p16v_volume_get_analog_rear, |
855 | .put = snd_p16v_volume_put_analog_rear | 855 | .put = snd_p16v_volume_put_analog_rear |
@@ -858,7 +858,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear = | |||
858 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front = | 858 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front = |
859 | { | 859 | { |
860 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 860 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
861 | .name = "HD SPDIF Front Volume", | 861 | .name = "HD SPDIF Front Playback Volume", |
862 | .info = snd_p16v_volume_info, | 862 | .info = snd_p16v_volume_info, |
863 | .get = snd_p16v_volume_get_spdif_front, | 863 | .get = snd_p16v_volume_get_spdif_front, |
864 | .put = snd_p16v_volume_put_spdif_front | 864 | .put = snd_p16v_volume_put_spdif_front |
@@ -867,7 +867,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front = | |||
867 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe = | 867 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe = |
868 | { | 868 | { |
869 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 869 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
870 | .name = "HD SPDIF Center/LFE Volume", | 870 | .name = "HD SPDIF Center/LFE Playback Volume", |
871 | .info = snd_p16v_volume_info, | 871 | .info = snd_p16v_volume_info, |
872 | .get = snd_p16v_volume_get_spdif_center_lfe, | 872 | .get = snd_p16v_volume_get_spdif_center_lfe, |
873 | .put = snd_p16v_volume_put_spdif_center_lfe | 873 | .put = snd_p16v_volume_put_spdif_center_lfe |
@@ -876,7 +876,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe = | |||
876 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown = | 876 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown = |
877 | { | 877 | { |
878 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 878 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
879 | .name = "HD SPDIF Unknown Volume", | 879 | .name = "HD SPDIF Unknown Playback Volume", |
880 | .info = snd_p16v_volume_info, | 880 | .info = snd_p16v_volume_info, |
881 | .get = snd_p16v_volume_get_spdif_unknown, | 881 | .get = snd_p16v_volume_get_spdif_unknown, |
882 | .put = snd_p16v_volume_put_spdif_unknown | 882 | .put = snd_p16v_volume_put_spdif_unknown |
@@ -885,7 +885,7 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown = | |||
885 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear = | 885 | static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear = |
886 | { | 886 | { |
887 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 887 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
888 | .name = "HD SPDIF Rear Volume", | 888 | .name = "HD SPDIF Rear Playback Volume", |
889 | .info = snd_p16v_volume_info, | 889 | .info = snd_p16v_volume_info, |
890 | .get = snd_p16v_volume_get_spdif_rear, | 890 | .get = snd_p16v_volume_get_spdif_rear, |
891 | .put = snd_p16v_volume_put_spdif_rear | 891 | .put = snd_p16v_volume_put_spdif_rear |
@@ -936,7 +936,7 @@ static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol, | |||
936 | static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata = | 936 | static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata = |
937 | { | 937 | { |
938 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 938 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
939 | .name = "HD Capture source", | 939 | .name = "HD source Capture", |
940 | .info = snd_p16v_capture_source_info, | 940 | .info = snd_p16v_capture_source_info, |
941 | .get = snd_p16v_capture_source_get, | 941 | .get = snd_p16v_capture_source_get, |
942 | .put = snd_p16v_capture_source_put | 942 | .put = snd_p16v_capture_source_put |
@@ -985,7 +985,7 @@ static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol, | |||
985 | static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata = | 985 | static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata = |
986 | { | 986 | { |
987 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 987 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
988 | .name = "HD Capture channel", | 988 | .name = "HD channel Capture", |
989 | .info = snd_p16v_capture_channel_info, | 989 | .info = snd_p16v_capture_channel_info, |
990 | .get = snd_p16v_capture_channel_get, | 990 | .get = snd_p16v_capture_channel_get, |
991 | .put = snd_p16v_capture_channel_put | 991 | .put = snd_p16v_capture_channel_put |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 4e63498a58b2..78a81f3912a1 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -685,6 +685,15 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97, | |||
685 | return 0; | 685 | return 0; |
686 | } | 686 | } |
687 | 687 | ||
688 | static void snd_es1371_codec_wait(ac97_t *ac97) | ||
689 | { | ||
690 | msleep(750); | ||
691 | snd_es1371_codec_read(ac97, AC97_RESET); | ||
692 | snd_es1371_codec_read(ac97, AC97_VENDOR_ID1); | ||
693 | snd_es1371_codec_read(ac97, AC97_VENDOR_ID2); | ||
694 | msleep(50); | ||
695 | } | ||
696 | |||
688 | static void snd_es1371_adc_rate(ensoniq_t * ensoniq, unsigned int rate) | 697 | static void snd_es1371_adc_rate(ensoniq_t * ensoniq, unsigned int rate) |
689 | { | 698 | { |
690 | unsigned int n, truncm, freq, result; | 699 | unsigned int n, truncm, freq, result; |
@@ -1585,6 +1594,7 @@ static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq) | |||
1585 | static ac97_bus_ops_t ops = { | 1594 | static ac97_bus_ops_t ops = { |
1586 | .write = snd_es1371_codec_write, | 1595 | .write = snd_es1371_codec_write, |
1587 | .read = snd_es1371_codec_read, | 1596 | .read = snd_es1371_codec_read, |
1597 | .wait = snd_es1371_codec_wait, | ||
1588 | }; | 1598 | }; |
1589 | 1599 | ||
1590 | if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0) | 1600 | if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0) |
@@ -2008,21 +2018,11 @@ static int __devinit snd_ensoniq_create(snd_card_t * card, | |||
2008 | if (pci->vendor == es1371_ac97_reset_hack[idx].vid && | 2018 | if (pci->vendor == es1371_ac97_reset_hack[idx].vid && |
2009 | pci->device == es1371_ac97_reset_hack[idx].did && | 2019 | pci->device == es1371_ac97_reset_hack[idx].did && |
2010 | ensoniq->rev == es1371_ac97_reset_hack[idx].rev) { | 2020 | ensoniq->rev == es1371_ac97_reset_hack[idx].rev) { |
2011 | unsigned long tmo; | ||
2012 | signed long tmo2; | ||
2013 | |||
2014 | ensoniq->cssr |= ES_1371_ST_AC97_RST; | 2021 | ensoniq->cssr |= ES_1371_ST_AC97_RST; |
2015 | outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); | 2022 | outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); |
2016 | /* need to delay around 20ms(bleech) to give | 2023 | /* need to delay around 20ms(bleech) to give |
2017 | some CODECs enough time to wakeup */ | 2024 | some CODECs enough time to wakeup */ |
2018 | tmo = jiffies + (HZ / 50) + 1; | 2025 | msleep(20); |
2019 | while (1) { | ||
2020 | tmo2 = tmo - jiffies; | ||
2021 | if (tmo2 <= 0) | ||
2022 | break; | ||
2023 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
2024 | schedule_timeout(tmo2); | ||
2025 | } | ||
2026 | break; | 2026 | break; |
2027 | } | 2027 | } |
2028 | /* AC'97 warm reset to start the bitclk */ | 2028 | /* AC'97 warm reset to start the bitclk */ |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 327a341e276b..9d7a28783930 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -664,11 +664,6 @@ static inline u16 maestro_read(es1968_t *chip, u16 reg) | |||
664 | return result; | 664 | return result; |
665 | } | 665 | } |
666 | 666 | ||
667 | #define big_mdelay(msec) do {\ | ||
668 | set_current_state(TASK_UNINTERRUPTIBLE);\ | ||
669 | schedule_timeout(((msec) * HZ + 999) / 1000);\ | ||
670 | } while (0) | ||
671 | |||
672 | /* Wait for the codec bus to be free */ | 667 | /* Wait for the codec bus to be free */ |
673 | static int snd_es1968_ac97_wait(es1968_t *chip) | 668 | static int snd_es1968_ac97_wait(es1968_t *chip) |
674 | { | 669 | { |
@@ -1809,8 +1804,7 @@ static void __devinit es1968_measure_clock(es1968_t *chip) | |||
1809 | snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR); | 1804 | snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR); |
1810 | do_gettimeofday(&start_time); | 1805 | do_gettimeofday(&start_time); |
1811 | spin_unlock_irq(&chip->reg_lock); | 1806 | spin_unlock_irq(&chip->reg_lock); |
1812 | set_current_state(TASK_UNINTERRUPTIBLE); | 1807 | msleep(50); |
1813 | schedule_timeout(HZ / 20); /* 50 msec */ | ||
1814 | spin_lock_irq(&chip->reg_lock); | 1808 | spin_lock_irq(&chip->reg_lock); |
1815 | offset = __apu_get_register(chip, apu, 5); | 1809 | offset = __apu_get_register(chip, apu, 5); |
1816 | do_gettimeofday(&stop_time); | 1810 | do_gettimeofday(&stop_time); |
@@ -2093,7 +2087,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip) | |||
2093 | outw(0x0000, ioaddr + 0x60); /* write 0 to gpio 0 */ | 2087 | outw(0x0000, ioaddr + 0x60); /* write 0 to gpio 0 */ |
2094 | udelay(20); | 2088 | udelay(20); |
2095 | outw(0x0001, ioaddr + 0x60); /* write 1 to gpio 1 */ | 2089 | outw(0x0001, ioaddr + 0x60); /* write 1 to gpio 1 */ |
2096 | big_mdelay(20); | 2090 | msleep(20); |
2097 | 2091 | ||
2098 | outw(save_68 | 0x1, ioaddr + 0x68); /* now restore .. */ | 2092 | outw(save_68 | 0x1, ioaddr + 0x68); /* now restore .. */ |
2099 | outw((inw(ioaddr + 0x38) & 0xfffc) | 0x1, ioaddr + 0x38); | 2093 | outw((inw(ioaddr + 0x38) & 0xfffc) | 0x1, ioaddr + 0x38); |
@@ -2109,7 +2103,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip) | |||
2109 | outw(0x0001, ioaddr + 0x60); /* write 1 to gpio */ | 2103 | outw(0x0001, ioaddr + 0x60); /* write 1 to gpio */ |
2110 | udelay(20); | 2104 | udelay(20); |
2111 | outw(0x0009, ioaddr + 0x60); /* write 9 to gpio */ | 2105 | outw(0x0009, ioaddr + 0x60); /* write 9 to gpio */ |
2112 | big_mdelay(500); | 2106 | msleep(500); |
2113 | //outw(inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38); | 2107 | //outw(inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38); |
2114 | outw(inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a); | 2108 | outw(inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a); |
2115 | outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c); | 2109 | outw(inw(ioaddr + 0x3c) & 0xfffc, ioaddr + 0x3c); |
@@ -2135,7 +2129,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip) | |||
2135 | 2129 | ||
2136 | if (w > 10000) { | 2130 | if (w > 10000) { |
2137 | outb(inb(ioaddr + 0x37) | 0x08, ioaddr + 0x37); /* do a software reset */ | 2131 | outb(inb(ioaddr + 0x37) | 0x08, ioaddr + 0x37); /* do a software reset */ |
2138 | big_mdelay(500); /* oh my.. */ | 2132 | msleep(500); /* oh my.. */ |
2139 | outb(inb(ioaddr + 0x37) & ~0x08, | 2133 | outb(inb(ioaddr + 0x37) & ~0x08, |
2140 | ioaddr + 0x37); | 2134 | ioaddr + 0x37); |
2141 | udelay(1); | 2135 | udelay(1); |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 59991560d492..dd0d99d2ad27 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -262,6 +262,9 @@ enum { | |||
262 | #define AC_PINCTL_OUT_EN (1<<6) | 262 | #define AC_PINCTL_OUT_EN (1<<6) |
263 | #define AC_PINCTL_HP_EN (1<<7) | 263 | #define AC_PINCTL_HP_EN (1<<7) |
264 | 264 | ||
265 | /* Unsolicited response - 8bit */ | ||
266 | #define AC_USRSP_EN (1<<7) | ||
267 | |||
265 | /* configuration default - 32bit */ | 268 | /* configuration default - 32bit */ |
266 | #define AC_DEFCFG_SEQUENCE (0xf<<0) | 269 | #define AC_DEFCFG_SEQUENCE (0xf<<0) |
267 | #define AC_DEFCFG_DEF_ASSOC (0xf<<4) | 270 | #define AC_DEFCFG_DEF_ASSOC (0xf<<4) |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 5e0cca36ed57..288ab0764830 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -178,6 +178,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
178 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ | 178 | #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ |
179 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ | 179 | #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ |
180 | 180 | ||
181 | /* GCTL unsolicited response enable bit */ | ||
182 | #define ICH6_GCTL_UREN (1<<8) | ||
183 | |||
181 | /* GCTL reset bit */ | 184 | /* GCTL reset bit */ |
182 | #define ICH6_GCTL_RESET (1<<0) | 185 | #define ICH6_GCTL_RESET (1<<0) |
183 | 186 | ||
@@ -562,6 +565,9 @@ static int azx_reset(azx_t *chip) | |||
562 | return -EBUSY; | 565 | return -EBUSY; |
563 | } | 566 | } |
564 | 567 | ||
568 | /* Accept unsolicited responses */ | ||
569 | azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN); | ||
570 | |||
565 | /* detect codecs */ | 571 | /* detect codecs */ |
566 | if (! chip->codec_mask) { | 572 | if (! chip->codec_mask) { |
567 | chip->codec_mask = azx_readw(chip, STATESTS); | 573 | chip->codec_mask = azx_readw(chip, STATESTS); |
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c index 2d6e3e3d0a38..86f195f19eef 100644 --- a/sound/pci/hda/patch_cmedia.c +++ b/sound/pci/hda/patch_cmedia.c | |||
@@ -408,7 +408,7 @@ static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec, const struct aut | |||
408 | /* search for an empty channel */ | 408 | /* search for an empty channel */ |
409 | for (j = 0; j < cfg->line_outs; j++) { | 409 | for (j = 0; j < cfg->line_outs; j++) { |
410 | if (! assigned[j]) { | 410 | if (! assigned[j]) { |
411 | spec->dac_nids[i] = i + 0x03; | 411 | spec->dac_nids[i] = j + 0x03; |
412 | assigned[j] = 1; | 412 | assigned[j] = 1; |
413 | break; | 413 | break; |
414 | } | 414 | } |
@@ -444,11 +444,10 @@ static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pi | |||
444 | len = snd_hda_get_connections(codec, nid, conn, 4); | 444 | len = snd_hda_get_connections(codec, nid, conn, 4); |
445 | for (k = 0; k < len; k++) | 445 | for (k = 0; k < len; k++) |
446 | if (conn[k] == spec->dac_nids[i]) { | 446 | if (conn[k] == spec->dac_nids[i]) { |
447 | spec->multi_init[j].param = j; | 447 | spec->multi_init[j].param = k; |
448 | break; | 448 | break; |
449 | } | 449 | } |
450 | j++; | 450 | j++; |
451 | break; | ||
452 | } | 451 | } |
453 | } | 452 | } |
454 | return 0; | 453 | return 0; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bab89843d850..9b8569900787 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -40,6 +40,7 @@ enum { | |||
40 | ALC880_W810, | 40 | ALC880_W810, |
41 | ALC880_Z71V, | 41 | ALC880_Z71V, |
42 | ALC880_AUTO, | 42 | ALC880_AUTO, |
43 | ALC880_6ST, | ||
43 | ALC880_6ST_DIG, | 44 | ALC880_6ST_DIG, |
44 | ALC880_F1734, | 45 | ALC880_F1734, |
45 | ALC880_ASUS, | 46 | ALC880_ASUS, |
@@ -119,6 +120,7 @@ struct alc_spec { | |||
119 | unsigned int num_kctl_alloc, num_kctl_used; | 120 | unsigned int num_kctl_alloc, num_kctl_used; |
120 | snd_kcontrol_new_t *kctl_alloc; | 121 | snd_kcontrol_new_t *kctl_alloc; |
121 | struct hda_input_mux private_imux; | 122 | struct hda_input_mux private_imux; |
123 | hda_nid_t private_dac_nids[4]; | ||
122 | }; | 124 | }; |
123 | 125 | ||
124 | 126 | ||
@@ -1547,9 +1549,10 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
1547 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG }, | 1549 | { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG }, |
1548 | { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG }, | 1550 | { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG }, |
1549 | { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG }, | 1551 | { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG }, |
1550 | { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, | 1552 | /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */ |
1551 | { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG }, | 1553 | { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG }, |
1552 | { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, | 1554 | /* note subvendor = 0 below */ |
1555 | /* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */ | ||
1553 | 1556 | ||
1554 | { .modelname = "w810", .config = ALC880_W810 }, | 1557 | { .modelname = "w810", .config = ALC880_W810 }, |
1555 | { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 }, | 1558 | { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 }, |
@@ -1557,7 +1560,10 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
1557 | { .modelname = "z71v", .config = ALC880_Z71V }, | 1560 | { .modelname = "z71v", .config = ALC880_Z71V }, |
1558 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V }, | 1561 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V }, |
1559 | 1562 | ||
1560 | { .modelname = "6statack-digout", .config = ALC880_6ST_DIG }, | 1563 | { .modelname = "6stack", .config = ALC880_6ST }, |
1564 | { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */ | ||
1565 | |||
1566 | { .modelname = "6stack-digout", .config = ALC880_6ST_DIG }, | ||
1561 | { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG }, | 1567 | { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG }, |
1562 | { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG }, | 1568 | { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG }, |
1563 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG }, | 1569 | { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG }, |
@@ -1644,6 +1650,15 @@ static struct alc_config_preset alc880_presets[] = { | |||
1644 | .channel_mode = alc880_fivestack_modes, | 1650 | .channel_mode = alc880_fivestack_modes, |
1645 | .input_mux = &alc880_capture_source, | 1651 | .input_mux = &alc880_capture_source, |
1646 | }, | 1652 | }, |
1653 | [ALC880_6ST] = { | ||
1654 | .mixers = { alc880_six_stack_mixer }, | ||
1655 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, | ||
1656 | .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids), | ||
1657 | .dac_nids = alc880_6st_dac_nids, | ||
1658 | .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes), | ||
1659 | .channel_mode = alc880_sixstack_modes, | ||
1660 | .input_mux = &alc880_6stack_capture_source, | ||
1661 | }, | ||
1647 | [ALC880_6ST_DIG] = { | 1662 | [ALC880_6ST_DIG] = { |
1648 | .mixers = { alc880_six_stack_mixer }, | 1663 | .mixers = { alc880_six_stack_mixer }, |
1649 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, | 1664 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs }, |
@@ -1656,7 +1671,8 @@ static struct alc_config_preset alc880_presets[] = { | |||
1656 | }, | 1671 | }, |
1657 | [ALC880_W810] = { | 1672 | [ALC880_W810] = { |
1658 | .mixers = { alc880_w810_base_mixer }, | 1673 | .mixers = { alc880_w810_base_mixer }, |
1659 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs }, | 1674 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs, |
1675 | alc880_gpio2_init_verbs }, | ||
1660 | .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), | 1676 | .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids), |
1661 | .dac_nids = alc880_w810_dac_nids, | 1677 | .dac_nids = alc880_w810_dac_nids, |
1662 | .dig_out_nid = ALC880_DIGOUT_NID, | 1678 | .dig_out_nid = ALC880_DIGOUT_NID, |
@@ -1666,8 +1682,7 @@ static struct alc_config_preset alc880_presets[] = { | |||
1666 | }, | 1682 | }, |
1667 | [ALC880_Z71V] = { | 1683 | [ALC880_Z71V] = { |
1668 | .mixers = { alc880_z71v_mixer }, | 1684 | .mixers = { alc880_z71v_mixer }, |
1669 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs, | 1685 | .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs }, |
1670 | alc880_gpio2_init_verbs }, | ||
1671 | .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), | 1686 | .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids), |
1672 | .dac_nids = alc880_z71v_dac_nids, | 1687 | .dac_nids = alc880_z71v_dac_nids, |
1673 | .dig_out_nid = ALC880_DIGOUT_NID, | 1688 | .dig_out_nid = ALC880_DIGOUT_NID, |
@@ -1809,6 +1824,7 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pi | |||
1809 | int i, j; | 1824 | int i, j; |
1810 | 1825 | ||
1811 | memset(assigned, 0, sizeof(assigned)); | 1826 | memset(assigned, 0, sizeof(assigned)); |
1827 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
1812 | 1828 | ||
1813 | /* check the pins hardwired to audio widget */ | 1829 | /* check the pins hardwired to audio widget */ |
1814 | for (i = 0; i < cfg->line_outs; i++) { | 1830 | for (i = 0; i < cfg->line_outs; i++) { |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 013be2ea513a..9d503da7320d 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -30,32 +30,37 @@ | |||
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
33 | #include <sound/asoundef.h> | ||
33 | #include "hda_codec.h" | 34 | #include "hda_codec.h" |
34 | #include "hda_local.h" | 35 | #include "hda_local.h" |
35 | 36 | ||
36 | #undef STAC_TEST | 37 | #undef STAC_TEST |
37 | 38 | ||
39 | #define NUM_CONTROL_ALLOC 32 | ||
40 | #define STAC_HP_EVENT 0x37 | ||
41 | #define STAC_UNSOL_ENABLE (AC_USRSP_EN | STAC_HP_EVENT) | ||
42 | |||
38 | struct sigmatel_spec { | 43 | struct sigmatel_spec { |
44 | snd_kcontrol_new_t *mixers[4]; | ||
45 | unsigned int num_mixers; | ||
46 | |||
47 | unsigned int surr_switch: 1; | ||
48 | |||
39 | /* playback */ | 49 | /* playback */ |
40 | struct hda_multi_out multiout; | 50 | struct hda_multi_out multiout; |
41 | hda_nid_t playback_nid; | 51 | hda_nid_t dac_nids[4]; |
42 | 52 | ||
43 | /* capture */ | 53 | /* capture */ |
44 | hda_nid_t *adc_nids; | 54 | hda_nid_t *adc_nids; |
45 | unsigned int num_adcs; | 55 | unsigned int num_adcs; |
46 | hda_nid_t *mux_nids; | 56 | hda_nid_t *mux_nids; |
47 | unsigned int num_muxes; | 57 | unsigned int num_muxes; |
48 | hda_nid_t capture_nid; | ||
49 | hda_nid_t dig_in_nid; | 58 | hda_nid_t dig_in_nid; |
50 | 59 | ||
51 | /* power management*/ | 60 | #ifdef STAC_TEST |
52 | hda_nid_t *pstate_nids; | ||
53 | unsigned int num_pstates; | ||
54 | |||
55 | /* pin widgets */ | 61 | /* pin widgets */ |
56 | hda_nid_t *pin_nids; | 62 | hda_nid_t *pin_nids; |
57 | unsigned int num_pins; | 63 | unsigned int num_pins; |
58 | #ifdef STAC_TEST | ||
59 | unsigned int *pin_configs; | 64 | unsigned int *pin_configs; |
60 | #endif | 65 | #endif |
61 | 66 | ||
@@ -64,16 +69,20 @@ struct sigmatel_spec { | |||
64 | snd_kcontrol_new_t *mixer; | 69 | snd_kcontrol_new_t *mixer; |
65 | 70 | ||
66 | /* capture source */ | 71 | /* capture source */ |
67 | struct hda_input_mux input_mux; | 72 | struct hda_input_mux *input_mux; |
68 | char input_labels[HDA_MAX_NUM_INPUTS][16]; | ||
69 | unsigned int cur_mux[2]; | 73 | unsigned int cur_mux[2]; |
70 | 74 | ||
71 | /* channel mode */ | 75 | /* channel mode */ |
72 | unsigned int num_ch_modes; | 76 | unsigned int num_ch_modes; |
73 | unsigned int cur_ch_mode; | 77 | unsigned int cur_ch_mode; |
74 | const struct sigmatel_channel_mode *channel_modes; | ||
75 | 78 | ||
76 | struct hda_pcm pcm_rec[1]; /* PCM information */ | 79 | struct hda_pcm pcm_rec[2]; /* PCM information */ |
80 | |||
81 | /* dynamic controls and input_mux */ | ||
82 | struct auto_pin_cfg autocfg; | ||
83 | unsigned int num_kctl_alloc, num_kctl_used; | ||
84 | snd_kcontrol_new_t *kctl_alloc; | ||
85 | struct hda_input_mux private_imux; | ||
77 | }; | 86 | }; |
78 | 87 | ||
79 | static hda_nid_t stac9200_adc_nids[1] = { | 88 | static hda_nid_t stac9200_adc_nids[1] = { |
@@ -88,14 +97,6 @@ static hda_nid_t stac9200_dac_nids[1] = { | |||
88 | 0x02, | 97 | 0x02, |
89 | }; | 98 | }; |
90 | 99 | ||
91 | static hda_nid_t stac9200_pstate_nids[3] = { | ||
92 | 0x01, 0x02, 0x03, | ||
93 | }; | ||
94 | |||
95 | static hda_nid_t stac9200_pin_nids[8] = { | ||
96 | 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, | ||
97 | }; | ||
98 | |||
99 | static hda_nid_t stac922x_adc_nids[2] = { | 100 | static hda_nid_t stac922x_adc_nids[2] = { |
100 | 0x06, 0x07, | 101 | 0x06, 0x07, |
101 | }; | 102 | }; |
@@ -104,24 +105,22 @@ static hda_nid_t stac922x_mux_nids[2] = { | |||
104 | 0x12, 0x13, | 105 | 0x12, 0x13, |
105 | }; | 106 | }; |
106 | 107 | ||
107 | static hda_nid_t stac922x_dac_nids[4] = { | 108 | #ifdef STAC_TEST |
108 | 0x02, 0x03, 0x04, 0x05, | 109 | static hda_nid_t stac9200_pin_nids[8] = { |
109 | }; | 110 | 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, |
110 | |||
111 | static hda_nid_t stac922x_pstate_nids[8] = { | ||
112 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x11, | ||
113 | }; | 111 | }; |
114 | 112 | ||
115 | static hda_nid_t stac922x_pin_nids[10] = { | 113 | static hda_nid_t stac922x_pin_nids[10] = { |
116 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 114 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, |
117 | 0x0f, 0x10, 0x11, 0x15, 0x1b, | 115 | 0x0f, 0x10, 0x11, 0x15, 0x1b, |
118 | }; | 116 | }; |
117 | #endif | ||
119 | 118 | ||
120 | static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | 119 | static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) |
121 | { | 120 | { |
122 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 121 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
123 | struct sigmatel_spec *spec = codec->spec; | 122 | struct sigmatel_spec *spec = codec->spec; |
124 | return snd_hda_input_mux_info(&spec->input_mux, uinfo); | 123 | return snd_hda_input_mux_info(spec->input_mux, uinfo); |
125 | } | 124 | } |
126 | 125 | ||
127 | static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 126 | static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
@@ -140,26 +139,64 @@ static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
140 | struct sigmatel_spec *spec = codec->spec; | 139 | struct sigmatel_spec *spec = codec->spec; |
141 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 140 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
142 | 141 | ||
143 | return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol, | 142 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, |
144 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); | 143 | spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); |
145 | } | 144 | } |
146 | 145 | ||
147 | static struct hda_verb stac9200_ch2_init[] = { | 146 | static struct hda_verb stac9200_core_init[] = { |
148 | /* set dac0mux for dac converter */ | 147 | /* set dac0mux for dac converter */ |
149 | { 0x07, 0x701, 0x00}, | 148 | { 0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, |
150 | {} | 149 | {} |
151 | }; | 150 | }; |
152 | 151 | ||
153 | static struct hda_verb stac922x_ch2_init[] = { | 152 | static struct hda_verb stac922x_core_init[] = { |
154 | /* set master volume and direct control */ | 153 | /* set master volume and direct control */ |
155 | { 0x16, 0x70f, 0xff}, | 154 | { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
156 | {} | 155 | {} |
157 | }; | 156 | }; |
158 | 157 | ||
159 | struct sigmatel_channel_mode { | 158 | static int stac922x_channel_modes[3] = {2, 6, 8}; |
160 | unsigned int channels; | 159 | |
161 | const struct hda_verb *sequence; | 160 | static int stac922x_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) |
162 | }; | 161 | { |
162 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
163 | struct sigmatel_spec *spec = codec->spec; | ||
164 | |||
165 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
166 | uinfo->count = 1; | ||
167 | uinfo->value.enumerated.items = spec->num_ch_modes; | ||
168 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
169 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
170 | sprintf(uinfo->value.enumerated.name, "%dch", | ||
171 | stac922x_channel_modes[uinfo->value.enumerated.item]); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int stac922x_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
176 | { | ||
177 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
178 | struct sigmatel_spec *spec = codec->spec; | ||
179 | |||
180 | ucontrol->value.enumerated.item[0] = spec->cur_ch_mode; | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int stac922x_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
185 | { | ||
186 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
187 | struct sigmatel_spec *spec = codec->spec; | ||
188 | |||
189 | if (ucontrol->value.enumerated.item[0] >= spec->num_ch_modes) | ||
190 | ucontrol->value.enumerated.item[0] = spec->num_ch_modes; | ||
191 | if (ucontrol->value.enumerated.item[0] == spec->cur_ch_mode && | ||
192 | ! codec->in_resume) | ||
193 | return 0; | ||
194 | |||
195 | spec->cur_ch_mode = ucontrol->value.enumerated.item[0]; | ||
196 | spec->multiout.max_channels = stac922x_channel_modes[spec->cur_ch_mode]; | ||
197 | |||
198 | return 1; | ||
199 | } | ||
163 | 200 | ||
164 | static snd_kcontrol_new_t stac9200_mixer[] = { | 201 | static snd_kcontrol_new_t stac9200_mixer[] = { |
165 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 202 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), |
@@ -174,13 +211,12 @@ static snd_kcontrol_new_t stac9200_mixer[] = { | |||
174 | }, | 211 | }, |
175 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | 212 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), |
176 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | 213 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), |
177 | HDA_CODEC_VOLUME("Input Mux Volume", 0x0c, 0, HDA_OUTPUT), | 214 | HDA_CODEC_VOLUME("Capture Mux Volume", 0x0c, 0, HDA_OUTPUT), |
178 | { } /* end */ | 215 | { } /* end */ |
179 | }; | 216 | }; |
180 | 217 | ||
218 | /* This needs to be generated dynamically based on sequence */ | ||
181 | static snd_kcontrol_new_t stac922x_mixer[] = { | 219 | static snd_kcontrol_new_t stac922x_mixer[] = { |
182 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x2, 0x0, HDA_OUTPUT), | ||
183 | HDA_CODEC_MUTE("PCM Playback Switch", 0x2, 0x0, HDA_OUTPUT), | ||
184 | { | 220 | { |
185 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 221 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
186 | .name = "Input Source", | 222 | .name = "Input Source", |
@@ -195,14 +231,38 @@ static snd_kcontrol_new_t stac922x_mixer[] = { | |||
195 | { } /* end */ | 231 | { } /* end */ |
196 | }; | 232 | }; |
197 | 233 | ||
234 | static snd_kcontrol_new_t stac922x_ch_mode_mixer[] = { | ||
235 | { | ||
236 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
237 | .name = "Channel Mode", | ||
238 | .info = stac922x_ch_mode_info, | ||
239 | .get = stac922x_ch_mode_get, | ||
240 | .put = stac922x_ch_mode_put, | ||
241 | }, | ||
242 | { } /* end */ | ||
243 | }; | ||
244 | |||
198 | static int stac92xx_build_controls(struct hda_codec *codec) | 245 | static int stac92xx_build_controls(struct hda_codec *codec) |
199 | { | 246 | { |
200 | struct sigmatel_spec *spec = codec->spec; | 247 | struct sigmatel_spec *spec = codec->spec; |
201 | int err; | 248 | int err; |
249 | int i; | ||
202 | 250 | ||
203 | err = snd_hda_add_new_ctls(codec, spec->mixer); | 251 | err = snd_hda_add_new_ctls(codec, spec->mixer); |
204 | if (err < 0) | 252 | if (err < 0) |
205 | return err; | 253 | return err; |
254 | |||
255 | for (i = 0; i < spec->num_mixers; i++) { | ||
256 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | ||
257 | if (err < 0) | ||
258 | return err; | ||
259 | } | ||
260 | |||
261 | if (spec->surr_switch) { | ||
262 | err = snd_hda_add_new_ctls(codec, stac922x_ch_mode_mixer); | ||
263 | if (err < 0) | ||
264 | return err; | ||
265 | } | ||
206 | if (spec->multiout.dig_out_nid) { | 266 | if (spec->multiout.dig_out_nid) { |
207 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | 267 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); |
208 | if (err < 0) | 268 | if (err < 0) |
@@ -222,9 +282,9 @@ static unsigned int stac9200_pin_configs[8] = { | |||
222 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, | 282 | 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, |
223 | }; | 283 | }; |
224 | 284 | ||
225 | static unsigned int stac922x_pin_configs[14] = { | 285 | static unsigned int stac922x_pin_configs[10] = { |
226 | 0x40000100, 0x40000100, 0x40000100, 0x01114010, | 286 | 0x01014010, 0x01014011, 0x01014012, 0x0221401f, |
227 | 0x01813122, 0x40000100, 0x01447010, 0x01c47010, | 287 | 0x01813122, 0x01014014, 0x01441030, 0x01c41030, |
228 | 0x40000100, 0x40000100, | 288 | 0x40000100, 0x40000100, |
229 | }; | 289 | }; |
230 | 290 | ||
@@ -255,180 +315,66 @@ static void stac92xx_set_config_regs(struct hda_codec *codec) | |||
255 | } | 315 | } |
256 | #endif | 316 | #endif |
257 | 317 | ||
258 | static int stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int value) | ||
259 | { | ||
260 | unsigned int pin_ctl; | ||
261 | |||
262 | pin_ctl = snd_hda_codec_read(codec, nid, 0, | ||
263 | AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
264 | 0x00); | ||
265 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
266 | pin_ctl | value); | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int stac92xx_set_vref(struct hda_codec *codec, hda_nid_t nid) | ||
272 | { | ||
273 | unsigned int vref_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) >> AC_PINCAP_VREF_SHIFT; | ||
274 | unsigned int vref_ctl = AC_PINCTL_VREF_HIZ; | ||
275 | |||
276 | if (vref_caps & AC_PINCAP_VREF_100) | ||
277 | vref_ctl = AC_PINCTL_VREF_100; | ||
278 | else if (vref_caps & AC_PINCAP_VREF_80) | ||
279 | vref_ctl = AC_PINCTL_VREF_80; | ||
280 | else if (vref_caps & AC_PINCAP_VREF_50) | ||
281 | vref_ctl = AC_PINCTL_VREF_50; | ||
282 | else if (vref_caps & AC_PINCAP_VREF_GRD) | ||
283 | vref_ctl = AC_PINCTL_VREF_GRD; | ||
284 | |||
285 | stac92xx_set_pinctl(codec, nid, vref_ctl); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | /* | 318 | /* |
291 | * retrieve the default device type from the default config value | 319 | * Analog playback callbacks |
292 | */ | 320 | */ |
293 | #define get_defcfg_type(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) | 321 | static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo, |
294 | #define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT) | 322 | struct hda_codec *codec, |
295 | 323 | snd_pcm_substream_t *substream) | |
296 | static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg) | ||
297 | { | 324 | { |
298 | struct sigmatel_spec *spec = codec->spec; | 325 | struct sigmatel_spec *spec = codec->spec; |
299 | u32 location = get_defcfg_location(pin_cfg); | 326 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); |
300 | char *label; | ||
301 | const char *type = NULL; | ||
302 | int ainput = 0; | ||
303 | |||
304 | switch(get_defcfg_type(pin_cfg)) { | ||
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_SPDIF_OUT: | ||
310 | case AC_JACK_LINE_OUT: | ||
311 | case AC_JACK_SPEAKER: | ||
312 | /* Enable output */ | ||
313 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | ||
314 | break; | ||
315 | case AC_JACK_SPDIF_IN: | ||
316 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); | ||
317 | break; | ||
318 | case AC_JACK_MIC_IN: | ||
319 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) | ||
320 | type = "Front Mic"; | ||
321 | else | ||
322 | type = "Mic"; | ||
323 | ainput = 1; | ||
324 | /* Set vref */ | ||
325 | stac92xx_set_vref(codec, nid); | ||
326 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); | ||
327 | break; | ||
328 | case AC_JACK_CD: | ||
329 | type = "CD"; | ||
330 | ainput = 1; | ||
331 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); | ||
332 | break; | ||
333 | case AC_JACK_LINE_IN: | ||
334 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) | ||
335 | type = "Front Line"; | ||
336 | else | ||
337 | type = "Line"; | ||
338 | ainput = 1; | ||
339 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); | ||
340 | break; | ||
341 | case AC_JACK_AUX: | ||
342 | if ((location & 0x0f) == AC_JACK_LOC_FRONT) | ||
343 | type = "Front Aux"; | ||
344 | else | ||
345 | type = "Aux"; | ||
346 | ainput = 1; | ||
347 | stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); | ||
348 | break; | ||
349 | } | ||
350 | |||
351 | if (ainput) { | ||
352 | hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; | ||
353 | int i, j, num_cons, index = -1; | ||
354 | if (!type) | ||
355 | type = "Input"; | ||
356 | label = spec->input_labels[spec->input_mux.num_items]; | ||
357 | strcpy(label, type); | ||
358 | spec->input_mux.items[spec->input_mux.num_items].label = label; | ||
359 | for (i=0; i<spec->num_muxes; i++) { | ||
360 | num_cons = snd_hda_get_connections(codec, spec->mux_nids[i], con_lst, HDA_MAX_NUM_INPUTS); | ||
361 | for (j=0; j<num_cons; j++) | ||
362 | if (con_lst[j] == nid) { | ||
363 | index = j; | ||
364 | break; | ||
365 | } | ||
366 | if (index >= 0) | ||
367 | break; | ||
368 | } | ||
369 | spec->input_mux.items[spec->input_mux.num_items].index = index; | ||
370 | spec->input_mux.num_items++; | ||
371 | } | ||
372 | |||
373 | return 0; | ||
374 | } | 327 | } |
375 | 328 | ||
376 | static int stac92xx_config_pins(struct hda_codec *codec) | 329 | /* |
330 | * set up the i/o for analog out | ||
331 | * when the digital out is available, copy the front out to digital out, too. | ||
332 | */ | ||
333 | static int stac92xx_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout, | ||
334 | unsigned int stream_tag, | ||
335 | unsigned int format, | ||
336 | snd_pcm_substream_t *substream) | ||
377 | { | 337 | { |
378 | struct sigmatel_spec *spec = codec->spec; | 338 | hda_nid_t *nids = mout->dac_nids; |
339 | int chs = substream->runtime->channels; | ||
379 | int i; | 340 | int i; |
380 | unsigned int pin_cfg; | ||
381 | 341 | ||
382 | for (i=0; i < spec->num_pins; i++) { | 342 | down(&codec->spdif_mutex); |
383 | /* Default to disabled */ | 343 | if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) { |
384 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | 344 | if (chs == 2 && |
385 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 345 | snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && |
386 | 0x00); | 346 | ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) { |
387 | 347 | mout->dig_out_used = HDA_DIG_ANALOG_DUP; | |
388 | pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0, | 348 | /* setup digital receiver */ |
389 | AC_VERB_GET_CONFIG_DEFAULT, | 349 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, |
390 | 0x00); | 350 | stream_tag, 0, format); |
391 | if (((pin_cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) == AC_JACK_PORT_NONE) | 351 | } else { |
392 | continue; /* Move on */ | 352 | mout->dig_out_used = 0; |
393 | 353 | snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); | |
394 | stac92xx_config_pin(codec, spec->pin_nids[i], pin_cfg); | 354 | } |
395 | } | 355 | } |
396 | 356 | up(&codec->spdif_mutex); | |
397 | return 0; | 357 | |
398 | } | 358 | /* front */ |
399 | 359 | snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); | |
400 | static int stac92xx_init(struct hda_codec *codec) | 360 | if (mout->hp_nid) |
401 | { | 361 | /* headphone out will just decode front left/right (stereo) */ |
402 | struct sigmatel_spec *spec = codec->spec; | 362 | snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); |
403 | int i; | 363 | /* surrounds */ |
404 | 364 | if (mout->max_channels > 2) | |
405 | for (i=0; i < spec->num_pstates; i++) | 365 | for (i = 1; i < mout->num_dacs; i++) { |
406 | snd_hda_codec_write(codec, spec->pstate_nids[i], 0, | 366 | if ((mout->max_channels == 6) && (i == 3)) |
407 | AC_VERB_SET_POWER_STATE, 0x00); | 367 | break; |
408 | 368 | if (chs >= (i + 1) * 2) /* independent out */ | |
409 | mdelay(100); | 369 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2, |
410 | 370 | format); | |
411 | snd_hda_sequence_write(codec, spec->init); | 371 | else /* copy front */ |
412 | 372 | snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, | |
413 | #ifdef STAC_TEST | 373 | format); |
414 | stac92xx_set_config_regs(codec); | 374 | } |
415 | #endif | ||
416 | |||
417 | stac92xx_config_pins(codec); | ||
418 | |||
419 | return 0; | 375 | return 0; |
420 | } | 376 | } |
421 | 377 | ||
422 | /* | ||
423 | * Analog playback callbacks | ||
424 | */ | ||
425 | static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
426 | struct hda_codec *codec, | ||
427 | snd_pcm_substream_t *substream) | ||
428 | { | ||
429 | struct sigmatel_spec *spec = codec->spec; | ||
430 | return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream); | ||
431 | } | ||
432 | 378 | ||
433 | static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 379 | static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
434 | struct hda_codec *codec, | 380 | struct hda_codec *codec, |
@@ -437,7 +383,7 @@ static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
437 | snd_pcm_substream_t *substream) | 383 | snd_pcm_substream_t *substream) |
438 | { | 384 | { |
439 | struct sigmatel_spec *spec = codec->spec; | 385 | struct sigmatel_spec *spec = codec->spec; |
440 | return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, | 386 | return stac92xx_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, |
441 | format, substream); | 387 | format, substream); |
442 | } | 388 | } |
443 | 389 | ||
@@ -516,7 +462,7 @@ static struct hda_pcm_stream stac92xx_pcm_digital_capture = { | |||
516 | static struct hda_pcm_stream stac92xx_pcm_analog_playback = { | 462 | static struct hda_pcm_stream stac92xx_pcm_analog_playback = { |
517 | .substreams = 1, | 463 | .substreams = 1, |
518 | .channels_min = 2, | 464 | .channels_min = 2, |
519 | .channels_max = 2, | 465 | .channels_max = 8, |
520 | .nid = 0x02, /* NID to query formats and rates */ | 466 | .nid = 0x02, /* NID to query formats and rates */ |
521 | .ops = { | 467 | .ops = { |
522 | .open = stac92xx_playback_pcm_open, | 468 | .open = stac92xx_playback_pcm_open, |
@@ -544,11 +490,9 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
544 | codec->num_pcms = 1; | 490 | codec->num_pcms = 1; |
545 | codec->pcm_info = info; | 491 | codec->pcm_info = info; |
546 | 492 | ||
547 | info->name = "STAC92xx"; | 493 | info->name = "STAC92xx Analog"; |
548 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; | 494 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback; |
549 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->playback_nid; | ||
550 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; | 495 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; |
551 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid; | ||
552 | 496 | ||
553 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { | 497 | if (spec->multiout.dig_out_nid || spec->dig_in_nid) { |
554 | codec->num_pcms++; | 498 | codec->num_pcms++; |
@@ -567,21 +511,413 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
567 | return 0; | 511 | return 0; |
568 | } | 512 | } |
569 | 513 | ||
514 | enum { | ||
515 | STAC_CTL_WIDGET_VOL, | ||
516 | STAC_CTL_WIDGET_MUTE, | ||
517 | }; | ||
518 | |||
519 | static snd_kcontrol_new_t stac92xx_control_templates[] = { | ||
520 | HDA_CODEC_VOLUME(NULL, 0, 0, 0), | ||
521 | HDA_CODEC_MUTE(NULL, 0, 0, 0), | ||
522 | }; | ||
523 | |||
524 | /* add dynamic controls */ | ||
525 | static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char *name, unsigned long val) | ||
526 | { | ||
527 | snd_kcontrol_new_t *knew; | ||
528 | |||
529 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | ||
530 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | ||
531 | |||
532 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | ||
533 | if (! knew) | ||
534 | return -ENOMEM; | ||
535 | if (spec->kctl_alloc) { | ||
536 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
537 | kfree(spec->kctl_alloc); | ||
538 | } | ||
539 | spec->kctl_alloc = knew; | ||
540 | spec->num_kctl_alloc = num; | ||
541 | } | ||
542 | |||
543 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
544 | *knew = stac92xx_control_templates[type]; | ||
545 | knew->name = kstrdup(name, GFP_KERNEL); | ||
546 | if (! knew->name) | ||
547 | return -ENOMEM; | ||
548 | knew->private_value = val; | ||
549 | spec->num_kctl_used++; | ||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | /* fill in the dac_nids table from the parsed pin configuration */ | ||
554 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) | ||
555 | { | ||
556 | struct sigmatel_spec *spec = codec->spec; | ||
557 | hda_nid_t nid; | ||
558 | int i; | ||
559 | |||
560 | /* check the pins hardwired to audio widget */ | ||
561 | for (i = 0; i < cfg->line_outs; i++) { | ||
562 | nid = cfg->line_out_pins[i]; | ||
563 | spec->multiout.dac_nids[i] = snd_hda_codec_read(codec, nid, 0, | ||
564 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
565 | } | ||
566 | |||
567 | spec->multiout.num_dacs = cfg->line_outs; | ||
568 | |||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | /* add playback controls from the parsed DAC table */ | ||
573 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, const struct auto_pin_cfg *cfg) | ||
574 | { | ||
575 | char name[32]; | ||
576 | static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; | ||
577 | hda_nid_t nid; | ||
578 | int i, err; | ||
579 | |||
580 | for (i = 0; i < cfg->line_outs; i++) { | ||
581 | if (! spec->multiout.dac_nids[i]) | ||
582 | continue; | ||
583 | |||
584 | nid = spec->multiout.dac_nids[i]; | ||
585 | |||
586 | if (i == 2) { | ||
587 | /* Center/LFE */ | ||
588 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Center Playback Volume", | ||
589 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | ||
590 | return err; | ||
591 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "LFE Playback Volume", | ||
592 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | ||
593 | return err; | ||
594 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Center Playback Switch", | ||
595 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | ||
596 | return err; | ||
597 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "LFE Playback Switch", | ||
598 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | ||
599 | return err; | ||
600 | } else { | ||
601 | sprintf(name, "%s Playback Volume", chname[i]); | ||
602 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | ||
603 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
604 | return err; | ||
605 | sprintf(name, "%s Playback Switch", chname[i]); | ||
606 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | ||
607 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
608 | return err; | ||
609 | } | ||
610 | } | ||
611 | |||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | /* add playback controls for HP output */ | ||
616 | static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin_cfg *cfg) | ||
617 | { | ||
618 | struct sigmatel_spec *spec = codec->spec; | ||
619 | hda_nid_t pin = cfg->hp_pin; | ||
620 | hda_nid_t nid; | ||
621 | int i, err; | ||
622 | unsigned int wid_caps; | ||
623 | |||
624 | if (! pin) | ||
625 | return 0; | ||
626 | |||
627 | wid_caps = snd_hda_param_read(codec, pin, AC_PAR_AUDIO_WIDGET_CAP); | ||
628 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
629 | /* Enable unsolicited responses on the HP widget */ | ||
630 | snd_hda_codec_write(codec, pin, 0, | ||
631 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
632 | STAC_UNSOL_ENABLE); | ||
633 | |||
634 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
635 | for (i = 0; i < cfg->line_outs; i++) { | ||
636 | if (! spec->multiout.dac_nids[i]) | ||
637 | continue; | ||
638 | if (spec->multiout.dac_nids[i] == nid) | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | spec->multiout.hp_nid = nid; | ||
643 | |||
644 | /* control HP volume/switch on the output mixer amp */ | ||
645 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Headphone Playback Volume", | ||
646 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
647 | return err; | ||
648 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | ||
649 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
650 | return err; | ||
651 | |||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | /* create playback/capture controls for input pins */ | ||
656 | static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) | ||
657 | { | ||
658 | struct sigmatel_spec *spec = codec->spec; | ||
659 | static char *labels[AUTO_PIN_LAST] = { | ||
660 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" | ||
661 | }; | ||
662 | struct hda_input_mux *imux = &spec->private_imux; | ||
663 | hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; | ||
664 | int i, j, k; | ||
665 | |||
666 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
667 | int index = -1; | ||
668 | if (cfg->input_pins[i]) { | ||
669 | imux->items[imux->num_items].label = labels[i]; | ||
670 | |||
671 | for (j=0; j<spec->num_muxes; j++) { | ||
672 | int num_cons = snd_hda_get_connections(codec, spec->mux_nids[j], con_lst, HDA_MAX_NUM_INPUTS); | ||
673 | for (k=0; k<num_cons; k++) | ||
674 | if (con_lst[k] == cfg->input_pins[i]) { | ||
675 | index = k; | ||
676 | break; | ||
677 | } | ||
678 | if (index >= 0) | ||
679 | break; | ||
680 | } | ||
681 | imux->items[imux->num_items].index = index; | ||
682 | imux->num_items++; | ||
683 | } | ||
684 | } | ||
685 | |||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type) | ||
690 | |||
691 | { | ||
692 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type); | ||
693 | } | ||
694 | |||
695 | static void stac92xx_auto_init_multi_out(struct hda_codec *codec) | ||
696 | { | ||
697 | struct sigmatel_spec *spec = codec->spec; | ||
698 | int i; | ||
699 | |||
700 | for (i = 0; i < spec->autocfg.line_outs; i++) { | ||
701 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
702 | stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); | ||
703 | } | ||
704 | } | ||
705 | |||
706 | static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | ||
707 | { | ||
708 | struct sigmatel_spec *spec = codec->spec; | ||
709 | hda_nid_t pin; | ||
710 | |||
711 | pin = spec->autocfg.hp_pin; | ||
712 | if (pin) /* connect to front */ | ||
713 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | ||
714 | } | ||
715 | |||
716 | static int stac922x_parse_auto_config(struct hda_codec *codec) | ||
717 | { | ||
718 | struct sigmatel_spec *spec = codec->spec; | ||
719 | int err; | ||
720 | |||
721 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0) | ||
722 | return err; | ||
723 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | ||
724 | return err; | ||
725 | if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) | ||
726 | return 0; /* can't find valid pin config */ | ||
727 | |||
728 | if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | ||
729 | (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 || | ||
730 | (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | ||
731 | return err; | ||
732 | |||
733 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | ||
734 | if (spec->multiout.max_channels > 2) { | ||
735 | spec->surr_switch = 1; | ||
736 | spec->cur_ch_mode = 1; | ||
737 | spec->num_ch_modes = 2; | ||
738 | if (spec->multiout.max_channels == 8) { | ||
739 | spec->cur_ch_mode++; | ||
740 | spec->num_ch_modes++; | ||
741 | } | ||
742 | } | ||
743 | |||
744 | if (spec->autocfg.dig_out_pin) { | ||
745 | spec->multiout.dig_out_nid = 0x08; | ||
746 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); | ||
747 | } | ||
748 | if (spec->autocfg.dig_in_pin) { | ||
749 | spec->dig_in_nid = 0x09; | ||
750 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); | ||
751 | } | ||
752 | |||
753 | if (spec->kctl_alloc) | ||
754 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | ||
755 | |||
756 | spec->input_mux = &spec->private_imux; | ||
757 | |||
758 | return 1; | ||
759 | } | ||
760 | |||
761 | static int stac9200_parse_auto_config(struct hda_codec *codec) | ||
762 | { | ||
763 | struct sigmatel_spec *spec = codec->spec; | ||
764 | int err; | ||
765 | |||
766 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0) | ||
767 | return err; | ||
768 | |||
769 | if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | ||
770 | return err; | ||
771 | |||
772 | if (spec->autocfg.dig_out_pin) { | ||
773 | spec->multiout.dig_out_nid = 0x05; | ||
774 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); | ||
775 | } | ||
776 | if (spec->autocfg.dig_in_pin) { | ||
777 | spec->dig_in_nid = 0x04; | ||
778 | stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); | ||
779 | } | ||
780 | |||
781 | if (spec->kctl_alloc) | ||
782 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | ||
783 | |||
784 | spec->input_mux = &spec->private_imux; | ||
785 | |||
786 | return 1; | ||
787 | } | ||
788 | |||
789 | static int stac92xx_init_pstate(struct hda_codec *codec) | ||
790 | { | ||
791 | hda_nid_t nid, nid_start; | ||
792 | int nodes; | ||
793 | |||
794 | snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_POWER_STATE, 0x00); | ||
795 | |||
796 | nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start); | ||
797 | for (nid = nid_start; nid < nodes + nid_start; nid++) { | ||
798 | unsigned int wid_caps = snd_hda_param_read(codec, nid, | ||
799 | AC_PAR_AUDIO_WIDGET_CAP); | ||
800 | if (wid_caps & AC_WCAP_POWER) | ||
801 | snd_hda_codec_write(codec, nid, 0, | ||
802 | AC_VERB_SET_POWER_STATE, 0x00); | ||
803 | } | ||
804 | |||
805 | mdelay(100); | ||
806 | |||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static int stac92xx_init(struct hda_codec *codec) | ||
811 | { | ||
812 | struct sigmatel_spec *spec = codec->spec; | ||
813 | |||
814 | stac92xx_init_pstate(codec); | ||
815 | |||
816 | snd_hda_sequence_write(codec, spec->init); | ||
817 | |||
818 | stac92xx_auto_init_multi_out(codec); | ||
819 | stac92xx_auto_init_hp_out(codec); | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
570 | static void stac92xx_free(struct hda_codec *codec) | 824 | static void stac92xx_free(struct hda_codec *codec) |
571 | { | 825 | { |
572 | kfree(codec->spec); | 826 | struct sigmatel_spec *spec = codec->spec; |
827 | int i; | ||
828 | |||
829 | if (! spec) | ||
830 | return; | ||
831 | |||
832 | if (spec->kctl_alloc) { | ||
833 | for (i = 0; i < spec->num_kctl_used; i++) | ||
834 | kfree(spec->kctl_alloc[i].name); | ||
835 | kfree(spec->kctl_alloc); | ||
836 | } | ||
837 | |||
838 | kfree(spec); | ||
839 | } | ||
840 | |||
841 | static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | ||
842 | unsigned int flag) | ||
843 | { | ||
844 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | ||
845 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | ||
846 | snd_hda_codec_write(codec, nid, 0, | ||
847 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
848 | pin_ctl | flag); | ||
849 | } | ||
850 | |||
851 | static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | ||
852 | unsigned int flag) | ||
853 | { | ||
854 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | ||
855 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | ||
856 | snd_hda_codec_write(codec, nid, 0, | ||
857 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
858 | pin_ctl & ~flag); | ||
859 | } | ||
860 | |||
861 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
862 | { | ||
863 | struct sigmatel_spec *spec = codec->spec; | ||
864 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
865 | int i, presence; | ||
866 | |||
867 | if ((res >> 26) != STAC_HP_EVENT) | ||
868 | return; | ||
869 | |||
870 | presence = snd_hda_codec_read(codec, cfg->hp_pin, 0, | ||
871 | AC_VERB_GET_PIN_SENSE, 0x00) >> 31; | ||
872 | |||
873 | if (presence) { | ||
874 | /* disable lineouts, enable hp */ | ||
875 | for (i = 0; i < cfg->line_outs; i++) | ||
876 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], | ||
877 | AC_PINCTL_OUT_EN); | ||
878 | stac92xx_set_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | ||
879 | } else { | ||
880 | /* enable lineouts, disable hp */ | ||
881 | for (i = 0; i < cfg->line_outs; i++) | ||
882 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], | ||
883 | AC_PINCTL_OUT_EN); | ||
884 | stac92xx_reset_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | ||
885 | } | ||
886 | } | ||
887 | |||
888 | #ifdef CONFIG_PM | ||
889 | static int stac92xx_resume(struct hda_codec *codec) | ||
890 | { | ||
891 | struct sigmatel_spec *spec = codec->spec; | ||
892 | int i; | ||
893 | |||
894 | stac92xx_init(codec); | ||
895 | for (i = 0; i < spec->num_mixers; i++) | ||
896 | snd_hda_resume_ctls(codec, spec->mixers[i]); | ||
897 | if (spec->multiout.dig_out_nid) | ||
898 | snd_hda_resume_spdif_out(codec); | ||
899 | if (spec->dig_in_nid) | ||
900 | snd_hda_resume_spdif_in(codec); | ||
901 | |||
902 | return 0; | ||
573 | } | 903 | } |
904 | #endif | ||
574 | 905 | ||
575 | static struct hda_codec_ops stac92xx_patch_ops = { | 906 | static struct hda_codec_ops stac92xx_patch_ops = { |
576 | .build_controls = stac92xx_build_controls, | 907 | .build_controls = stac92xx_build_controls, |
577 | .build_pcms = stac92xx_build_pcms, | 908 | .build_pcms = stac92xx_build_pcms, |
578 | .init = stac92xx_init, | 909 | .init = stac92xx_init, |
579 | .free = stac92xx_free, | 910 | .free = stac92xx_free, |
911 | .unsol_event = stac92xx_unsol_event, | ||
912 | #ifdef CONFIG_PM | ||
913 | .resume = stac92xx_resume, | ||
914 | #endif | ||
580 | }; | 915 | }; |
581 | 916 | ||
582 | static int patch_stac9200(struct hda_codec *codec) | 917 | static int patch_stac9200(struct hda_codec *codec) |
583 | { | 918 | { |
584 | struct sigmatel_spec *spec; | 919 | struct sigmatel_spec *spec; |
920 | int err; | ||
585 | 921 | ||
586 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 922 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
587 | if (spec == NULL) | 923 | if (spec == NULL) |
@@ -589,26 +925,27 @@ static int patch_stac9200(struct hda_codec *codec) | |||
589 | 925 | ||
590 | codec->spec = spec; | 926 | codec->spec = spec; |
591 | 927 | ||
928 | #ifdef STAC_TEST | ||
929 | spec->pin_nids = stac9200_pin_nids; | ||
930 | spec->num_pins = 8; | ||
931 | spec->pin_configs = stac9200_pin_configs; | ||
932 | stac92xx_set_config_regs(codec); | ||
933 | #endif | ||
592 | spec->multiout.max_channels = 2; | 934 | spec->multiout.max_channels = 2; |
593 | spec->multiout.num_dacs = 1; | 935 | spec->multiout.num_dacs = 1; |
594 | spec->multiout.dac_nids = stac9200_dac_nids; | 936 | spec->multiout.dac_nids = stac9200_dac_nids; |
595 | spec->multiout.dig_out_nid = 0x05; | ||
596 | spec->dig_in_nid = 0x04; | ||
597 | spec->adc_nids = stac9200_adc_nids; | 937 | spec->adc_nids = stac9200_adc_nids; |
598 | spec->mux_nids = stac9200_mux_nids; | 938 | spec->mux_nids = stac9200_mux_nids; |
599 | spec->num_muxes = 1; | 939 | spec->num_muxes = 1; |
600 | spec->input_mux.num_items = 0; | 940 | |
601 | spec->pstate_nids = stac9200_pstate_nids; | 941 | spec->init = stac9200_core_init; |
602 | spec->num_pstates = 3; | ||
603 | spec->pin_nids = stac9200_pin_nids; | ||
604 | #ifdef STAC_TEST | ||
605 | spec->pin_configs = stac9200_pin_configs; | ||
606 | #endif | ||
607 | spec->num_pins = 8; | ||
608 | spec->init = stac9200_ch2_init; | ||
609 | spec->mixer = stac9200_mixer; | 942 | spec->mixer = stac9200_mixer; |
610 | spec->playback_nid = 0x02; | 943 | |
611 | spec->capture_nid = 0x03; | 944 | err = stac9200_parse_auto_config(codec); |
945 | if (err < 0) { | ||
946 | stac92xx_free(codec); | ||
947 | return err; | ||
948 | } | ||
612 | 949 | ||
613 | codec->patch_ops = stac92xx_patch_ops; | 950 | codec->patch_ops = stac92xx_patch_ops; |
614 | 951 | ||
@@ -618,6 +955,7 @@ static int patch_stac9200(struct hda_codec *codec) | |||
618 | static int patch_stac922x(struct hda_codec *codec) | 955 | static int patch_stac922x(struct hda_codec *codec) |
619 | { | 956 | { |
620 | struct sigmatel_spec *spec; | 957 | struct sigmatel_spec *spec; |
958 | int err; | ||
621 | 959 | ||
622 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | 960 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); |
623 | if (spec == NULL) | 961 | if (spec == NULL) |
@@ -625,26 +963,26 @@ static int patch_stac922x(struct hda_codec *codec) | |||
625 | 963 | ||
626 | codec->spec = spec; | 964 | codec->spec = spec; |
627 | 965 | ||
628 | spec->multiout.max_channels = 2; | ||
629 | spec->multiout.num_dacs = 4; | ||
630 | spec->multiout.dac_nids = stac922x_dac_nids; | ||
631 | spec->multiout.dig_out_nid = 0x08; | ||
632 | spec->dig_in_nid = 0x09; | ||
633 | spec->adc_nids = stac922x_adc_nids; | ||
634 | spec->mux_nids = stac922x_mux_nids; | ||
635 | spec->num_muxes = 2; | ||
636 | spec->input_mux.num_items = 0; | ||
637 | spec->pstate_nids = stac922x_pstate_nids; | ||
638 | spec->num_pstates = 8; | ||
639 | spec->pin_nids = stac922x_pin_nids; | ||
640 | #ifdef STAC_TEST | 966 | #ifdef STAC_TEST |
967 | spec->num_pins = 10; | ||
968 | spec->pin_nids = stac922x_pin_nids; | ||
641 | spec->pin_configs = stac922x_pin_configs; | 969 | spec->pin_configs = stac922x_pin_configs; |
970 | stac92xx_set_config_regs(codec); | ||
642 | #endif | 971 | #endif |
643 | spec->num_pins = 10; | 972 | spec->adc_nids = stac922x_adc_nids; |
644 | spec->init = stac922x_ch2_init; | 973 | spec->mux_nids = stac922x_mux_nids; |
974 | spec->num_muxes = 2; | ||
975 | |||
976 | spec->init = stac922x_core_init; | ||
645 | spec->mixer = stac922x_mixer; | 977 | spec->mixer = stac922x_mixer; |
646 | spec->playback_nid = 0x02; | 978 | |
647 | spec->capture_nid = 0x06; | 979 | spec->multiout.dac_nids = spec->dac_nids; |
980 | |||
981 | err = stac922x_parse_auto_config(codec); | ||
982 | if (err < 0) { | ||
983 | stac92xx_free(codec); | ||
984 | return err; | ||
985 | } | ||
648 | 986 | ||
649 | codec->patch_ops = stac92xx_patch_ops; | 987 | codec->patch_ops = stac92xx_patch_ops; |
650 | 988 | ||
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 28ac005c21b5..d7af3e474432 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -424,6 +424,7 @@ struct _snd_intel8x0 { | |||
424 | unsigned xbox: 1; /* workaround for Xbox AC'97 detection */ | 424 | unsigned xbox: 1; /* workaround for Xbox AC'97 detection */ |
425 | 425 | ||
426 | int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */ | 426 | int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */ |
427 | unsigned int sdm_saved; /* SDM reg value */ | ||
427 | 428 | ||
428 | ac97_bus_t *ac97_bus; | 429 | ac97_bus_t *ac97_bus; |
429 | ac97_t *ac97[3]; | 430 | ac97_t *ac97[3]; |
@@ -2373,6 +2374,9 @@ static int intel8x0_suspend(snd_card_t *card, pm_message_t state) | |||
2373 | for (i = 0; i < 3; i++) | 2374 | for (i = 0; i < 3; i++) |
2374 | if (chip->ac97[i]) | 2375 | if (chip->ac97[i]) |
2375 | snd_ac97_suspend(chip->ac97[i]); | 2376 | snd_ac97_suspend(chip->ac97[i]); |
2377 | if (chip->device_type == DEVICE_INTEL_ICH4) | ||
2378 | chip->sdm_saved = igetbyte(chip, ICHREG(SDM)); | ||
2379 | |||
2376 | if (chip->irq >= 0) | 2380 | if (chip->irq >= 0) |
2377 | free_irq(chip->irq, (void *)chip); | 2381 | free_irq(chip->irq, (void *)chip); |
2378 | pci_disable_device(chip->pci); | 2382 | pci_disable_device(chip->pci); |
@@ -2390,6 +2394,16 @@ static int intel8x0_resume(snd_card_t *card) | |||
2390 | synchronize_irq(chip->irq); | 2394 | synchronize_irq(chip->irq); |
2391 | snd_intel8x0_chip_init(chip, 1); | 2395 | snd_intel8x0_chip_init(chip, 1); |
2392 | 2396 | ||
2397 | /* re-initialize mixer stuff */ | ||
2398 | if (chip->device_type == DEVICE_INTEL_ICH4) { | ||
2399 | /* enable separate SDINs for ICH4 */ | ||
2400 | iputbyte(chip, ICHREG(SDM), chip->sdm_saved); | ||
2401 | /* use slot 10/11 for SPDIF */ | ||
2402 | iputdword(chip, ICHREG(GLOB_CNT), | ||
2403 | (igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK) | | ||
2404 | ICH_PCM_SPDIF_1011); | ||
2405 | } | ||
2406 | |||
2393 | /* refill nocache */ | 2407 | /* refill nocache */ |
2394 | if (chip->fix_nocache) | 2408 | if (chip->fix_nocache) |
2395 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); | 2409 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); |
@@ -2455,8 +2469,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip) | |||
2455 | } | 2469 | } |
2456 | do_gettimeofday(&start_time); | 2470 | do_gettimeofday(&start_time); |
2457 | spin_unlock_irq(&chip->reg_lock); | 2471 | spin_unlock_irq(&chip->reg_lock); |
2458 | set_current_state(TASK_UNINTERRUPTIBLE); | 2472 | msleep(50); |
2459 | schedule_timeout(HZ / 20); | ||
2460 | spin_lock_irq(&chip->reg_lock); | 2473 | spin_lock_irq(&chip->reg_lock); |
2461 | /* check the position */ | 2474 | /* check the position */ |
2462 | pos = ichdev->fragsize1; | 2475 | pos = ichdev->fragsize1; |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 52c585901c54..39b5e7db1543 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -1050,11 +1050,6 @@ static struct m3_hv_quirk m3_hv_quirk_list[] = { | |||
1050 | * lowlevel functions | 1050 | * lowlevel functions |
1051 | */ | 1051 | */ |
1052 | 1052 | ||
1053 | #define big_mdelay(msec) do {\ | ||
1054 | set_current_state(TASK_UNINTERRUPTIBLE);\ | ||
1055 | schedule_timeout(((msec) * HZ) / 1000);\ | ||
1056 | } while (0) | ||
1057 | |||
1058 | static inline void snd_m3_outw(m3_t *chip, u16 value, unsigned long reg) | 1053 | static inline void snd_m3_outw(m3_t *chip, u16 value, unsigned long reg) |
1059 | { | 1054 | { |
1060 | outw(value, chip->iobase + reg); | 1055 | outw(value, chip->iobase + reg); |
@@ -1096,7 +1091,7 @@ static void snd_m3_assp_write(m3_t *chip, u16 region, u16 index, u16 data) | |||
1096 | static void snd_m3_assp_halt(m3_t *chip) | 1091 | static void snd_m3_assp_halt(m3_t *chip) |
1097 | { | 1092 | { |
1098 | chip->reset_state = snd_m3_inb(chip, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK; | 1093 | chip->reset_state = snd_m3_inb(chip, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK; |
1099 | big_mdelay(10); | 1094 | msleep(10); |
1100 | snd_m3_outb(chip, chip->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B); | 1095 | snd_m3_outb(chip, chip->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B); |
1101 | } | 1096 | } |
1102 | 1097 | ||
@@ -2108,9 +2103,9 @@ static void snd_m3_ac97_reset(m3_t *chip) | |||
2108 | */ | 2103 | */ |
2109 | tmp = inw(io + RING_BUS_CTRL_A); | 2104 | tmp = inw(io + RING_BUS_CTRL_A); |
2110 | outw(RAC_SDFS_ENABLE|LAC_SDFS_ENABLE, io + RING_BUS_CTRL_A); | 2105 | outw(RAC_SDFS_ENABLE|LAC_SDFS_ENABLE, io + RING_BUS_CTRL_A); |
2111 | big_mdelay(20); | 2106 | msleep(20); |
2112 | outw(tmp, io + RING_BUS_CTRL_A); | 2107 | outw(tmp, io + RING_BUS_CTRL_A); |
2113 | big_mdelay(50); | 2108 | msleep(50); |
2114 | #endif | 2109 | #endif |
2115 | } | 2110 | } |
2116 | 2111 | ||
@@ -2525,9 +2520,13 @@ static void | |||
2525 | snd_m3_enable_ints(m3_t *chip) | 2520 | snd_m3_enable_ints(m3_t *chip) |
2526 | { | 2521 | { |
2527 | unsigned long io = chip->iobase; | 2522 | unsigned long io = chip->iobase; |
2523 | unsigned short val; | ||
2528 | 2524 | ||
2529 | /* TODO: MPU401 not supported yet */ | 2525 | /* TODO: MPU401 not supported yet */ |
2530 | outw(ASSP_INT_ENABLE | HV_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL); | 2526 | val = ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/; |
2527 | if (chip->hv_quirk && (chip->hv_quirk->config & HV_CTRL_ENABLE)) | ||
2528 | val |= HV_INT_ENABLE; | ||
2529 | outw(val, io + HOST_INT_CTRL); | ||
2531 | outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, | 2530 | outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, |
2532 | io + ASSP_CONTROL_C); | 2531 | io + ASSP_CONTROL_C); |
2533 | } | 2532 | } |
@@ -2589,7 +2588,7 @@ static int m3_suspend(snd_card_t *card, pm_message_t state) | |||
2589 | snd_pcm_suspend_all(chip->pcm); | 2588 | snd_pcm_suspend_all(chip->pcm); |
2590 | snd_ac97_suspend(chip->ac97); | 2589 | snd_ac97_suspend(chip->ac97); |
2591 | 2590 | ||
2592 | big_mdelay(10); /* give the assp a chance to idle.. */ | 2591 | msleep(10); /* give the assp a chance to idle.. */ |
2593 | 2592 | ||
2594 | snd_m3_assp_halt(chip); | 2593 | snd_m3_assp_halt(chip); |
2595 | 2594 | ||
@@ -2697,6 +2696,8 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, | |||
2697 | } | 2696 | } |
2698 | 2697 | ||
2699 | spin_lock_init(&chip->reg_lock); | 2698 | spin_lock_init(&chip->reg_lock); |
2699 | spin_lock_init(&chip->ac97_lock); | ||
2700 | |||
2700 | switch (pci->device) { | 2701 | switch (pci->device) { |
2701 | case PCI_DEVICE_ID_ESS_ALLEGRO: | 2702 | case PCI_DEVICE_ID_ESS_ALLEGRO: |
2702 | case PCI_DEVICE_ID_ESS_ALLEGRO_1: | 2703 | case PCI_DEVICE_ID_ESS_ALLEGRO_1: |
@@ -2765,6 +2766,8 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, | |||
2765 | snd_m3_assp_init(chip); | 2766 | snd_m3_assp_init(chip); |
2766 | snd_m3_amp_enable(chip, 1); | 2767 | snd_m3_amp_enable(chip, 1); |
2767 | 2768 | ||
2769 | tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); | ||
2770 | |||
2768 | if (request_irq(pci->irq, snd_m3_interrupt, SA_INTERRUPT|SA_SHIRQ, | 2771 | if (request_irq(pci->irq, snd_m3_interrupt, SA_INTERRUPT|SA_SHIRQ, |
2769 | card->driver, (void *)chip)) { | 2772 | card->driver, (void *)chip)) { |
2770 | snd_printk("unable to grab IRQ %d\n", pci->irq); | 2773 | snd_printk("unable to grab IRQ %d\n", pci->irq); |
@@ -2786,9 +2789,6 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci, | |||
2786 | return err; | 2789 | return err; |
2787 | } | 2790 | } |
2788 | 2791 | ||
2789 | spin_lock_init(&chip->ac97_lock); | ||
2790 | tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); | ||
2791 | |||
2792 | if ((err = snd_m3_mixer(chip)) < 0) | 2792 | if ((err = snd_m3_mixer(chip)) < 0) |
2793 | return err; | 2793 | return err; |
2794 | 2794 | ||
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 082c0d0f73d2..6c868d913634 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -445,9 +445,9 @@ static int snd_mixart_trigger(snd_pcm_substream_t *subs, int cmd) | |||
445 | 445 | ||
446 | static int mixart_sync_nonblock_events(mixart_mgr_t *mgr) | 446 | static int mixart_sync_nonblock_events(mixart_mgr_t *mgr) |
447 | { | 447 | { |
448 | int timeout = HZ; | 448 | unsigned long timeout = jiffies + HZ; |
449 | while (atomic_read(&mgr->msg_processed) > 0) { | 449 | while (atomic_read(&mgr->msg_processed) > 0) { |
450 | if (! timeout--) { | 450 | if (time_after(jiffies, timeout)) { |
451 | snd_printk(KERN_ERR "mixart: cannot process nonblock events!\n"); | 451 | snd_printk(KERN_ERR "mixart: cannot process nonblock events!\n"); |
452 | return -EBUSY; | 452 | return -EBUSY; |
453 | } | 453 | } |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index a673cc438b91..796621de5009 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -445,6 +445,7 @@ struct _hdsp { | |||
445 | u32 control2_register; /* cached value */ | 445 | u32 control2_register; /* cached value */ |
446 | u32 creg_spdif; | 446 | u32 creg_spdif; |
447 | u32 creg_spdif_stream; | 447 | u32 creg_spdif_stream; |
448 | int clock_source_locked; | ||
448 | char *card_name; /* digiface/multiface */ | 449 | char *card_name; /* digiface/multiface */ |
449 | HDSP_IO_Type io_type; /* ditto, but for code use */ | 450 | HDSP_IO_Type io_type; /* ditto, but for code use */ |
450 | unsigned short firmware_rev; | 451 | unsigned short firmware_rev; |
@@ -678,8 +679,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) { | |||
678 | } | 679 | } |
679 | 680 | ||
680 | if ((1000 / HZ) < 3000) { | 681 | if ((1000 / HZ) < 3000) { |
681 | set_current_state(TASK_UNINTERRUPTIBLE); | 682 | ssleep(3); |
682 | schedule_timeout((3000 * HZ + 999) / 1000); | ||
683 | } else { | 683 | } else { |
684 | mdelay(3000); | 684 | mdelay(3000); |
685 | } | 685 | } |
@@ -2095,6 +2095,34 @@ static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_val | |||
2095 | return change; | 2095 | return change; |
2096 | } | 2096 | } |
2097 | 2097 | ||
2098 | static int snd_hdsp_info_clock_source_lock(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) | ||
2099 | { | ||
2100 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2101 | uinfo->count = 1; | ||
2102 | uinfo->value.integer.min = 0; | ||
2103 | uinfo->value.integer.max = 1; | ||
2104 | return 0; | ||
2105 | } | ||
2106 | |||
2107 | static int snd_hdsp_get_clock_source_lock(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
2108 | { | ||
2109 | hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); | ||
2110 | |||
2111 | ucontrol->value.integer.value[0] = hdsp->clock_source_locked; | ||
2112 | return 0; | ||
2113 | } | ||
2114 | |||
2115 | static int snd_hdsp_put_clock_source_lock(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) | ||
2116 | { | ||
2117 | hdsp_t *hdsp = snd_kcontrol_chip(kcontrol); | ||
2118 | int change; | ||
2119 | |||
2120 | change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked; | ||
2121 | if (change) | ||
2122 | hdsp->clock_source_locked = ucontrol->value.integer.value[0]; | ||
2123 | return change; | ||
2124 | } | ||
2125 | |||
2098 | #define HDSP_DA_GAIN(xname, xindex) \ | 2126 | #define HDSP_DA_GAIN(xname, xindex) \ |
2099 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | 2127 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ |
2100 | .name = xname, \ | 2128 | .name = xname, \ |
@@ -3117,6 +3145,15 @@ HDSP_SPDIF_EMPHASIS("IEC958 Emphasis Bit", 0), | |||
3117 | HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0), | 3145 | HDSP_SPDIF_NON_AUDIO("IEC958 Non-audio Bit", 0), |
3118 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ | 3146 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ |
3119 | HDSP_CLOCK_SOURCE("Sample Clock Source", 0), | 3147 | HDSP_CLOCK_SOURCE("Sample Clock Source", 0), |
3148 | { | ||
3149 | /* FIXME: should be PCM or MIXER? */ | ||
3150 | /* .iface = SNDRV_CTL_ELEM_IFACE_PCM, */ | ||
3151 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3152 | .name = "Sample Clock Source Locking", | ||
3153 | .info = snd_hdsp_info_clock_source_lock, | ||
3154 | .get = snd_hdsp_get_clock_source_lock, | ||
3155 | .put = snd_hdsp_put_clock_source_lock, | ||
3156 | }, | ||
3120 | HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | 3157 | HDSP_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
3121 | HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0), | 3158 | HDSP_PREF_SYNC_REF("Preferred Sync Reference", 0), |
3122 | HDSP_AUTOSYNC_REF("AutoSync Reference", 0), | 3159 | HDSP_AUTOSYNC_REF("AutoSync Reference", 0), |
@@ -3349,6 +3386,7 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer) | |||
3349 | snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode); | 3386 | snd_iprintf (buffer, "System Clock Mode: %s\n", system_clock_mode); |
3350 | 3387 | ||
3351 | snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate); | 3388 | snd_iprintf (buffer, "System Clock Frequency: %d\n", hdsp->system_sample_rate); |
3389 | snd_iprintf (buffer, "System Clock Locked: %s\n", hdsp->clock_source_locked ? "Yes" : "No"); | ||
3352 | 3390 | ||
3353 | snd_iprintf(buffer, "\n"); | 3391 | snd_iprintf(buffer, "\n"); |
3354 | 3392 | ||
@@ -3853,13 +3891,14 @@ static int snd_hdsp_hw_params(snd_pcm_substream_t *substream, | |||
3853 | */ | 3891 | */ |
3854 | 3892 | ||
3855 | spin_lock_irq(&hdsp->lock); | 3893 | spin_lock_irq(&hdsp->lock); |
3856 | if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) { | 3894 | if (! hdsp->clock_source_locked) { |
3857 | spin_unlock_irq(&hdsp->lock); | 3895 | if ((err = hdsp_set_rate(hdsp, params_rate(params), 0)) < 0) { |
3858 | _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); | 3896 | spin_unlock_irq(&hdsp->lock); |
3859 | return err; | 3897 | _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); |
3860 | } else { | 3898 | return err; |
3861 | spin_unlock_irq(&hdsp->lock); | 3899 | } |
3862 | } | 3900 | } |
3901 | spin_unlock_irq(&hdsp->lock); | ||
3863 | 3902 | ||
3864 | if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) { | 3903 | if ((err = hdsp_set_interrupt_interval(hdsp, params_period_size(params))) < 0) { |
3865 | _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | 3904 | _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); |
@@ -4284,13 +4323,17 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream) | |||
4284 | 4323 | ||
4285 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | 4324 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); |
4286 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes); | 4325 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes); |
4287 | if (hdsp->io_type == H9632) { | 4326 | if (hdsp->clock_source_locked) { |
4288 | runtime->hw.channels_min = hdsp->qs_out_channels; | 4327 | runtime->hw.rate_min = runtime->hw.rate_max = hdsp->system_sample_rate; |
4289 | runtime->hw.channels_max = hdsp->ss_out_channels; | 4328 | } else if (hdsp->io_type == H9632) { |
4290 | runtime->hw.rate_max = 192000; | 4329 | runtime->hw.rate_max = 192000; |
4291 | runtime->hw.rates = SNDRV_PCM_RATE_KNOT; | 4330 | runtime->hw.rates = SNDRV_PCM_RATE_KNOT; |
4292 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates); | 4331 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hdsp_hw_constraints_9632_sample_rates); |
4293 | } | 4332 | } |
4333 | if (hdsp->io_type == H9632) { | ||
4334 | runtime->hw.channels_min = hdsp->qs_out_channels; | ||
4335 | runtime->hw.channels_max = hdsp->ss_out_channels; | ||
4336 | } | ||
4294 | 4337 | ||
4295 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 4338 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
4296 | snd_hdsp_hw_rule_out_channels, hdsp, | 4339 | snd_hdsp_hw_rule_out_channels, hdsp, |
@@ -5036,8 +5079,7 @@ static int __devinit snd_hdsp_create(snd_card_t *card, | |||
5036 | if (!is_9652 && !is_9632) { | 5079 | if (!is_9652 && !is_9632) { |
5037 | /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ | 5080 | /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ |
5038 | if ((1000 / HZ) < 2000) { | 5081 | if ((1000 / HZ) < 2000) { |
5039 | set_current_state(TASK_UNINTERRUPTIBLE); | 5082 | ssleep(2); |
5040 | schedule_timeout((2000 * HZ + 999) / 1000); | ||
5041 | } else { | 5083 | } else { |
5042 | mdelay(2000); | 5084 | mdelay(2000); |
5043 | } | 5085 | } |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index a09b0fb49e81..29d89bfba0a4 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -472,6 +472,7 @@ void snd_trident_write_voice_regs(trident_t * trident, | |||
472 | break; | 472 | break; |
473 | default: | 473 | default: |
474 | snd_BUG(); | 474 | snd_BUG(); |
475 | return; | ||
475 | } | 476 | } |
476 | 477 | ||
477 | outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); | 478 | outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR)); |
@@ -3152,8 +3153,7 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode) | |||
3152 | switch (mode) { | 3153 | switch (mode) { |
3153 | case GAMEPORT_MODE_COOKED: | 3154 | case GAMEPORT_MODE_COOKED: |
3154 | outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR)); | 3155 | outb(GAMEPORT_MODE_ADC, TRID_REG(chip, GAMEPORT_GCR)); |
3155 | set_current_state(TASK_UNINTERRUPTIBLE); | 3156 | msleep(20); |
3156 | schedule_timeout(1 + 20 * HZ / 1000); /* 20msec */ | ||
3157 | return 0; | 3157 | return 0; |
3158 | case GAMEPORT_MODE_RAW: | 3158 | case GAMEPORT_MODE_RAW: |
3159 | outb(0, TRID_REG(chip, GAMEPORT_GCR)); | 3159 | outb(0, TRID_REG(chip, GAMEPORT_GCR)); |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 42c48f0ce8e8..4889600387c8 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -547,8 +547,7 @@ static void snd_via82xx_codec_wait(ac97_t *ac97) | |||
547 | int err; | 547 | int err; |
548 | err = snd_via82xx_codec_ready(chip, ac97->num); | 548 | err = snd_via82xx_codec_ready(chip, ac97->num); |
549 | /* here we need to wait fairly for long time.. */ | 549 | /* here we need to wait fairly for long time.. */ |
550 | set_current_state(TASK_UNINTERRUPTIBLE); | 550 | msleep(500); |
551 | schedule_timeout(HZ/2); | ||
552 | } | 551 | } |
553 | 552 | ||
554 | static void snd_via82xx_codec_write(ac97_t *ac97, | 553 | static void snd_via82xx_codec_write(ac97_t *ac97, |
@@ -1847,7 +1846,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip) | |||
1847 | static int snd_via82xx_chip_init(via82xx_t *chip) | 1846 | static int snd_via82xx_chip_init(via82xx_t *chip) |
1848 | { | 1847 | { |
1849 | unsigned int val; | 1848 | unsigned int val; |
1850 | int max_count; | 1849 | unsigned long end_time; |
1851 | unsigned char pval; | 1850 | unsigned char pval; |
1852 | 1851 | ||
1853 | #if 0 /* broken on K7M? */ | 1852 | #if 0 /* broken on K7M? */ |
@@ -1889,14 +1888,14 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
1889 | } | 1888 | } |
1890 | 1889 | ||
1891 | /* wait until codec ready */ | 1890 | /* wait until codec ready */ |
1892 | max_count = ((3 * HZ) / 4) + 1; | 1891 | end_time = jiffies + msecs_to_jiffies(750); |
1893 | do { | 1892 | do { |
1894 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 1893 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
1895 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 1894 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
1896 | break; | 1895 | break; |
1897 | set_current_state(TASK_UNINTERRUPTIBLE); | 1896 | set_current_state(TASK_UNINTERRUPTIBLE); |
1898 | schedule_timeout(1); | 1897 | schedule_timeout(1); |
1899 | } while (--max_count > 0); | 1898 | } while (time_before(jiffies, end_time)); |
1900 | 1899 | ||
1901 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 1900 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
1902 | snd_printk("AC'97 codec is not ready [0x%x]\n", val); | 1901 | snd_printk("AC'97 codec is not ready [0x%x]\n", val); |
@@ -1905,7 +1904,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
1905 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | | 1904 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | |
1906 | VIA_REG_AC97_SECONDARY_VALID | | 1905 | VIA_REG_AC97_SECONDARY_VALID | |
1907 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); | 1906 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); |
1908 | max_count = ((3 * HZ) / 4) + 1; | 1907 | end_time = jiffies + msecs_to_jiffies(750); |
1909 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | | 1908 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | |
1910 | VIA_REG_AC97_SECONDARY_VALID | | 1909 | VIA_REG_AC97_SECONDARY_VALID | |
1911 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); | 1910 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); |
@@ -1916,7 +1915,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
1916 | } | 1915 | } |
1917 | set_current_state(TASK_INTERRUPTIBLE); | 1916 | set_current_state(TASK_INTERRUPTIBLE); |
1918 | schedule_timeout(1); | 1917 | schedule_timeout(1); |
1919 | } while (--max_count > 0); | 1918 | } while (time_before(jiffies, end_time)); |
1920 | /* This is ok, the most of motherboards have only one codec */ | 1919 | /* This is ok, the most of motherboards have only one codec */ |
1921 | 1920 | ||
1922 | __ac97_ok2: | 1921 | __ac97_ok2: |
@@ -2178,7 +2177,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) | |||
2178 | { .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */ | 2177 | { .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */ |
2179 | { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ | 2178 | { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */ |
2180 | { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ | 2179 | { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */ |
2181 | { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_NO_VRA }, /* Twinhead mobo */ | 2180 | { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_SRC }, /* Twinhead laptop */ |
2182 | { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ | 2181 | { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */ |
2183 | { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ | 2182 | { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */ |
2184 | { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ | 2183 | { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */ |
@@ -2187,6 +2186,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci) | |||
2187 | { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ | 2186 | { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */ |
2188 | { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ | 2187 | { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ |
2189 | { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */ | 2188 | { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */ |
2189 | { .subvendor = 0x4005, .subdevice = 0x4710, .action = VIA_DXS_SRC }, /* MSI K7T266 Pro2 (MS-6380 V2.0) BIOS 3.7 */ | ||
2190 | { } /* terminator */ | 2190 | { } /* terminator */ |
2191 | }; | 2191 | }; |
2192 | struct dxs_whitelist *w; | 2192 | struct dxs_whitelist *w; |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 5896d289f9ac..4a9779cc9733 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -408,8 +408,7 @@ static void snd_via82xx_codec_wait(ac97_t *ac97) | |||
408 | int err; | 408 | int err; |
409 | err = snd_via82xx_codec_ready(chip, ac97->num); | 409 | err = snd_via82xx_codec_ready(chip, ac97->num); |
410 | /* here we need to wait fairly for long time.. */ | 410 | /* here we need to wait fairly for long time.. */ |
411 | set_current_state(TASK_UNINTERRUPTIBLE); | 411 | msleep(500); |
412 | schedule_timeout(HZ/2); | ||
413 | } | 412 | } |
414 | 413 | ||
415 | static void snd_via82xx_codec_write(ac97_t *ac97, | 414 | static void snd_via82xx_codec_write(ac97_t *ac97, |
@@ -923,7 +922,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip) | |||
923 | static int snd_via82xx_chip_init(via82xx_t *chip) | 922 | static int snd_via82xx_chip_init(via82xx_t *chip) |
924 | { | 923 | { |
925 | unsigned int val; | 924 | unsigned int val; |
926 | int max_count; | 925 | unsigned long end_time; |
927 | unsigned char pval; | 926 | unsigned char pval; |
928 | 927 | ||
929 | pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval); | 928 | pci_read_config_byte(chip->pci, VIA_MC97_CTRL, &pval); |
@@ -962,14 +961,14 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
962 | } | 961 | } |
963 | 962 | ||
964 | /* wait until codec ready */ | 963 | /* wait until codec ready */ |
965 | max_count = ((3 * HZ) / 4) + 1; | 964 | end_time = jiffies + msecs_to_jiffies(750); |
966 | do { | 965 | do { |
967 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 966 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
968 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 967 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
969 | break; | 968 | break; |
970 | set_current_state(TASK_UNINTERRUPTIBLE); | 969 | set_current_state(TASK_UNINTERRUPTIBLE); |
971 | schedule_timeout(1); | 970 | schedule_timeout(1); |
972 | } while (--max_count > 0); | 971 | } while (time_before(jiffies, end_time)); |
973 | 972 | ||
974 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 973 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
975 | snd_printk("AC'97 codec is not ready [0x%x]\n", val); | 974 | snd_printk("AC'97 codec is not ready [0x%x]\n", val); |
@@ -977,7 +976,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
977 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | | 976 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | |
978 | VIA_REG_AC97_SECONDARY_VALID | | 977 | VIA_REG_AC97_SECONDARY_VALID | |
979 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); | 978 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); |
980 | max_count = ((3 * HZ) / 4) + 1; | 979 | end_time = jiffies + msecs_to_jiffies(750); |
981 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | | 980 | snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ | |
982 | VIA_REG_AC97_SECONDARY_VALID | | 981 | VIA_REG_AC97_SECONDARY_VALID | |
983 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); | 982 | (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT)); |
@@ -988,7 +987,7 @@ static int snd_via82xx_chip_init(via82xx_t *chip) | |||
988 | } | 987 | } |
989 | set_current_state(TASK_INTERRUPTIBLE); | 988 | set_current_state(TASK_INTERRUPTIBLE); |
990 | schedule_timeout(1); | 989 | schedule_timeout(1); |
991 | } while (--max_count > 0); | 990 | } while (time_before(jiffies, end_time)); |
992 | /* This is ok, the most of motherboards have only one codec */ | 991 | /* This is ok, the most of motherboards have only one codec */ |
993 | 992 | ||
994 | __ac97_ok2: | 993 | __ac97_ok2: |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 2ae79610ecb5..d54f88a1b525 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -84,16 +84,16 @@ static inline void snd_ymfpci_writel(ymfpci_t *chip, u32 offset, u32 val) | |||
84 | 84 | ||
85 | static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary) | 85 | static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary) |
86 | { | 86 | { |
87 | signed long end_time; | 87 | unsigned long end_time; |
88 | u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR; | 88 | u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR; |
89 | 89 | ||
90 | end_time = (jiffies + ((3 * HZ) / 4)) + 1; | 90 | end_time = jiffies + msecs_to_jiffies(750); |
91 | do { | 91 | do { |
92 | if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0) | 92 | if ((snd_ymfpci_readw(chip, reg) & 0x8000) == 0) |
93 | return 0; | 93 | return 0; |
94 | set_current_state(TASK_UNINTERRUPTIBLE); | 94 | set_current_state(TASK_UNINTERRUPTIBLE); |
95 | schedule_timeout(1); | 95 | schedule_timeout(1); |
96 | } while (end_time - (signed long)jiffies >= 0); | 96 | } while (time_before(jiffies, end_time)); |
97 | snd_printk("codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); | 97 | snd_printk("codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_ymfpci_readw(chip, reg)); |
98 | return -EBUSY; | 98 | return -EBUSY; |
99 | } | 99 | } |
diff --git a/sound/pcmcia/Kconfig b/sound/pcmcia/Kconfig index 3611e298834f..5d1b0b762efa 100644 --- a/sound/pcmcia/Kconfig +++ b/sound/pcmcia/Kconfig | |||
@@ -8,23 +8,12 @@ config SND_VXPOCKET | |||
8 | depends on SND && PCMCIA && ISA | 8 | depends on SND && PCMCIA && ISA |
9 | select SND_VX_LIB | 9 | select SND_VX_LIB |
10 | help | 10 | help |
11 | Say Y here to include support for Digigram VXpocket | 11 | Say Y here to include support for Digigram VXpocket and |
12 | soundcards. | 12 | VXpocket 440 soundcards. |
13 | 13 | ||
14 | To compile this driver as a module, choose M here: the module | 14 | To compile this driver as a module, choose M here: the module |
15 | will be called snd-vxpocket. | 15 | will be called snd-vxpocket. |
16 | 16 | ||
17 | config SND_VXP440 | ||
18 | tristate "Digigram VXpocket 440" | ||
19 | depends on SND && PCMCIA && ISA | ||
20 | select SND_VX_LIB | ||
21 | help | ||
22 | Say Y here to include support for Digigram VXpocket 440 | ||
23 | soundcards. | ||
24 | |||
25 | To compile this driver as a module, choose M here: the module | ||
26 | will be called snd-vxp440. | ||
27 | |||
28 | config SND_PDAUDIOCF | 17 | config SND_PDAUDIOCF |
29 | tristate "Sound Core PDAudioCF" | 18 | tristate "Sound Core PDAudioCF" |
30 | depends on SND && PCMCIA && ISA | 19 | depends on SND && PCMCIA && ISA |
diff --git a/sound/pcmcia/vx/Makefile b/sound/pcmcia/vx/Makefile index f35dfa1af094..54971f01e968 100644 --- a/sound/pcmcia/vx/Makefile +++ b/sound/pcmcia/vx/Makefile | |||
@@ -3,9 +3,6 @@ | |||
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-vx-cs-objs := vx_entry.o vxp_ops.o vxp_mixer.o | 6 | snd-vxpocket-objs := vxpocket.o vxp_ops.o vxp_mixer.o |
7 | snd-vxpocket-objs := vxpocket.o | ||
8 | snd-vxp440-objs := vxp440.o | ||
9 | 7 | ||
10 | obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o snd-vx-cs.o | 8 | obj-$(CONFIG_SND_VXPOCKET) += snd-vxpocket.o |
11 | obj-$(CONFIG_SND_VXP440) += snd-vxp440.o snd-vx-cs.o | ||
diff --git a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c deleted file mode 100644 index df7a39ba9680..000000000000 --- a/sound/pcmcia/vx/vx_entry.c +++ /dev/null | |||
@@ -1,375 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for Digigram VXpocket soundcards | ||
3 | * | ||
4 | * PCMCIA entry part | ||
5 | * | ||
6 | * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <sound/driver.h> | ||
24 | #include <sound/core.h> | ||
25 | #include "vxpocket.h" | ||
26 | #include <pcmcia/ciscode.h> | ||
27 | #include <pcmcia/cisreg.h> | ||
28 | |||
29 | |||
30 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); | ||
31 | MODULE_DESCRIPTION("Common routines for Digigram PCMCIA VX drivers"); | ||
32 | MODULE_LICENSE("GPL"); | ||
33 | |||
34 | /* | ||
35 | * prototypes | ||
36 | */ | ||
37 | static void vxpocket_config(dev_link_t *link); | ||
38 | |||
39 | |||
40 | static void vxpocket_release(dev_link_t *link) | ||
41 | { | ||
42 | if (link->state & DEV_CONFIG) { | ||
43 | /* release cs resources */ | ||
44 | pcmcia_release_configuration(link->handle); | ||
45 | pcmcia_release_io(link->handle, &link->io); | ||
46 | pcmcia_release_irq(link->handle, &link->irq); | ||
47 | link->state &= ~DEV_CONFIG; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * destructor | ||
53 | */ | ||
54 | static int snd_vxpocket_free(vx_core_t *chip) | ||
55 | { | ||
56 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
57 | struct snd_vxp_entry *hw; | ||
58 | dev_link_t *link = &vxp->link; | ||
59 | |||
60 | vxpocket_release(link); | ||
61 | |||
62 | /* Break the link with Card Services */ | ||
63 | if (link->handle) | ||
64 | pcmcia_deregister_client(link->handle); | ||
65 | |||
66 | hw = vxp->hw_entry; | ||
67 | if (hw) | ||
68 | hw->card_list[vxp->index] = NULL; | ||
69 | chip->card = NULL; | ||
70 | kfree(chip->dev); | ||
71 | |||
72 | snd_vx_free_firmware(chip); | ||
73 | kfree(chip); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int snd_vxpocket_dev_free(snd_device_t *device) | ||
78 | { | ||
79 | vx_core_t *chip = device->device_data; | ||
80 | return snd_vxpocket_free(chip); | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * snd_vxpocket_attach - attach callback for cs | ||
85 | * @hw: the hardware information | ||
86 | */ | ||
87 | dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw) | ||
88 | { | ||
89 | client_reg_t client_reg; /* Register with cardmgr */ | ||
90 | dev_link_t *link; /* Info for cardmgr */ | ||
91 | int i, ret; | ||
92 | vx_core_t *chip; | ||
93 | struct snd_vxpocket *vxp; | ||
94 | snd_card_t *card; | ||
95 | static snd_device_ops_t ops = { | ||
96 | .dev_free = snd_vxpocket_dev_free, | ||
97 | }; | ||
98 | |||
99 | snd_printdd(KERN_DEBUG "vxpocket_attach called\n"); | ||
100 | /* find an empty slot from the card list */ | ||
101 | for (i = 0; i < SNDRV_CARDS; i++) { | ||
102 | if (! hw->card_list[i]) | ||
103 | break; | ||
104 | } | ||
105 | if (i >= SNDRV_CARDS) { | ||
106 | snd_printk(KERN_ERR "vxpocket: too many cards found\n"); | ||
107 | return NULL; | ||
108 | } | ||
109 | if (! hw->enable_table[i]) | ||
110 | return NULL; /* disabled explicitly */ | ||
111 | |||
112 | /* ok, create a card instance */ | ||
113 | card = snd_card_new(hw->index_table[i], hw->id_table[i], THIS_MODULE, 0); | ||
114 | if (card == NULL) { | ||
115 | snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); | ||
116 | return NULL; | ||
117 | } | ||
118 | |||
119 | chip = snd_vx_create(card, hw->hardware, hw->ops, | ||
120 | sizeof(struct snd_vxpocket) - sizeof(vx_core_t)); | ||
121 | if (! chip) | ||
122 | return NULL; | ||
123 | |||
124 | #ifdef SND_VX_FW_LOADER | ||
125 | /* fake a device here since pcmcia doesn't give a valid device... */ | ||
126 | chip->dev = kcalloc(1, sizeof(*chip->dev), GFP_KERNEL); | ||
127 | if (! chip->dev) { | ||
128 | snd_printk(KERN_ERR "vxp: can't malloc chip->dev\n"); | ||
129 | kfree(chip); | ||
130 | snd_card_free(card); | ||
131 | return NULL; | ||
132 | } | ||
133 | device_initialize(chip->dev); | ||
134 | sprintf(chip->dev->bus_id, "vxpocket%d", i); | ||
135 | #endif | ||
136 | |||
137 | if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) { | ||
138 | kfree(chip); | ||
139 | snd_card_free(card); | ||
140 | return NULL; | ||
141 | } | ||
142 | |||
143 | vxp = (struct snd_vxpocket *)chip; | ||
144 | vxp->index = i; | ||
145 | vxp->hw_entry = hw; | ||
146 | chip->ibl.size = hw->ibl[i]; | ||
147 | hw->card_list[i] = chip; | ||
148 | |||
149 | link = &vxp->link; | ||
150 | link->priv = chip; | ||
151 | |||
152 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
153 | link->io.NumPorts1 = 16; | ||
154 | |||
155 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
156 | // link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | ||
157 | |||
158 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
159 | link->irq.Handler = &snd_vx_irq_handler; | ||
160 | link->irq.Instance = chip; | ||
161 | |||
162 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
163 | link->conf.Vcc = 50; | ||
164 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
165 | link->conf.ConfigIndex = 1; | ||
166 | link->conf.Present = PRESENT_OPTION; | ||
167 | |||
168 | /* Register with Card Services */ | ||
169 | memset(&client_reg, 0, sizeof(client_reg)); | ||
170 | client_reg.dev_info = hw->dev_info; | ||
171 | client_reg.Version = 0x0210; | ||
172 | client_reg.event_callback_args.client_data = link; | ||
173 | |||
174 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
175 | if (ret != CS_SUCCESS) { | ||
176 | cs_error(link->handle, RegisterClient, ret); | ||
177 | snd_card_free(card); | ||
178 | return NULL; | ||
179 | } | ||
180 | |||
181 | /* Chain drivers */ | ||
182 | link->next = hw->dev_list; | ||
183 | hw->dev_list = link; | ||
184 | |||
185 | /* snd_card_set_pm_callback(card, snd_vxpocket_suspend, snd_vxpocket_resume, chip); */ | ||
186 | |||
187 | return link; | ||
188 | } | ||
189 | |||
190 | |||
191 | /** | ||
192 | * snd_vxpocket_assign_resources - initialize the hardware and card instance. | ||
193 | * @port: i/o port for the card | ||
194 | * @irq: irq number for the card | ||
195 | * | ||
196 | * this function assigns the specified port and irq, boot the card, | ||
197 | * create pcm and control instances, and initialize the rest hardware. | ||
198 | * | ||
199 | * returns 0 if successful, or a negative error code. | ||
200 | */ | ||
201 | static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq) | ||
202 | { | ||
203 | int err; | ||
204 | snd_card_t *card = chip->card; | ||
205 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
206 | |||
207 | snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); | ||
208 | vxp->port = port; | ||
209 | |||
210 | sprintf(card->shortname, "Digigram %s", card->driver); | ||
211 | sprintf(card->longname, "%s at 0x%x, irq %i", | ||
212 | card->shortname, port, irq); | ||
213 | |||
214 | chip->irq = irq; | ||
215 | |||
216 | if ((err = snd_vx_setup_firmware(chip)) < 0) | ||
217 | return err; | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | |||
223 | /* | ||
224 | * snd_vxpocket_detach - detach callback for cs | ||
225 | * @hw: the hardware information | ||
226 | */ | ||
227 | void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link) | ||
228 | { | ||
229 | vx_core_t *chip; | ||
230 | |||
231 | if (! link) | ||
232 | return; | ||
233 | |||
234 | chip = link->priv; | ||
235 | |||
236 | snd_printdd(KERN_DEBUG "vxpocket_detach called\n"); | ||
237 | /* Remove the interface data from the linked list */ | ||
238 | if (hw) { | ||
239 | dev_link_t **linkp; | ||
240 | /* Locate device structure */ | ||
241 | for (linkp = &hw->dev_list; *linkp; linkp = &(*linkp)->next) | ||
242 | if (*linkp == link) { | ||
243 | *linkp = link->next; | ||
244 | break; | ||
245 | } | ||
246 | } | ||
247 | chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ | ||
248 | snd_card_disconnect(chip->card); | ||
249 | snd_card_free_in_thread(chip->card); | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * configuration callback | ||
254 | */ | ||
255 | |||
256 | #define CS_CHECK(fn, ret) \ | ||
257 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
258 | |||
259 | static void vxpocket_config(dev_link_t *link) | ||
260 | { | ||
261 | client_handle_t handle = link->handle; | ||
262 | vx_core_t *chip = link->priv; | ||
263 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
264 | tuple_t tuple; | ||
265 | cisparse_t *parse = NULL; | ||
266 | u_short buf[32]; | ||
267 | int last_fn, last_ret; | ||
268 | |||
269 | snd_printdd(KERN_DEBUG "vxpocket_config called\n"); | ||
270 | parse = kmalloc(sizeof(*parse), GFP_KERNEL); | ||
271 | if (! parse) { | ||
272 | snd_printk(KERN_ERR "vx: cannot allocate\n"); | ||
273 | return; | ||
274 | } | ||
275 | tuple.Attributes = 0; | ||
276 | tuple.TupleData = (cisdata_t *)buf; | ||
277 | tuple.TupleDataMax = sizeof(buf); | ||
278 | tuple.TupleOffset = 0; | ||
279 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
280 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
281 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
282 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); | ||
283 | link->conf.ConfigBase = parse->config.base; | ||
284 | link->conf.Present = parse->config.rmask[0]; | ||
285 | |||
286 | /* Configure card */ | ||
287 | link->state |= DEV_CONFIG; | ||
288 | |||
289 | CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io)); | ||
290 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | ||
291 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | ||
292 | |||
293 | if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0) | ||
294 | goto failed; | ||
295 | |||
296 | link->dev = &vxp->node; | ||
297 | link->state &= ~DEV_CONFIG_PENDING; | ||
298 | kfree(parse); | ||
299 | return; | ||
300 | |||
301 | cs_failed: | ||
302 | cs_error(link->handle, last_fn, last_ret); | ||
303 | failed: | ||
304 | pcmcia_release_configuration(link->handle); | ||
305 | pcmcia_release_io(link->handle, &link->io); | ||
306 | pcmcia_release_irq(link->handle, &link->irq); | ||
307 | link->state &= ~DEV_CONFIG; | ||
308 | kfree(parse); | ||
309 | } | ||
310 | |||
311 | |||
312 | /* | ||
313 | * event callback | ||
314 | */ | ||
315 | int vxpocket_event(event_t event, int priority, event_callback_args_t *args) | ||
316 | { | ||
317 | dev_link_t *link = args->client_data; | ||
318 | vx_core_t *chip = link->priv; | ||
319 | |||
320 | switch (event) { | ||
321 | case CS_EVENT_CARD_REMOVAL: | ||
322 | snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n"); | ||
323 | link->state &= ~DEV_PRESENT; | ||
324 | if (link->state & DEV_CONFIG) { | ||
325 | chip->chip_status |= VX_STAT_IS_STALE; | ||
326 | } | ||
327 | break; | ||
328 | case CS_EVENT_CARD_INSERTION: | ||
329 | snd_printdd(KERN_DEBUG "CARD_INSERTION..\n"); | ||
330 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
331 | vxpocket_config(link); | ||
332 | break; | ||
333 | #ifdef CONFIG_PM | ||
334 | case CS_EVENT_PM_SUSPEND: | ||
335 | snd_printdd(KERN_DEBUG "SUSPEND\n"); | ||
336 | link->state |= DEV_SUSPEND; | ||
337 | if (chip && chip->card->pm_suspend) { | ||
338 | snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); | ||
339 | chip->card->pm_suspend(chip->card, PMSG_SUSPEND); | ||
340 | } | ||
341 | /* Fall through... */ | ||
342 | case CS_EVENT_RESET_PHYSICAL: | ||
343 | snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n"); | ||
344 | if (link->state & DEV_CONFIG) | ||
345 | pcmcia_release_configuration(link->handle); | ||
346 | break; | ||
347 | case CS_EVENT_PM_RESUME: | ||
348 | snd_printdd(KERN_DEBUG "RESUME\n"); | ||
349 | link->state &= ~DEV_SUSPEND; | ||
350 | /* Fall through... */ | ||
351 | case CS_EVENT_CARD_RESET: | ||
352 | snd_printdd(KERN_DEBUG "CARD_RESET\n"); | ||
353 | if (DEV_OK(link)) { | ||
354 | //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
355 | snd_printdd(KERN_DEBUG "requestconfig...\n"); | ||
356 | pcmcia_request_configuration(link->handle, &link->conf); | ||
357 | if (chip && chip->card->pm_resume) { | ||
358 | snd_printdd(KERN_DEBUG "calling snd_vx_resume\n"); | ||
359 | chip->card->pm_resume(chip->card); | ||
360 | } | ||
361 | } | ||
362 | snd_printdd(KERN_DEBUG "resume done!\n"); | ||
363 | break; | ||
364 | #endif | ||
365 | } | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * exported stuffs | ||
371 | */ | ||
372 | EXPORT_SYMBOL(snd_vxpocket_ops); | ||
373 | EXPORT_SYMBOL(snd_vxpocket_attach); | ||
374 | EXPORT_SYMBOL(vxpocket_event); | ||
375 | EXPORT_SYMBOL(snd_vxpocket_detach); | ||
diff --git a/sound/pcmcia/vx/vxp440.c b/sound/pcmcia/vx/vxp440.c deleted file mode 100644 index 59190a833001..000000000000 --- a/sound/pcmcia/vx/vxp440.c +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | #define COMPILE_VXP440 | ||
2 | |||
3 | /* | ||
4 | add the following as /etc/pcmcia/vxp440.conf: | ||
5 | |||
6 | device "snd-vxp440" | ||
7 | class "audio" module "snd-vxp440" | ||
8 | |||
9 | card "Digigram VX-POCKET440" | ||
10 | manfid 0x01f1, 0x0100 | ||
11 | bind "snd-vxp440" | ||
12 | */ | ||
13 | |||
14 | #include "vxpocket.c" | ||
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 62d6fa128148..3a82161d3b24 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
@@ -24,21 +24,17 @@ | |||
24 | #include <linux/moduleparam.h> | 24 | #include <linux/moduleparam.h> |
25 | #include <sound/core.h> | 25 | #include <sound/core.h> |
26 | #include "vxpocket.h" | 26 | #include "vxpocket.h" |
27 | #include <pcmcia/ciscode.h> | ||
28 | #include <pcmcia/cisreg.h> | ||
27 | #include <sound/initval.h> | 29 | #include <sound/initval.h> |
28 | 30 | ||
29 | /* | 31 | /* |
30 | */ | 32 | */ |
31 | 33 | ||
32 | #ifdef COMPILE_VXP440 | ||
33 | #define CARD_NAME "VXPocket440" | ||
34 | #else | ||
35 | #define CARD_NAME "VXPocket" | ||
36 | #endif | ||
37 | |||
38 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); | 34 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); |
39 | MODULE_DESCRIPTION("Digigram " CARD_NAME); | 35 | MODULE_DESCRIPTION("Digigram VXPocket"); |
40 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
41 | MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}"); | 37 | MODULE_SUPPORTED_DEVICE("{{Digigram,VXPocket},{Digigram,VXPocket440}}"); |
42 | 38 | ||
43 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 39 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
44 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 40 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
@@ -46,82 +42,405 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ | |||
46 | static int ibl[SNDRV_CARDS]; | 42 | static int ibl[SNDRV_CARDS]; |
47 | 43 | ||
48 | module_param_array(index, int, NULL, 0444); | 44 | module_param_array(index, int, NULL, 0444); |
49 | MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); | 45 | MODULE_PARM_DESC(index, "Index value for VXPocket soundcard."); |
50 | module_param_array(id, charp, NULL, 0444); | 46 | module_param_array(id, charp, NULL, 0444); |
51 | MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); | 47 | MODULE_PARM_DESC(id, "ID string for VXPocket soundcard."); |
52 | module_param_array(enable, bool, NULL, 0444); | 48 | module_param_array(enable, bool, NULL, 0444); |
53 | MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); | 49 | MODULE_PARM_DESC(enable, "Enable VXPocket soundcard."); |
54 | module_param_array(ibl, int, NULL, 0444); | 50 | module_param_array(ibl, int, NULL, 0444); |
55 | MODULE_PARM_DESC(ibl, "Capture IBL size for " CARD_NAME " soundcard."); | 51 | MODULE_PARM_DESC(ibl, "Capture IBL size for VXPocket soundcard."); |
56 | 52 | ||
57 | 53 | ||
58 | /* | 54 | /* |
59 | */ | 55 | */ |
60 | 56 | ||
61 | #ifdef COMPILE_VXP440 | 57 | static unsigned int card_alloc; |
58 | static dev_link_t *dev_list; /* Linked list of devices */ | ||
59 | static dev_info_t dev_info = "snd-vxpocket"; | ||
62 | 60 | ||
63 | /* 1 DSP, 1 sync UER, 1 sync World Clock (NIY) */ | ||
64 | /* SMPTE (NIY) */ | ||
65 | /* 2 stereo analog input (line/micro) */ | ||
66 | /* 2 stereo analog output */ | ||
67 | /* Only output levels can be modified */ | ||
68 | /* UER, but only for the first two inputs and outputs. */ | ||
69 | 61 | ||
70 | #define NUM_CODECS 2 | 62 | static int vxpocket_event(event_t event, int priority, event_callback_args_t *args); |
71 | #define CARD_TYPE VX_TYPE_VXP440 | ||
72 | #define DEV_INFO "snd-vxp440" | ||
73 | 63 | ||
74 | #else | ||
75 | 64 | ||
76 | /* 1 DSP, 1 sync UER */ | 65 | /* |
77 | /* 1 programmable clock (NIY) */ | 66 | */ |
78 | /* 1 stereo analog input (line/micro) */ | 67 | static void vxpocket_release(dev_link_t *link) |
79 | /* 1 stereo analog output */ | 68 | { |
80 | /* Only output levels can be modified */ | 69 | if (link->state & DEV_CONFIG) { |
70 | /* release cs resources */ | ||
71 | pcmcia_release_configuration(link->handle); | ||
72 | pcmcia_release_io(link->handle, &link->io); | ||
73 | pcmcia_release_irq(link->handle, &link->irq); | ||
74 | link->state &= ~DEV_CONFIG; | ||
75 | } | ||
76 | if (link->handle) { | ||
77 | /* Break the link with Card Services */ | ||
78 | pcmcia_deregister_client(link->handle); | ||
79 | link->handle = NULL; | ||
80 | } | ||
81 | } | ||
81 | 82 | ||
82 | #define NUM_CODECS 1 | 83 | /* |
83 | #define CARD_TYPE VX_TYPE_VXPOCKET | 84 | * destructor, called from snd_card_free_in_thread() |
84 | #define DEV_INFO "snd-vxpocket" | 85 | */ |
86 | static int snd_vxpocket_dev_free(snd_device_t *device) | ||
87 | { | ||
88 | vx_core_t *chip = device->device_data; | ||
85 | 89 | ||
86 | #endif | 90 | snd_vx_free_firmware(chip); |
91 | kfree(chip); | ||
92 | return 0; | ||
93 | } | ||
87 | 94 | ||
88 | static dev_info_t dev_info = DEV_INFO; | ||
89 | 95 | ||
90 | static struct snd_vx_hardware vxp_hw = { | 96 | /* |
91 | .name = CARD_NAME, | 97 | * Hardware information |
92 | .type = CARD_TYPE, | 98 | */ |
99 | |||
100 | /* VX-pocket V2 | ||
101 | * | ||
102 | * 1 DSP, 1 sync UER | ||
103 | * 1 programmable clock (NIY) | ||
104 | * 1 stereo analog input (line/micro) | ||
105 | * 1 stereo analog output | ||
106 | * Only output levels can be modified | ||
107 | */ | ||
108 | |||
109 | static struct snd_vx_hardware vxpocket_hw = { | ||
110 | .name = "VXPocket", | ||
111 | .type = VX_TYPE_VXPOCKET, | ||
93 | 112 | ||
94 | /* hardware specs */ | 113 | /* hardware specs */ |
95 | .num_codecs = NUM_CODECS, | 114 | .num_codecs = 1, |
96 | .num_ins = NUM_CODECS, | 115 | .num_ins = 1, |
97 | .num_outs = NUM_CODECS, | 116 | .num_outs = 1, |
98 | .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, | 117 | .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, |
99 | }; | 118 | }; |
100 | 119 | ||
101 | static struct snd_vxp_entry hw_entry = { | 120 | /* VX-pocket 440 |
102 | .dev_info = &dev_info, | 121 | * |
122 | * 1 DSP, 1 sync UER, 1 sync World Clock (NIY) | ||
123 | * SMPTE (NIY) | ||
124 | * 2 stereo analog input (line/micro) | ||
125 | * 2 stereo analog output | ||
126 | * Only output levels can be modified | ||
127 | * UER, but only for the first two inputs and outputs. | ||
128 | */ | ||
103 | 129 | ||
104 | /* module parameters */ | 130 | static struct snd_vx_hardware vxp440_hw = { |
105 | .index_table = index, | 131 | .name = "VXPocket440", |
106 | .id_table = id, | 132 | .type = VX_TYPE_VXP440, |
107 | .enable_table = enable, | 133 | |
108 | .ibl = ibl, | 134 | /* hardware specs */ |
135 | .num_codecs = 2, | ||
136 | .num_ins = 2, | ||
137 | .num_outs = 2, | ||
138 | .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, | ||
139 | }; | ||
140 | |||
141 | |||
142 | /* | ||
143 | * create vxpocket instance | ||
144 | */ | ||
145 | static struct snd_vxpocket *snd_vxpocket_new(snd_card_t *card, int ibl) | ||
146 | { | ||
147 | client_reg_t client_reg; /* Register with cardmgr */ | ||
148 | dev_link_t *link; /* Info for cardmgr */ | ||
149 | vx_core_t *chip; | ||
150 | struct snd_vxpocket *vxp; | ||
151 | int ret; | ||
152 | static snd_device_ops_t ops = { | ||
153 | .dev_free = snd_vxpocket_dev_free, | ||
154 | }; | ||
155 | |||
156 | chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops, | ||
157 | sizeof(struct snd_vxpocket) - sizeof(vx_core_t)); | ||
158 | if (! chip) | ||
159 | return NULL; | ||
160 | |||
161 | if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) { | ||
162 | kfree(chip); | ||
163 | return NULL; | ||
164 | } | ||
165 | chip->ibl.size = ibl; | ||
166 | |||
167 | vxp = (struct snd_vxpocket *)chip; | ||
168 | |||
169 | link = &vxp->link; | ||
170 | link->priv = chip; | ||
171 | |||
172 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
173 | link->io.NumPorts1 = 16; | ||
174 | |||
175 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
176 | |||
177 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
178 | link->irq.Handler = &snd_vx_irq_handler; | ||
179 | link->irq.Instance = chip; | ||
180 | |||
181 | link->conf.Attributes = CONF_ENABLE_IRQ; | ||
182 | link->conf.Vcc = 50; | ||
183 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
184 | link->conf.ConfigIndex = 1; | ||
185 | link->conf.Present = PRESENT_OPTION; | ||
186 | |||
187 | /* Register with Card Services */ | ||
188 | memset(&client_reg, 0, sizeof(client_reg)); | ||
189 | client_reg.dev_info = &dev_info; | ||
190 | client_reg.EventMask = | ||
191 | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | ||
192 | #ifdef CONFIG_PM | ||
193 | | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | ||
194 | | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME | ||
195 | #endif | ||
196 | ; | ||
197 | client_reg.event_handler = &vxpocket_event; | ||
198 | client_reg.Version = 0x0210; | ||
199 | client_reg.event_callback_args.client_data = link; | ||
200 | |||
201 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
202 | if (ret != CS_SUCCESS) { | ||
203 | cs_error(link->handle, RegisterClient, ret); | ||
204 | return NULL; | ||
205 | } | ||
206 | |||
207 | return vxp; | ||
208 | } | ||
209 | |||
210 | |||
211 | /** | ||
212 | * snd_vxpocket_assign_resources - initialize the hardware and card instance. | ||
213 | * @port: i/o port for the card | ||
214 | * @irq: irq number for the card | ||
215 | * | ||
216 | * this function assigns the specified port and irq, boot the card, | ||
217 | * create pcm and control instances, and initialize the rest hardware. | ||
218 | * | ||
219 | * returns 0 if successful, or a negative error code. | ||
220 | */ | ||
221 | static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq) | ||
222 | { | ||
223 | int err; | ||
224 | snd_card_t *card = chip->card; | ||
225 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
226 | |||
227 | snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); | ||
228 | vxp->port = port; | ||
229 | |||
230 | sprintf(card->shortname, "Digigram %s", card->driver); | ||
231 | sprintf(card->longname, "%s at 0x%x, irq %i", | ||
232 | card->shortname, port, irq); | ||
233 | |||
234 | chip->irq = irq; | ||
235 | |||
236 | if ((err = snd_vx_setup_firmware(chip)) < 0) | ||
237 | return err; | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | |||
243 | /* | ||
244 | * configuration callback | ||
245 | */ | ||
246 | |||
247 | #define CS_CHECK(fn, ret) \ | ||
248 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
249 | |||
250 | static void vxpocket_config(dev_link_t *link) | ||
251 | { | ||
252 | client_handle_t handle = link->handle; | ||
253 | vx_core_t *chip = link->priv; | ||
254 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
255 | tuple_t tuple; | ||
256 | cisparse_t *parse; | ||
257 | u_short buf[32]; | ||
258 | int last_fn, last_ret; | ||
259 | |||
260 | snd_printdd(KERN_DEBUG "vxpocket_config called\n"); | ||
261 | parse = kmalloc(sizeof(*parse), GFP_KERNEL); | ||
262 | if (! parse) { | ||
263 | snd_printk(KERN_ERR "vx: cannot allocate\n"); | ||
264 | return; | ||
265 | } | ||
266 | tuple.Attributes = 0; | ||
267 | tuple.TupleData = (cisdata_t *)buf; | ||
268 | tuple.TupleDataMax = sizeof(buf); | ||
269 | tuple.TupleOffset = 0; | ||
270 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
271 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
272 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
273 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); | ||
274 | link->conf.ConfigBase = parse->config.base; | ||
275 | link->conf.Present = parse->config.rmask[0]; | ||
276 | |||
277 | /* redefine hardware record according to the VERSION1 string */ | ||
278 | tuple.DesiredTuple = CISTPL_VERS_1; | ||
279 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
280 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
281 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, parse)); | ||
282 | if (! strcmp(parse->version_1.str + parse->version_1.ofs[1], "VX-POCKET")) { | ||
283 | snd_printdd("VX-pocket is detected\n"); | ||
284 | } else { | ||
285 | snd_printdd("VX-pocket 440 is detected\n"); | ||
286 | /* overwrite the hardware information */ | ||
287 | chip->hw = &vxp440_hw; | ||
288 | chip->type = vxp440_hw.type; | ||
289 | strcpy(chip->card->driver, vxp440_hw.name); | ||
290 | } | ||
291 | |||
292 | /* Configure card */ | ||
293 | link->state |= DEV_CONFIG; | ||
294 | |||
295 | CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io)); | ||
296 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | ||
297 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | ||
298 | |||
299 | chip->dev = &handle_to_dev(link->handle); | ||
300 | |||
301 | if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0) | ||
302 | goto failed; | ||
303 | |||
304 | link->dev = &vxp->node; | ||
305 | link->state &= ~DEV_CONFIG_PENDING; | ||
306 | kfree(parse); | ||
307 | return; | ||
308 | |||
309 | cs_failed: | ||
310 | cs_error(link->handle, last_fn, last_ret); | ||
311 | failed: | ||
312 | pcmcia_release_configuration(link->handle); | ||
313 | pcmcia_release_io(link->handle, &link->io); | ||
314 | pcmcia_release_irq(link->handle, &link->irq); | ||
315 | link->state &= ~DEV_CONFIG; | ||
316 | kfree(parse); | ||
317 | } | ||
318 | |||
319 | |||
320 | /* | ||
321 | * event callback | ||
322 | */ | ||
323 | static int vxpocket_event(event_t event, int priority, event_callback_args_t *args) | ||
324 | { | ||
325 | dev_link_t *link = args->client_data; | ||
326 | vx_core_t *chip = link->priv; | ||
327 | |||
328 | switch (event) { | ||
329 | case CS_EVENT_CARD_REMOVAL: | ||
330 | snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n"); | ||
331 | link->state &= ~DEV_PRESENT; | ||
332 | if (link->state & DEV_CONFIG) | ||
333 | chip->chip_status |= VX_STAT_IS_STALE; | ||
334 | break; | ||
335 | case CS_EVENT_CARD_INSERTION: | ||
336 | snd_printdd(KERN_DEBUG "CARD_INSERTION..\n"); | ||
337 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
338 | vxpocket_config(link); | ||
339 | break; | ||
340 | #ifdef CONFIG_PM | ||
341 | case CS_EVENT_PM_SUSPEND: | ||
342 | snd_printdd(KERN_DEBUG "SUSPEND\n"); | ||
343 | link->state |= DEV_SUSPEND; | ||
344 | if (chip && chip->card->pm_suspend) { | ||
345 | snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); | ||
346 | chip->card->pm_suspend(chip->card, PMSG_SUSPEND); | ||
347 | } | ||
348 | /* Fall through... */ | ||
349 | case CS_EVENT_RESET_PHYSICAL: | ||
350 | snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n"); | ||
351 | if (link->state & DEV_CONFIG) | ||
352 | pcmcia_release_configuration(link->handle); | ||
353 | break; | ||
354 | case CS_EVENT_PM_RESUME: | ||
355 | snd_printdd(KERN_DEBUG "RESUME\n"); | ||
356 | link->state &= ~DEV_SUSPEND; | ||
357 | /* Fall through... */ | ||
358 | case CS_EVENT_CARD_RESET: | ||
359 | snd_printdd(KERN_DEBUG "CARD_RESET\n"); | ||
360 | if (DEV_OK(link)) { | ||
361 | //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | ||
362 | snd_printdd(KERN_DEBUG "requestconfig...\n"); | ||
363 | pcmcia_request_configuration(link->handle, &link->conf); | ||
364 | if (chip && chip->card->pm_resume) { | ||
365 | snd_printdd(KERN_DEBUG "calling snd_vx_resume\n"); | ||
366 | chip->card->pm_resume(chip->card); | ||
367 | } | ||
368 | } | ||
369 | snd_printdd(KERN_DEBUG "resume done!\n"); | ||
370 | break; | ||
371 | #endif | ||
372 | } | ||
373 | return 0; | ||
374 | } | ||
109 | 375 | ||
110 | /* h/w config */ | ||
111 | .hardware = &vxp_hw, | ||
112 | .ops = &snd_vxpocket_ops, | ||
113 | }; | ||
114 | 376 | ||
115 | /* | 377 | /* |
116 | */ | 378 | */ |
117 | static dev_link_t *vxp_attach(void) | 379 | static dev_link_t *vxp_attach(void) |
118 | { | 380 | { |
119 | return snd_vxpocket_attach(&hw_entry); | 381 | snd_card_t *card; |
382 | struct snd_vxpocket *vxp; | ||
383 | int i; | ||
384 | |||
385 | /* find an empty slot from the card list */ | ||
386 | for (i = 0; i < SNDRV_CARDS; i++) { | ||
387 | if (! card_alloc & (1 << i)) | ||
388 | break; | ||
389 | } | ||
390 | if (i >= SNDRV_CARDS) { | ||
391 | snd_printk(KERN_ERR "vxpocket: too many cards found\n"); | ||
392 | return NULL; | ||
393 | } | ||
394 | if (! enable[i]) | ||
395 | return NULL; /* disabled explicitly */ | ||
396 | |||
397 | /* ok, create a card instance */ | ||
398 | card = snd_card_new(index[i], id[i], THIS_MODULE, 0); | ||
399 | if (card == NULL) { | ||
400 | snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); | ||
401 | return NULL; | ||
402 | } | ||
403 | |||
404 | vxp = snd_vxpocket_new(card, ibl[i]); | ||
405 | if (! vxp) { | ||
406 | snd_card_free(card); | ||
407 | return NULL; | ||
408 | } | ||
409 | |||
410 | vxp->index = index[i]; | ||
411 | card_alloc |= 1 << i; | ||
412 | |||
413 | /* Chain drivers */ | ||
414 | vxp->link.next = dev_list; | ||
415 | dev_list = &vxp->link; | ||
416 | |||
417 | return &vxp->link; | ||
120 | } | 418 | } |
121 | 419 | ||
122 | static void vxp_detach(dev_link_t *link) | 420 | static void vxp_detach(dev_link_t *link) |
123 | { | 421 | { |
124 | snd_vxpocket_detach(&hw_entry, link); | 422 | struct snd_vxpocket *vxp; |
423 | vx_core_t *chip; | ||
424 | dev_link_t **linkp; | ||
425 | |||
426 | if (! link) | ||
427 | return; | ||
428 | |||
429 | vxp = link->priv; | ||
430 | chip = (vx_core_t *)vxp; | ||
431 | card_alloc &= ~(1 << vxp->index); | ||
432 | |||
433 | /* Remove the interface data from the linked list */ | ||
434 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
435 | if (*linkp == link) { | ||
436 | *linkp = link->next; | ||
437 | break; | ||
438 | } | ||
439 | |||
440 | chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ | ||
441 | snd_card_disconnect(chip->card); | ||
442 | vxpocket_release(link); | ||
443 | snd_card_free_in_thread(chip->card); | ||
125 | } | 444 | } |
126 | 445 | ||
127 | /* | 446 | /* |
@@ -137,7 +456,7 @@ MODULE_DEVICE_TABLE(pcmcia, vxp_ids); | |||
137 | static struct pcmcia_driver vxp_cs_driver = { | 456 | static struct pcmcia_driver vxp_cs_driver = { |
138 | .owner = THIS_MODULE, | 457 | .owner = THIS_MODULE, |
139 | .drv = { | 458 | .drv = { |
140 | .name = DEV_INFO, | 459 | .name = "snd-vxpocket", |
141 | }, | 460 | }, |
142 | .attach = vxp_attach, | 461 | .attach = vxp_attach, |
143 | .detach = vxp_detach, | 462 | .detach = vxp_detach, |
@@ -152,7 +471,7 @@ static int __init init_vxpocket(void) | |||
152 | static void __exit exit_vxpocket(void) | 471 | static void __exit exit_vxpocket(void) |
153 | { | 472 | { |
154 | pcmcia_unregister_driver(&vxp_cs_driver); | 473 | pcmcia_unregister_driver(&vxp_cs_driver); |
155 | BUG_ON(hw_entry.dev_list != NULL); | 474 | BUG_ON(dev_list != NULL); |
156 | } | 475 | } |
157 | 476 | ||
158 | module_init(init_vxpocket); | 477 | module_init(init_vxpocket); |
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h index 4462c04a4e8f..70754aa3dd11 100644 --- a/sound/pcmcia/vx/vxpocket.h +++ b/sound/pcmcia/vx/vxpocket.h | |||
@@ -28,24 +28,6 @@ | |||
28 | #include <pcmcia/cistpl.h> | 28 | #include <pcmcia/cistpl.h> |
29 | #include <pcmcia/ds.h> | 29 | #include <pcmcia/ds.h> |
30 | 30 | ||
31 | struct snd_vxp_entry { | ||
32 | dev_info_t *dev_info; | ||
33 | |||
34 | /* module parameters */ | ||
35 | int *index_table; | ||
36 | char **id_table; | ||
37 | int *enable_table; | ||
38 | int *ibl; | ||
39 | |||
40 | /* h/w config */ | ||
41 | struct snd_vx_hardware *hardware; | ||
42 | struct snd_vx_ops *ops; | ||
43 | |||
44 | /* slots */ | ||
45 | vx_core_t *card_list[SNDRV_CARDS]; | ||
46 | dev_link_t *dev_list; /* Linked list of devices */ | ||
47 | }; | ||
48 | |||
49 | struct snd_vxpocket { | 31 | struct snd_vxpocket { |
50 | 32 | ||
51 | vx_core_t core; | 33 | vx_core_t core; |
@@ -57,8 +39,7 @@ struct snd_vxpocket { | |||
57 | unsigned int regCDSP; /* current CDSP register */ | 39 | unsigned int regCDSP; /* current CDSP register */ |
58 | unsigned int regDIALOG; /* current DIALOG register */ | 40 | unsigned int regDIALOG; /* current DIALOG register */ |
59 | 41 | ||
60 | int index; | 42 | int index; /* card index */ |
61 | struct snd_vxp_entry *hw_entry; | ||
62 | 43 | ||
63 | /* pcmcia stuff */ | 44 | /* pcmcia stuff */ |
64 | dev_link_t link; | 45 | dev_link_t link; |
@@ -70,12 +51,6 @@ extern struct snd_vx_ops snd_vxpocket_ops; | |||
70 | void vx_set_mic_boost(vx_core_t *chip, int boost); | 51 | void vx_set_mic_boost(vx_core_t *chip, int boost); |
71 | void vx_set_mic_level(vx_core_t *chip, int level); | 52 | void vx_set_mic_level(vx_core_t *chip, int level); |
72 | 53 | ||
73 | /* | ||
74 | * pcmcia stuff | ||
75 | */ | ||
76 | dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw); | ||
77 | void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link); | ||
78 | |||
79 | int vxp_add_mic_controls(vx_core_t *chip); | 54 | int vxp_add_mic_controls(vx_core_t *chip); |
80 | 55 | ||
81 | /* Constants used to access the CDSP register (0x08). */ | 56 | /* Constants used to access the CDSP register (0x08). */ |
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 061e52d3d771..758ca1bcbcf2 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c | |||
@@ -103,7 +103,7 @@ static void screamer_recalibrate(pmac_t *chip) | |||
103 | snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); | 103 | snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); |
104 | if (chip->manufacturer == 0x1) | 104 | if (chip->manufacturer == 0x1) |
105 | /* delay for broken crystal part */ | 105 | /* delay for broken crystal part */ |
106 | big_mdelay(750); | 106 | msleep(750); |
107 | snd_pmac_awacs_write_noreg(chip, 1, | 107 | snd_pmac_awacs_write_noreg(chip, 1, |
108 | chip->awacs_reg[1] | MASK_RECALIBRATE | MASK_CMUTE | MASK_AMUTE); | 108 | chip->awacs_reg[1] | MASK_RECALIBRATE | MASK_CMUTE | MASK_AMUTE); |
109 | snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); | 109 | snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]); |
@@ -653,10 +653,10 @@ static void snd_pmac_awacs_resume(pmac_t *chip) | |||
653 | { | 653 | { |
654 | if (machine_is_compatible("PowerBook3,1") | 654 | if (machine_is_compatible("PowerBook3,1") |
655 | || machine_is_compatible("PowerBook3,2")) { | 655 | || machine_is_compatible("PowerBook3,2")) { |
656 | big_mdelay(100); | 656 | msleep(100); |
657 | snd_pmac_awacs_write_reg(chip, 1, | 657 | snd_pmac_awacs_write_reg(chip, 1, |
658 | chip->awacs_reg[1] & ~MASK_PAROUT); | 658 | chip->awacs_reg[1] & ~MASK_PAROUT); |
659 | big_mdelay(300); | 659 | msleep(300); |
660 | } | 660 | } |
661 | 661 | ||
662 | awacs_restore_all_regs(chip); | 662 | awacs_restore_all_regs(chip); |
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index 582db5220119..ae3bb6c6edff 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h | |||
@@ -212,9 +212,4 @@ int snd_pmac_boolean_mono_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *ui | |||
212 | 212 | ||
213 | int snd_pmac_add_automute(pmac_t *chip); | 213 | int snd_pmac_add_automute(pmac_t *chip); |
214 | 214 | ||
215 | #define big_mdelay(msec) do {\ | ||
216 | set_current_state(TASK_UNINTERRUPTIBLE);\ | ||
217 | schedule_timeout(((msec) * HZ + 999) / 1000);\ | ||
218 | } while (0) | ||
219 | |||
220 | #endif /* __PMAC_H */ | 215 | #endif /* __PMAC_H */ |
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 36c5d5d45bb1..b94437c024b1 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c | |||
@@ -945,7 +945,7 @@ static void device_change_handler(void *self) | |||
945 | check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify, | 945 | check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify, |
946 | chip->lineout_sw_ctl); | 946 | chip->lineout_sw_ctl); |
947 | if (mix->anded_reset) | 947 | if (mix->anded_reset) |
948 | big_mdelay(10); | 948 | msleep(10); |
949 | check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, | 949 | check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, |
950 | chip->speaker_sw_ctl); | 950 | chip->speaker_sw_ctl); |
951 | mix->drc_enable = 0; | 951 | mix->drc_enable = 0; |
@@ -954,7 +954,7 @@ static void device_change_handler(void *self) | |||
954 | check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, | 954 | check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, |
955 | chip->speaker_sw_ctl); | 955 | chip->speaker_sw_ctl); |
956 | if (mix->anded_reset) | 956 | if (mix->anded_reset) |
957 | big_mdelay(10); | 957 | msleep(10); |
958 | check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, | 958 | check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, |
959 | chip->master_sw_ctl); | 959 | chip->master_sw_ctl); |
960 | if (mix->line_mute.addr != 0) | 960 | if (mix->line_mute.addr != 0) |
@@ -1109,22 +1109,22 @@ static void tumbler_reset_audio(pmac_t *chip) | |||
1109 | DBG("(I) codec anded reset !\n"); | 1109 | DBG("(I) codec anded reset !\n"); |
1110 | write_audio_gpio(&mix->hp_mute, 0); | 1110 | write_audio_gpio(&mix->hp_mute, 0); |
1111 | write_audio_gpio(&mix->amp_mute, 0); | 1111 | write_audio_gpio(&mix->amp_mute, 0); |
1112 | big_mdelay(200); | 1112 | msleep(200); |
1113 | write_audio_gpio(&mix->hp_mute, 1); | 1113 | write_audio_gpio(&mix->hp_mute, 1); |
1114 | write_audio_gpio(&mix->amp_mute, 1); | 1114 | write_audio_gpio(&mix->amp_mute, 1); |
1115 | big_mdelay(100); | 1115 | msleep(100); |
1116 | write_audio_gpio(&mix->hp_mute, 0); | 1116 | write_audio_gpio(&mix->hp_mute, 0); |
1117 | write_audio_gpio(&mix->amp_mute, 0); | 1117 | write_audio_gpio(&mix->amp_mute, 0); |
1118 | big_mdelay(100); | 1118 | msleep(100); |
1119 | } else { | 1119 | } else { |
1120 | DBG("(I) codec normal reset !\n"); | 1120 | DBG("(I) codec normal reset !\n"); |
1121 | 1121 | ||
1122 | write_audio_gpio(&mix->audio_reset, 0); | 1122 | write_audio_gpio(&mix->audio_reset, 0); |
1123 | big_mdelay(200); | 1123 | msleep(200); |
1124 | write_audio_gpio(&mix->audio_reset, 1); | 1124 | write_audio_gpio(&mix->audio_reset, 1); |
1125 | big_mdelay(100); | 1125 | msleep(100); |
1126 | write_audio_gpio(&mix->audio_reset, 0); | 1126 | write_audio_gpio(&mix->audio_reset, 0); |
1127 | big_mdelay(100); | 1127 | msleep(100); |
1128 | } | 1128 | } |
1129 | } | 1129 | } |
1130 | 1130 | ||
diff --git a/sound/sparc/Kconfig b/sound/sparc/Kconfig index 2358df1c45a9..25a8a558ef92 100644 --- a/sound/sparc/Kconfig +++ b/sound/sparc/Kconfig | |||
@@ -7,12 +7,30 @@ config SND_SUN_AMD7930 | |||
7 | tristate "Sun AMD7930" | 7 | tristate "Sun AMD7930" |
8 | depends on SBUS && SND | 8 | depends on SBUS && SND |
9 | select SND_PCM | 9 | select SND_PCM |
10 | help | ||
11 | Say Y here to include support for AMD7930 sound device on Sun. | ||
12 | |||
13 | To compile this driver as a module, choose M here: the module | ||
14 | will be called snd-sun-amd7930. | ||
10 | 15 | ||
11 | # dep_tristate 'Sun DBRI' CONFIG_SND_SUN_DBRI $CONFIG_SND | ||
12 | config SND_SUN_CS4231 | 16 | config SND_SUN_CS4231 |
13 | tristate "Sun CS4231" | 17 | tristate "Sun CS4231" |
14 | depends on SND | 18 | depends on SND |
15 | select SND_PCM | 19 | select SND_PCM |
20 | help | ||
21 | Say Y here to include support for CS4231 sound device on Sun. | ||
16 | 22 | ||
17 | endmenu | 23 | To compile this driver as a module, choose M here: the module |
24 | will be called snd-sun-cs4231. | ||
25 | |||
26 | config SND_SUN_DBRI | ||
27 | tristate "Sun DBRI" | ||
28 | depends on SND && SBUS | ||
29 | select SND_PCM | ||
30 | help | ||
31 | Say Y here to include support for DBRI sound device on Sun. | ||
32 | |||
33 | To compile this driver as a module, choose M here: the module | ||
34 | will be called snd-sun-dbri. | ||
18 | 35 | ||
36 | endmenu | ||
diff --git a/sound/sparc/Makefile b/sound/sparc/Makefile index 6809cc92d276..3cd89c67c2f2 100644 --- a/sound/sparc/Makefile +++ b/sound/sparc/Makefile | |||
@@ -4,9 +4,9 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | snd-sun-amd7930-objs := amd7930.o | 6 | snd-sun-amd7930-objs := amd7930.o |
7 | #snd-sun-dbri-objs := dbri.o | ||
8 | snd-sun-cs4231-objs := cs4231.o | 7 | snd-sun-cs4231-objs := cs4231.o |
8 | snd-sun-dbri-objs := dbri.o | ||
9 | 9 | ||
10 | obj-$(CONFIG_SND_SUN_AMD7930) += snd-sun-amd7930.o | 10 | obj-$(CONFIG_SND_SUN_AMD7930) += snd-sun-amd7930.o |
11 | #obj-$(CONFIG_SND_SUN_DBRI) += snd-sun-dbri.o | ||
12 | obj-$(CONFIG_SND_SUN_CS4231) += snd-sun-cs4231.o | 11 | obj-$(CONFIG_SND_SUN_CS4231) += snd-sun-cs4231.o |
12 | obj-$(CONFIG_SND_SUN_DBRI) += snd-sun-dbri.o | ||
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c new file mode 100644 index 000000000000..941c7b1e7ebb --- /dev/null +++ b/sound/sparc/dbri.c | |||
@@ -0,0 +1,2729 @@ | |||
1 | /* | ||
2 | * Driver for DBRI sound chip found on Sparcs. | ||
3 | * Copyright (C) 2004 Martin Habets (mhabets@users.sourceforge.net) | ||
4 | * | ||
5 | * Based entirely upon drivers/sbus/audio/dbri.c which is: | ||
6 | * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) | ||
7 | * Copyright (C) 1998, 1999 Brent Baccala (baccala@freesoft.org) | ||
8 | * | ||
9 | * This is the lowlevel driver for the DBRI & MMCODEC duo used for ISDN & AUDIO | ||
10 | * on Sun SPARCstation 10, 20, LX and Voyager models. | ||
11 | * | ||
12 | * - DBRI: AT&T T5900FX Dual Basic Rates ISDN Interface. It is a 32 channel | ||
13 | * data time multiplexer with ISDN support (aka T7259) | ||
14 | * Interfaces: SBus,ISDN NT & TE, CHI, 4 bits parallel. | ||
15 | * CHI: (spelled ki) Concentration Highway Interface (AT&T or Intel bus ?). | ||
16 | * Documentation: | ||
17 | * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Tranceiver" from | ||
18 | * Sparc Technology Business (courtesy of Sun Support) | ||
19 | * - Data sheet of the T7903, a newer but very similar ISA bus equivalent | ||
20 | * available from the Lucent (formarly AT&T microelectronics) home | ||
21 | * page. | ||
22 | * - http://www.freesoft.org/Linux/DBRI/ | ||
23 | * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec | ||
24 | * Interfaces: CHI, Audio In & Out, 2 bits parallel | ||
25 | * Documentation: from the Crystal Semiconductor home page. | ||
26 | * | ||
27 | * The DBRI is a 32 pipe machine, each pipe can transfer some bits between | ||
28 | * memory and a serial device (long pipes, nr 0-15) or between two serial | ||
29 | * devices (short pipes, nr 16-31), or simply send a fixed data to a serial | ||
30 | * device (short pipes). | ||
31 | * A timeslot defines the bit-offset and nr of bits read from a serial device. | ||
32 | * The timeslots are linked to 6 circular lists, one for each direction for | ||
33 | * each serial device (NT,TE,CHI). A timeslot is associated to 1 or 2 pipes | ||
34 | * (the second one is a monitor/tee pipe, valid only for serial input). | ||
35 | * | ||
36 | * The mmcodec is connected via the CHI bus and needs the data & some | ||
37 | * parameters (volume, balance, output selection) timemultiplexed in 8 byte | ||
38 | * chunks. It also has a control mode, which serves for audio format setting. | ||
39 | * | ||
40 | * Looking at the CS4215 data sheet it is easy to set up 2 or 4 codecs on | ||
41 | * the same CHI bus, so I thought perhaps it is possible to use the onboard | ||
42 | * & the speakerbox codec simultanously, giving 2 (not very independent :-) | ||
43 | * audio devices. But the SUN HW group decided against it, at least on my | ||
44 | * LX the speakerbox connector has at least 1 pin missing and 1 wrongly | ||
45 | * connected. | ||
46 | */ | ||
47 | |||
48 | #include <sound/driver.h> | ||
49 | #include <linux/interrupt.h> | ||
50 | #include <linux/delay.h> | ||
51 | |||
52 | #include <sound/core.h> | ||
53 | #include <sound/pcm.h> | ||
54 | #include <sound/pcm_params.h> | ||
55 | #include <sound/info.h> | ||
56 | #include <sound/control.h> | ||
57 | #include <sound/initval.h> | ||
58 | |||
59 | #include <asm/irq.h> | ||
60 | #include <asm/io.h> | ||
61 | #include <asm/sbus.h> | ||
62 | #include <asm/atomic.h> | ||
63 | |||
64 | MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets"); | ||
65 | MODULE_DESCRIPTION("Sun DBRI"); | ||
66 | MODULE_LICENSE("GPL"); | ||
67 | MODULE_SUPPORTED_DEVICE("{{Sun,DBRI}}"); | ||
68 | |||
69 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | ||
70 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | ||
71 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | ||
72 | |||
73 | module_param_array(index, int, NULL, 0444); | ||
74 | MODULE_PARM_DESC(index, "Index value for Sun DBRI soundcard."); | ||
75 | module_param_array(id, charp, NULL, 0444); | ||
76 | MODULE_PARM_DESC(id, "ID string for Sun DBRI soundcard."); | ||
77 | module_param_array(enable, bool, NULL, 0444); | ||
78 | MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard."); | ||
79 | |||
80 | #define DBRI_DEBUG | ||
81 | |||
82 | #define D_INT (1<<0) | ||
83 | #define D_GEN (1<<1) | ||
84 | #define D_CMD (1<<2) | ||
85 | #define D_MM (1<<3) | ||
86 | #define D_USR (1<<4) | ||
87 | #define D_DESC (1<<5) | ||
88 | |||
89 | static int dbri_debug = 0; | ||
90 | module_param(dbri_debug, int, 0444); | ||
91 | MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard."); | ||
92 | |||
93 | #ifdef DBRI_DEBUG | ||
94 | static char *cmds[] = { | ||
95 | "WAIT", "PAUSE", "JUMP", "IIQ", "REX", "SDP", "CDP", "DTS", | ||
96 | "SSP", "CHI", "NT", "TE", "CDEC", "TEST", "CDM", "RESRV" | ||
97 | }; | ||
98 | |||
99 | #define dprintk(a, x...) if(dbri_debug & a) printk(KERN_DEBUG x) | ||
100 | |||
101 | #define DBRI_CMD(cmd, intr, value) ((cmd << 28) | \ | ||
102 | (1 << 27) | \ | ||
103 | value) | ||
104 | #else | ||
105 | #define dprintk(a, x...) | ||
106 | |||
107 | #define DBRI_CMD(cmd, intr, value) ((cmd << 28) | \ | ||
108 | (intr << 27) | \ | ||
109 | value) | ||
110 | #endif /* DBRI_DEBUG */ | ||
111 | |||
112 | /*************************************************************************** | ||
113 | CS4215 specific definitions and structures | ||
114 | ****************************************************************************/ | ||
115 | |||
116 | struct cs4215 { | ||
117 | __u8 data[4]; /* Data mode: Time slots 5-8 */ | ||
118 | __u8 ctrl[4]; /* Ctrl mode: Time slots 1-4 */ | ||
119 | __u8 onboard; | ||
120 | __u8 offset; /* Bit offset from frame sync to time slot 1 */ | ||
121 | volatile __u32 status; | ||
122 | volatile __u32 version; | ||
123 | __u8 precision; /* In bits, either 8 or 16 */ | ||
124 | __u8 channels; /* 1 or 2 */ | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * Control mode first | ||
129 | */ | ||
130 | |||
131 | /* Time Slot 1, Status register */ | ||
132 | #define CS4215_CLB (1<<2) /* Control Latch Bit */ | ||
133 | #define CS4215_OLB (1<<3) /* 1: line: 2.0V, speaker 4V */ | ||
134 | /* 0: line: 2.8V, speaker 8V */ | ||
135 | #define CS4215_MLB (1<<4) /* 1: Microphone: 20dB gain disabled */ | ||
136 | #define CS4215_RSRVD_1 (1<<5) | ||
137 | |||
138 | /* Time Slot 2, Data Format Register */ | ||
139 | #define CS4215_DFR_LINEAR16 0 | ||
140 | #define CS4215_DFR_ULAW 1 | ||
141 | #define CS4215_DFR_ALAW 2 | ||
142 | #define CS4215_DFR_LINEAR8 3 | ||
143 | #define CS4215_DFR_STEREO (1<<2) | ||
144 | static struct { | ||
145 | unsigned short freq; | ||
146 | unsigned char xtal; | ||
147 | unsigned char csval; | ||
148 | } CS4215_FREQ[] = { | ||
149 | { 8000, (1 << 4), (0 << 3) }, | ||
150 | { 16000, (1 << 4), (1 << 3) }, | ||
151 | { 27429, (1 << 4), (2 << 3) }, /* Actually 24428.57 */ | ||
152 | { 32000, (1 << 4), (3 << 3) }, | ||
153 | /* { NA, (1 << 4), (4 << 3) }, */ | ||
154 | /* { NA, (1 << 4), (5 << 3) }, */ | ||
155 | { 48000, (1 << 4), (6 << 3) }, | ||
156 | { 9600, (1 << 4), (7 << 3) }, | ||
157 | { 5513, (2 << 4), (0 << 3) }, /* Actually 5512.5 */ | ||
158 | { 11025, (2 << 4), (1 << 3) }, | ||
159 | { 18900, (2 << 4), (2 << 3) }, | ||
160 | { 22050, (2 << 4), (3 << 3) }, | ||
161 | { 37800, (2 << 4), (4 << 3) }, | ||
162 | { 44100, (2 << 4), (5 << 3) }, | ||
163 | { 33075, (2 << 4), (6 << 3) }, | ||
164 | { 6615, (2 << 4), (7 << 3) }, | ||
165 | { 0, 0, 0} | ||
166 | }; | ||
167 | |||
168 | #define CS4215_HPF (1<<7) /* High Pass Filter, 1: Enabled */ | ||
169 | |||
170 | #define CS4215_12_MASK 0xfcbf /* Mask off reserved bits in slot 1 & 2 */ | ||
171 | |||
172 | /* Time Slot 3, Serial Port Control register */ | ||
173 | #define CS4215_XEN (1<<0) /* 0: Enable serial output */ | ||
174 | #define CS4215_XCLK (1<<1) /* 1: Master mode: Generate SCLK */ | ||
175 | #define CS4215_BSEL_64 (0<<2) /* Bitrate: 64 bits per frame */ | ||
176 | #define CS4215_BSEL_128 (1<<2) | ||
177 | #define CS4215_BSEL_256 (2<<2) | ||
178 | #define CS4215_MCK_MAST (0<<4) /* Master clock */ | ||
179 | #define CS4215_MCK_XTL1 (1<<4) /* 24.576 MHz clock source */ | ||
180 | #define CS4215_MCK_XTL2 (2<<4) /* 16.9344 MHz clock source */ | ||
181 | #define CS4215_MCK_CLK1 (3<<4) /* Clockin, 256 x Fs */ | ||
182 | #define CS4215_MCK_CLK2 (4<<4) /* Clockin, see DFR */ | ||
183 | |||
184 | /* Time Slot 4, Test Register */ | ||
185 | #define CS4215_DAD (1<<0) /* 0:Digital-Dig loop, 1:Dig-Analog-Dig loop */ | ||
186 | #define CS4215_ENL (1<<1) /* Enable Loopback Testing */ | ||
187 | |||
188 | /* Time Slot 5, Parallel Port Register */ | ||
189 | /* Read only here and the same as the in data mode */ | ||
190 | |||
191 | /* Time Slot 6, Reserved */ | ||
192 | |||
193 | /* Time Slot 7, Version Register */ | ||
194 | #define CS4215_VERSION_MASK 0xf /* Known versions 0/C, 1/D, 2/E */ | ||
195 | |||
196 | /* Time Slot 8, Reserved */ | ||
197 | |||
198 | /* | ||
199 | * Data mode | ||
200 | */ | ||
201 | /* Time Slot 1-2: Left Channel Data, 2-3: Right Channel Data */ | ||
202 | |||
203 | /* Time Slot 5, Output Setting */ | ||
204 | #define CS4215_LO(v) v /* Left Output Attenuation 0x3f: -94.5 dB */ | ||
205 | #define CS4215_LE (1<<6) /* Line Out Enable */ | ||
206 | #define CS4215_HE (1<<7) /* Headphone Enable */ | ||
207 | |||
208 | /* Time Slot 6, Output Setting */ | ||
209 | #define CS4215_RO(v) v /* Right Output Attenuation 0x3f: -94.5 dB */ | ||
210 | #define CS4215_SE (1<<6) /* Speaker Enable */ | ||
211 | #define CS4215_ADI (1<<7) /* A/D Data Invalid: Busy in calibration */ | ||
212 | |||
213 | /* Time Slot 7, Input Setting */ | ||
214 | #define CS4215_LG(v) v /* Left Gain Setting 0xf: 22.5 dB */ | ||
215 | #define CS4215_IS (1<<4) /* Input Select: 1=Microphone, 0=Line */ | ||
216 | #define CS4215_OVR (1<<5) /* 1: Overrange condition occurred */ | ||
217 | #define CS4215_PIO0 (1<<6) /* Parallel I/O 0 */ | ||
218 | #define CS4215_PIO1 (1<<7) | ||
219 | |||
220 | /* Time Slot 8, Input Setting */ | ||
221 | #define CS4215_RG(v) v /* Right Gain Setting 0xf: 22.5 dB */ | ||
222 | #define CS4215_MA(v) (v<<4) /* Monitor Path Attenuation 0xf: mute */ | ||
223 | |||
224 | /*************************************************************************** | ||
225 | DBRI specific definitions and structures | ||
226 | ****************************************************************************/ | ||
227 | |||
228 | /* DBRI main registers */ | ||
229 | #define REG0 0x00UL /* Status and Control */ | ||
230 | #define REG1 0x04UL /* Mode and Interrupt */ | ||
231 | #define REG2 0x08UL /* Parallel IO */ | ||
232 | #define REG3 0x0cUL /* Test */ | ||
233 | #define REG8 0x20UL /* Command Queue Pointer */ | ||
234 | #define REG9 0x24UL /* Interrupt Queue Pointer */ | ||
235 | |||
236 | #define DBRI_NO_CMDS 64 | ||
237 | #define DBRI_NO_INTS 1 /* Note: the value of this define was | ||
238 | * originally 2. The ringbuffer to store | ||
239 | * interrupts in dma is currently broken. | ||
240 | * This is a temporary fix until the ringbuffer | ||
241 | * is fixed. | ||
242 | */ | ||
243 | #define DBRI_INT_BLK 64 | ||
244 | #define DBRI_NO_DESCS 64 | ||
245 | #define DBRI_NO_PIPES 32 | ||
246 | |||
247 | #define DBRI_MM_ONB 1 | ||
248 | #define DBRI_MM_SB 2 | ||
249 | |||
250 | #define DBRI_REC 0 | ||
251 | #define DBRI_PLAY 1 | ||
252 | #define DBRI_NO_STREAMS 2 | ||
253 | |||
254 | /* One transmit/receive descriptor */ | ||
255 | struct dbri_mem { | ||
256 | volatile __u32 word1; | ||
257 | volatile __u32 ba; /* Transmit/Receive Buffer Address */ | ||
258 | volatile __u32 nda; /* Next Descriptor Address */ | ||
259 | volatile __u32 word4; | ||
260 | }; | ||
261 | |||
262 | /* This structure is in a DMA region where it can accessed by both | ||
263 | * the CPU and the DBRI | ||
264 | */ | ||
265 | struct dbri_dma { | ||
266 | volatile s32 cmd[DBRI_NO_CMDS]; /* Place for commands */ | ||
267 | volatile s32 intr[DBRI_NO_INTS * DBRI_INT_BLK]; /* Interrupt field */ | ||
268 | struct dbri_mem desc[DBRI_NO_DESCS]; /* Xmit/receive descriptors */ | ||
269 | }; | ||
270 | |||
271 | #define dbri_dma_off(member, elem) \ | ||
272 | ((u32)(unsigned long) \ | ||
273 | (&(((struct dbri_dma *)0)->member[elem]))) | ||
274 | |||
275 | enum in_or_out { PIPEinput, PIPEoutput }; | ||
276 | |||
277 | struct dbri_pipe { | ||
278 | u32 sdp; /* SDP command word */ | ||
279 | enum in_or_out direction; | ||
280 | int nextpipe; /* Next pipe in linked list */ | ||
281 | int prevpipe; | ||
282 | int cycle; /* Offset of timeslot (bits) */ | ||
283 | int length; /* Length of timeslot (bits) */ | ||
284 | int first_desc; /* Index of first descriptor */ | ||
285 | int desc; /* Index of active descriptor */ | ||
286 | volatile __u32 *recv_fixed_ptr; /* Ptr to receive fixed data */ | ||
287 | }; | ||
288 | |||
289 | struct dbri_desc { | ||
290 | int inuse; /* Boolean flag */ | ||
291 | int next; /* Index of next desc, or -1 */ | ||
292 | unsigned int len; | ||
293 | }; | ||
294 | |||
295 | /* Per stream (playback or record) information */ | ||
296 | typedef struct dbri_streaminfo { | ||
297 | snd_pcm_substream_t *substream; | ||
298 | u32 dvma_buffer; /* Device view of Alsa DMA buffer */ | ||
299 | int left; /* # of bytes left in DMA buffer */ | ||
300 | int size; /* Size of DMA buffer */ | ||
301 | size_t offset; /* offset in user buffer */ | ||
302 | int pipe; /* Data pipe used */ | ||
303 | int left_gain; /* mixer elements */ | ||
304 | int right_gain; | ||
305 | int balance; | ||
306 | } dbri_streaminfo_t; | ||
307 | |||
308 | /* This structure holds the information for both chips (DBRI & CS4215) */ | ||
309 | typedef struct snd_dbri { | ||
310 | snd_card_t *card; /* ALSA card */ | ||
311 | snd_pcm_t *pcm; | ||
312 | |||
313 | int regs_size, irq; /* Needed for unload */ | ||
314 | struct sbus_dev *sdev; /* SBUS device info */ | ||
315 | spinlock_t lock; | ||
316 | |||
317 | volatile struct dbri_dma *dma; /* Pointer to our DMA block */ | ||
318 | u32 dma_dvma; /* DBRI visible DMA address */ | ||
319 | |||
320 | void __iomem *regs; /* dbri HW regs */ | ||
321 | int dbri_version; /* 'e' and up is OK */ | ||
322 | int dbri_irqp; /* intr queue pointer */ | ||
323 | int wait_seen; | ||
324 | |||
325 | struct dbri_pipe pipes[DBRI_NO_PIPES]; /* DBRI's 32 data pipes */ | ||
326 | struct dbri_desc descs[DBRI_NO_DESCS]; | ||
327 | |||
328 | int chi_in_pipe; | ||
329 | int chi_out_pipe; | ||
330 | int chi_bpf; | ||
331 | |||
332 | struct cs4215 mm; /* mmcodec special info */ | ||
333 | /* per stream (playback/record) info */ | ||
334 | struct dbri_streaminfo stream_info[DBRI_NO_STREAMS]; | ||
335 | |||
336 | struct snd_dbri *next; | ||
337 | } snd_dbri_t; | ||
338 | |||
339 | /* Needed for the ALSA macros to work */ | ||
340 | #define chip_t snd_dbri_t | ||
341 | |||
342 | #define DBRI_MAX_VOLUME 63 /* Output volume */ | ||
343 | #define DBRI_MAX_GAIN 15 /* Input gain */ | ||
344 | #define DBRI_RIGHT_BALANCE 255 | ||
345 | #define DBRI_MID_BALANCE (DBRI_RIGHT_BALANCE >> 1) | ||
346 | |||
347 | /* DBRI Reg0 - Status Control Register - defines. (Page 17) */ | ||
348 | #define D_P (1<<15) /* Program command & queue pointer valid */ | ||
349 | #define D_G (1<<14) /* Allow 4-Word SBus Burst */ | ||
350 | #define D_S (1<<13) /* Allow 16-Word SBus Burst */ | ||
351 | #define D_E (1<<12) /* Allow 8-Word SBus Burst */ | ||
352 | #define D_X (1<<7) /* Sanity Timer Disable */ | ||
353 | #define D_T (1<<6) /* Permit activation of the TE interface */ | ||
354 | #define D_N (1<<5) /* Permit activation of the NT interface */ | ||
355 | #define D_C (1<<4) /* Permit activation of the CHI interface */ | ||
356 | #define D_F (1<<3) /* Force Sanity Timer Time-Out */ | ||
357 | #define D_D (1<<2) /* Disable Master Mode */ | ||
358 | #define D_H (1<<1) /* Halt for Analysis */ | ||
359 | #define D_R (1<<0) /* Soft Reset */ | ||
360 | |||
361 | /* DBRI Reg1 - Mode and Interrupt Register - defines. (Page 18) */ | ||
362 | #define D_LITTLE_END (1<<8) /* Byte Order */ | ||
363 | #define D_BIG_END (0<<8) /* Byte Order */ | ||
364 | #define D_MRR (1<<4) /* Multiple Error Ack on SBus (readonly) */ | ||
365 | #define D_MLE (1<<3) /* Multiple Late Error on SBus (readonly) */ | ||
366 | #define D_LBG (1<<2) /* Lost Bus Grant on SBus (readonly) */ | ||
367 | #define D_MBE (1<<1) /* Burst Error on SBus (readonly) */ | ||
368 | #define D_IR (1<<0) /* Interrupt Indicator (readonly) */ | ||
369 | |||
370 | /* DBRI Reg2 - Parallel IO Register - defines. (Page 18) */ | ||
371 | #define D_ENPIO3 (1<<7) /* Enable Pin 3 */ | ||
372 | #define D_ENPIO2 (1<<6) /* Enable Pin 2 */ | ||
373 | #define D_ENPIO1 (1<<5) /* Enable Pin 1 */ | ||
374 | #define D_ENPIO0 (1<<4) /* Enable Pin 0 */ | ||
375 | #define D_ENPIO (0xf0) /* Enable all the pins */ | ||
376 | #define D_PIO3 (1<<3) /* Pin 3: 1: Data mode, 0: Ctrl mode */ | ||
377 | #define D_PIO2 (1<<2) /* Pin 2: 1: Onboard PDN */ | ||
378 | #define D_PIO1 (1<<1) /* Pin 1: 0: Reset */ | ||
379 | #define D_PIO0 (1<<0) /* Pin 0: 1: Speakerbox PDN */ | ||
380 | |||
381 | /* DBRI Commands (Page 20) */ | ||
382 | #define D_WAIT 0x0 /* Stop execution */ | ||
383 | #define D_PAUSE 0x1 /* Flush long pipes */ | ||
384 | #define D_JUMP 0x2 /* New command queue */ | ||
385 | #define D_IIQ 0x3 /* Initialize Interrupt Queue */ | ||
386 | #define D_REX 0x4 /* Report command execution via interrupt */ | ||
387 | #define D_SDP 0x5 /* Setup Data Pipe */ | ||
388 | #define D_CDP 0x6 /* Continue Data Pipe (reread NULL Pointer) */ | ||
389 | #define D_DTS 0x7 /* Define Time Slot */ | ||
390 | #define D_SSP 0x8 /* Set short Data Pipe */ | ||
391 | #define D_CHI 0x9 /* Set CHI Global Mode */ | ||
392 | #define D_NT 0xa /* NT Command */ | ||
393 | #define D_TE 0xb /* TE Command */ | ||
394 | #define D_CDEC 0xc /* Codec setup */ | ||
395 | #define D_TEST 0xd /* No comment */ | ||
396 | #define D_CDM 0xe /* CHI Data mode command */ | ||
397 | |||
398 | /* Special bits for some commands */ | ||
399 | #define D_PIPE(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */ | ||
400 | |||
401 | /* Setup Data Pipe */ | ||
402 | /* IRM */ | ||
403 | #define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value rcvd */ | ||
404 | #define D_SDP_CHANGE (2<<18) /* Report any changes */ | ||
405 | #define D_SDP_EVERY (3<<18) /* Report any changes */ | ||
406 | #define D_SDP_EOL (1<<17) /* EOL interrupt enable */ | ||
407 | #define D_SDP_IDLE (1<<16) /* HDLC idle interrupt enable */ | ||
408 | |||
409 | /* Pipe data MODE */ | ||
410 | #define D_SDP_MEM (0<<13) /* To/from memory */ | ||
411 | #define D_SDP_HDLC (2<<13) | ||
412 | #define D_SDP_HDLC_D (3<<13) /* D Channel (prio control) */ | ||
413 | #define D_SDP_SER (4<<13) /* Serial to serial */ | ||
414 | #define D_SDP_FIXED (6<<13) /* Short only */ | ||
415 | #define D_SDP_MODE(v) ((v)&(7<<13)) | ||
416 | |||
417 | #define D_SDP_TO_SER (1<<12) /* Direction */ | ||
418 | #define D_SDP_FROM_SER (0<<12) /* Direction */ | ||
419 | #define D_SDP_MSB (1<<11) /* Bit order within Byte */ | ||
420 | #define D_SDP_LSB (0<<11) /* Bit order within Byte */ | ||
421 | #define D_SDP_P (1<<10) /* Pointer Valid */ | ||
422 | #define D_SDP_A (1<<8) /* Abort */ | ||
423 | #define D_SDP_C (1<<7) /* Clear */ | ||
424 | |||
425 | /* Define Time Slot */ | ||
426 | #define D_DTS_VI (1<<17) /* Valid Input Time-Slot Descriptor */ | ||
427 | #define D_DTS_VO (1<<16) /* Valid Output Time-Slot Descriptor */ | ||
428 | #define D_DTS_INS (1<<15) /* Insert Time Slot */ | ||
429 | #define D_DTS_DEL (0<<15) /* Delete Time Slot */ | ||
430 | #define D_DTS_PRVIN(v) ((v)<<10) /* Previous In Pipe */ | ||
431 | #define D_DTS_PRVOUT(v) ((v)<<5) /* Previous Out Pipe */ | ||
432 | |||
433 | /* Time Slot defines */ | ||
434 | #define D_TS_LEN(v) ((v)<<24) /* Number of bits in this time slot */ | ||
435 | #define D_TS_CYCLE(v) ((v)<<14) /* Bit Count at start of TS */ | ||
436 | #define D_TS_DI (1<<13) /* Data Invert */ | ||
437 | #define D_TS_1CHANNEL (0<<10) /* Single Channel / Normal mode */ | ||
438 | #define D_TS_MONITOR (2<<10) /* Monitor pipe */ | ||
439 | #define D_TS_NONCONTIG (3<<10) /* Non contiguous mode */ | ||
440 | #define D_TS_ANCHOR (7<<10) /* Starting short pipes */ | ||
441 | #define D_TS_MON(v) ((v)<<5) /* Monitor Pipe */ | ||
442 | #define D_TS_NEXT(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */ | ||
443 | |||
444 | /* Concentration Highway Interface Modes */ | ||
445 | #define D_CHI_CHICM(v) ((v)<<16) /* Clock mode */ | ||
446 | #define D_CHI_IR (1<<15) /* Immediate Interrupt Report */ | ||
447 | #define D_CHI_EN (1<<14) /* CHIL Interrupt enabled */ | ||
448 | #define D_CHI_OD (1<<13) /* Open Drain Enable */ | ||
449 | #define D_CHI_FE (1<<12) /* Sample CHIFS on Rising Frame Edge */ | ||
450 | #define D_CHI_FD (1<<11) /* Frame Drive */ | ||
451 | #define D_CHI_BPF(v) ((v)<<0) /* Bits per Frame */ | ||
452 | |||
453 | /* NT: These are here for completeness */ | ||
454 | #define D_NT_FBIT (1<<17) /* Frame Bit */ | ||
455 | #define D_NT_NBF (1<<16) /* Number of bad frames to loose framing */ | ||
456 | #define D_NT_IRM_IMM (1<<15) /* Interrupt Report & Mask: Immediate */ | ||
457 | #define D_NT_IRM_EN (1<<14) /* Interrupt Report & Mask: Enable */ | ||
458 | #define D_NT_ISNT (1<<13) /* Configfure interface as NT */ | ||
459 | #define D_NT_FT (1<<12) /* Fixed Timing */ | ||
460 | #define D_NT_EZ (1<<11) /* Echo Channel is Zeros */ | ||
461 | #define D_NT_IFA (1<<10) /* Inhibit Final Activation */ | ||
462 | #define D_NT_ACT (1<<9) /* Activate Interface */ | ||
463 | #define D_NT_MFE (1<<8) /* Multiframe Enable */ | ||
464 | #define D_NT_RLB(v) ((v)<<5) /* Remote Loopback */ | ||
465 | #define D_NT_LLB(v) ((v)<<2) /* Local Loopback */ | ||
466 | #define D_NT_FACT (1<<1) /* Force Activation */ | ||
467 | #define D_NT_ABV (1<<0) /* Activate Bipolar Violation */ | ||
468 | |||
469 | /* Codec Setup */ | ||
470 | #define D_CDEC_CK(v) ((v)<<24) /* Clock Select */ | ||
471 | #define D_CDEC_FED(v) ((v)<<12) /* FSCOD Falling Edge Delay */ | ||
472 | #define D_CDEC_RED(v) ((v)<<0) /* FSCOD Rising Edge Delay */ | ||
473 | |||
474 | /* Test */ | ||
475 | #define D_TEST_RAM(v) ((v)<<16) /* RAM Pointer */ | ||
476 | #define D_TEST_SIZE(v) ((v)<<11) /* */ | ||
477 | #define D_TEST_ROMONOFF 0x5 /* Toggle ROM opcode monitor on/off */ | ||
478 | #define D_TEST_PROC 0x6 /* MicroProcessor test */ | ||
479 | #define D_TEST_SER 0x7 /* Serial-Controller test */ | ||
480 | #define D_TEST_RAMREAD 0x8 /* Copy from Ram to system memory */ | ||
481 | #define D_TEST_RAMWRITE 0x9 /* Copy into Ram from system memory */ | ||
482 | #define D_TEST_RAMBIST 0xa /* RAM Built-In Self Test */ | ||
483 | #define D_TEST_MCBIST 0xb /* Microcontroller Built-In Self Test */ | ||
484 | #define D_TEST_DUMP 0xe /* ROM Dump */ | ||
485 | |||
486 | /* CHI Data Mode */ | ||
487 | #define D_CDM_THI (1<<8) /* Transmit Data on CHIDR Pin */ | ||
488 | #define D_CDM_RHI (1<<7) /* Receive Data on CHIDX Pin */ | ||
489 | #define D_CDM_RCE (1<<6) /* Receive on Rising Edge of CHICK */ | ||
490 | #define D_CDM_XCE (1<<2) /* Transmit Data on Rising Edge of CHICK */ | ||
491 | #define D_CDM_XEN (1<<1) /* Transmit Highway Enable */ | ||
492 | #define D_CDM_REN (1<<0) /* Receive Highway Enable */ | ||
493 | |||
494 | /* The Interrupts */ | ||
495 | #define D_INTR_BRDY 1 /* Buffer Ready for processing */ | ||
496 | #define D_INTR_MINT 2 /* Marked Interrupt in RD/TD */ | ||
497 | #define D_INTR_IBEG 3 /* Flag to idle transition detected (HDLC) */ | ||
498 | #define D_INTR_IEND 4 /* Idle to flag transition detected (HDLC) */ | ||
499 | #define D_INTR_EOL 5 /* End of List */ | ||
500 | #define D_INTR_CMDI 6 /* Command has bean read */ | ||
501 | #define D_INTR_XCMP 8 /* Transmission of frame complete */ | ||
502 | #define D_INTR_SBRI 9 /* BRI status change info */ | ||
503 | #define D_INTR_FXDT 10 /* Fixed data change */ | ||
504 | #define D_INTR_CHIL 11 /* CHI lost frame sync (channel 36 only) */ | ||
505 | #define D_INTR_COLL 11 /* Unrecoverable D-Channel collision */ | ||
506 | #define D_INTR_DBYT 12 /* Dropped by frame slip */ | ||
507 | #define D_INTR_RBYT 13 /* Repeated by frame slip */ | ||
508 | #define D_INTR_LINT 14 /* Lost Interrupt */ | ||
509 | #define D_INTR_UNDR 15 /* DMA underrun */ | ||
510 | |||
511 | #define D_INTR_TE 32 | ||
512 | #define D_INTR_NT 34 | ||
513 | #define D_INTR_CHI 36 | ||
514 | #define D_INTR_CMD 38 | ||
515 | |||
516 | #define D_INTR_GETCHAN(v) (((v)>>24) & 0x3f) | ||
517 | #define D_INTR_GETCODE(v) (((v)>>20) & 0xf) | ||
518 | #define D_INTR_GETCMD(v) (((v)>>16) & 0xf) | ||
519 | #define D_INTR_GETVAL(v) ((v) & 0xffff) | ||
520 | #define D_INTR_GETRVAL(v) ((v) & 0xfffff) | ||
521 | |||
522 | #define D_P_0 0 /* TE receive anchor */ | ||
523 | #define D_P_1 1 /* TE transmit anchor */ | ||
524 | #define D_P_2 2 /* NT transmit anchor */ | ||
525 | #define D_P_3 3 /* NT receive anchor */ | ||
526 | #define D_P_4 4 /* CHI send data */ | ||
527 | #define D_P_5 5 /* CHI receive data */ | ||
528 | #define D_P_6 6 /* */ | ||
529 | #define D_P_7 7 /* */ | ||
530 | #define D_P_8 8 /* */ | ||
531 | #define D_P_9 9 /* */ | ||
532 | #define D_P_10 10 /* */ | ||
533 | #define D_P_11 11 /* */ | ||
534 | #define D_P_12 12 /* */ | ||
535 | #define D_P_13 13 /* */ | ||
536 | #define D_P_14 14 /* */ | ||
537 | #define D_P_15 15 /* */ | ||
538 | #define D_P_16 16 /* CHI anchor pipe */ | ||
539 | #define D_P_17 17 /* CHI send */ | ||
540 | #define D_P_18 18 /* CHI receive */ | ||
541 | #define D_P_19 19 /* CHI receive */ | ||
542 | #define D_P_20 20 /* CHI receive */ | ||
543 | #define D_P_21 21 /* */ | ||
544 | #define D_P_22 22 /* */ | ||
545 | #define D_P_23 23 /* */ | ||
546 | #define D_P_24 24 /* */ | ||
547 | #define D_P_25 25 /* */ | ||
548 | #define D_P_26 26 /* */ | ||
549 | #define D_P_27 27 /* */ | ||
550 | #define D_P_28 28 /* */ | ||
551 | #define D_P_29 29 /* */ | ||
552 | #define D_P_30 30 /* */ | ||
553 | #define D_P_31 31 /* */ | ||
554 | |||
555 | /* Transmit descriptor defines */ | ||
556 | #define DBRI_TD_F (1<<31) /* End of Frame */ | ||
557 | #define DBRI_TD_D (1<<30) /* Do not append CRC */ | ||
558 | #define DBRI_TD_CNT(v) ((v)<<16) /* Number of valid bytes in the buffer */ | ||
559 | #define DBRI_TD_B (1<<15) /* Final interrupt */ | ||
560 | #define DBRI_TD_M (1<<14) /* Marker interrupt */ | ||
561 | #define DBRI_TD_I (1<<13) /* Transmit Idle Characters */ | ||
562 | #define DBRI_TD_FCNT(v) (v) /* Flag Count */ | ||
563 | #define DBRI_TD_UNR (1<<3) /* Underrun: transmitter is out of data */ | ||
564 | #define DBRI_TD_ABT (1<<2) /* Abort: frame aborted */ | ||
565 | #define DBRI_TD_TBC (1<<0) /* Transmit buffer Complete */ | ||
566 | #define DBRI_TD_STATUS(v) ((v)&0xff) /* Transmit status */ | ||
567 | /* Maximum buffer size per TD: almost 8Kb */ | ||
568 | #define DBRI_TD_MAXCNT ((1 << 13) - 1) | ||
569 | |||
570 | /* Receive descriptor defines */ | ||
571 | #define DBRI_RD_F (1<<31) /* End of Frame */ | ||
572 | #define DBRI_RD_C (1<<30) /* Completed buffer */ | ||
573 | #define DBRI_RD_B (1<<15) /* Final interrupt */ | ||
574 | #define DBRI_RD_M (1<<14) /* Marker interrupt */ | ||
575 | #define DBRI_RD_BCNT(v) (v) /* Buffer size */ | ||
576 | #define DBRI_RD_CRC (1<<7) /* 0: CRC is correct */ | ||
577 | #define DBRI_RD_BBC (1<<6) /* 1: Bad Byte received */ | ||
578 | #define DBRI_RD_ABT (1<<5) /* Abort: frame aborted */ | ||
579 | #define DBRI_RD_OVRN (1<<3) /* Overrun: data lost */ | ||
580 | #define DBRI_RD_STATUS(v) ((v)&0xff) /* Receive status */ | ||
581 | #define DBRI_RD_CNT(v) (((v)>>16)&0x1fff) /* Valid bytes in the buffer */ | ||
582 | |||
583 | /* stream_info[] access */ | ||
584 | /* Translate the ALSA direction into the array index */ | ||
585 | #define DBRI_STREAMNO(substream) \ | ||
586 | (substream->stream == \ | ||
587 | SNDRV_PCM_STREAM_PLAYBACK? DBRI_PLAY: DBRI_REC) | ||
588 | |||
589 | /* Return a pointer to dbri_streaminfo */ | ||
590 | #define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)] | ||
591 | |||
592 | static snd_dbri_t *dbri_list = NULL; /* All DBRI devices */ | ||
593 | |||
594 | /* | ||
595 | * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. | ||
596 | * So we have to reverse the bits. Note: not all bit lengths are supported | ||
597 | */ | ||
598 | static __u32 reverse_bytes(__u32 b, int len) | ||
599 | { | ||
600 | switch (len) { | ||
601 | case 32: | ||
602 | b = ((b & 0xffff0000) >> 16) | ((b & 0x0000ffff) << 16); | ||
603 | case 16: | ||
604 | b = ((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8); | ||
605 | case 8: | ||
606 | b = ((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4); | ||
607 | case 4: | ||
608 | b = ((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2); | ||
609 | case 2: | ||
610 | b = ((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1); | ||
611 | case 1: | ||
612 | case 0: | ||
613 | break; | ||
614 | default: | ||
615 | printk(KERN_ERR "DBRI reverse_bytes: unsupported length\n"); | ||
616 | }; | ||
617 | |||
618 | return b; | ||
619 | } | ||
620 | |||
621 | /* | ||
622 | **************************************************************************** | ||
623 | ************** DBRI initialization and command synchronization ************* | ||
624 | **************************************************************************** | ||
625 | |||
626 | Commands are sent to the DBRI by building a list of them in memory, | ||
627 | then writing the address of the first list item to DBRI register 8. | ||
628 | The list is terminated with a WAIT command, which can generate a | ||
629 | CPU interrupt if required. | ||
630 | |||
631 | Since the DBRI can run in parallel with the CPU, several means of | ||
632 | synchronization present themselves. The original scheme (Rudolf's) | ||
633 | was to set a flag when we "cmdlock"ed the DBRI, clear the flag when | ||
634 | an interrupt signaled completion, and wait on a wait_queue if a routine | ||
635 | attempted to cmdlock while the flag was set. The problems arose when | ||
636 | we tried to cmdlock from inside an interrupt handler, which might | ||
637 | cause scheduling in an interrupt (if we waited), etc, etc | ||
638 | |||
639 | A more sophisticated scheme might involve a circular command buffer | ||
640 | or an array of command buffers. A routine could fill one with | ||
641 | commands and link it onto a list. When a interrupt signaled | ||
642 | completion of the current command buffer, look on the list for | ||
643 | the next one. | ||
644 | |||
645 | I've decided to implement something much simpler - after each command, | ||
646 | the CPU waits for the DBRI to finish the command by polling the P bit | ||
647 | in DBRI register 0. I've tried to implement this in such a way | ||
648 | that might make implementing a more sophisticated scheme easier. | ||
649 | |||
650 | Every time a routine wants to write commands to the DBRI, it must | ||
651 | first call dbri_cmdlock() and get an initial pointer into dbri->dma->cmd | ||
652 | in return. After the commands have been writen, dbri_cmdsend() is | ||
653 | called with the final pointer value. | ||
654 | |||
655 | */ | ||
656 | |||
657 | enum dbri_lock_t { NoGetLock, GetLock }; | ||
658 | |||
659 | static volatile s32 *dbri_cmdlock(snd_dbri_t * dbri, enum dbri_lock_t get) | ||
660 | { | ||
661 | #ifndef SMP | ||
662 | if ((get == GetLock) && spin_is_locked(&dbri->lock)) { | ||
663 | printk(KERN_ERR "DBRI: cmdlock called while in spinlock."); | ||
664 | } | ||
665 | #endif | ||
666 | |||
667 | /*if (get == GetLock) spin_lock(&dbri->lock); */ | ||
668 | return &dbri->dma->cmd[0]; | ||
669 | } | ||
670 | |||
671 | static void dbri_process_interrupt_buffer(snd_dbri_t *); | ||
672 | |||
673 | static void dbri_cmdsend(snd_dbri_t * dbri, volatile s32 * cmd) | ||
674 | { | ||
675 | int MAXLOOPS = 1000000; | ||
676 | int maxloops = MAXLOOPS; | ||
677 | volatile s32 *ptr; | ||
678 | |||
679 | for (ptr = &dbri->dma->cmd[0]; ptr < cmd; ptr++) { | ||
680 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); | ||
681 | } | ||
682 | |||
683 | if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS - 1) { | ||
684 | printk("DBRI: Command buffer overflow! (bug in driver)\n"); | ||
685 | /* Ignore the last part. */ | ||
686 | cmd = &dbri->dma->cmd[DBRI_NO_CMDS - 3]; | ||
687 | } | ||
688 | |||
689 | *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); | ||
690 | *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); | ||
691 | dbri->wait_seen = 0; | ||
692 | sbus_writel(dbri->dma_dvma, dbri->regs + REG8); | ||
693 | while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P)) | ||
694 | barrier(); | ||
695 | if (maxloops == 0) { | ||
696 | printk(KERN_ERR "DBRI: Chip never completed command buffer\n"); | ||
697 | dprintk(D_CMD, "DBRI: Chip never completed command buffer\n"); | ||
698 | } else { | ||
699 | while ((--maxloops) > 0 && (!dbri->wait_seen)) | ||
700 | dbri_process_interrupt_buffer(dbri); | ||
701 | if (maxloops == 0) { | ||
702 | printk(KERN_ERR "DBRI: Chip never acked WAIT\n"); | ||
703 | dprintk(D_CMD, "DBRI: Chip never acked WAIT\n"); | ||
704 | } else { | ||
705 | dprintk(D_CMD, "Chip completed command " | ||
706 | "buffer (%d)\n", MAXLOOPS - maxloops); | ||
707 | } | ||
708 | } | ||
709 | |||
710 | /*spin_unlock(&dbri->lock); */ | ||
711 | } | ||
712 | |||
713 | /* Lock must be held when calling this */ | ||
714 | static void dbri_reset(snd_dbri_t * dbri) | ||
715 | { | ||
716 | int i; | ||
717 | |||
718 | dprintk(D_GEN, "reset 0:%x 2:%x 8:%x 9:%x\n", | ||
719 | sbus_readl(dbri->regs + REG0), | ||
720 | sbus_readl(dbri->regs + REG2), | ||
721 | sbus_readl(dbri->regs + REG8), sbus_readl(dbri->regs + REG9)); | ||
722 | |||
723 | sbus_writel(D_R, dbri->regs + REG0); /* Soft Reset */ | ||
724 | for (i = 0; (sbus_readl(dbri->regs + REG0) & D_R) && i < 64; i++) | ||
725 | udelay(10); | ||
726 | } | ||
727 | |||
728 | /* Lock must not be held before calling this */ | ||
729 | static void dbri_initialize(snd_dbri_t * dbri) | ||
730 | { | ||
731 | volatile s32 *cmd; | ||
732 | u32 dma_addr, tmp; | ||
733 | unsigned long flags; | ||
734 | int n; | ||
735 | |||
736 | spin_lock_irqsave(&dbri->lock, flags); | ||
737 | |||
738 | dbri_reset(dbri); | ||
739 | |||
740 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
741 | dprintk(D_GEN, "init: cmd: %p, int: %p\n", | ||
742 | &dbri->dma->cmd[0], &dbri->dma->intr[0]); | ||
743 | |||
744 | /* | ||
745 | * Initialize the interrupt ringbuffer. | ||
746 | */ | ||
747 | for (n = 0; n < DBRI_NO_INTS - 1; n++) { | ||
748 | dma_addr = dbri->dma_dvma; | ||
749 | dma_addr += dbri_dma_off(intr, ((n + 1) & DBRI_INT_BLK)); | ||
750 | dbri->dma->intr[n * DBRI_INT_BLK] = dma_addr; | ||
751 | } | ||
752 | dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); | ||
753 | dbri->dma->intr[n * DBRI_INT_BLK] = dma_addr; | ||
754 | dbri->dbri_irqp = 1; | ||
755 | |||
756 | /* Initialize pipes */ | ||
757 | for (n = 0; n < DBRI_NO_PIPES; n++) | ||
758 | dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1; | ||
759 | |||
760 | /* We should query the openprom to see what burst sizes this | ||
761 | * SBus supports. For now, just disable all SBus bursts */ | ||
762 | tmp = sbus_readl(dbri->regs + REG0); | ||
763 | tmp &= ~(D_G | D_S | D_E); | ||
764 | sbus_writel(tmp, dbri->regs + REG0); | ||
765 | |||
766 | /* | ||
767 | * Set up the interrupt queue | ||
768 | */ | ||
769 | dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); | ||
770 | *(cmd++) = DBRI_CMD(D_IIQ, 0, 0); | ||
771 | *(cmd++) = dma_addr; | ||
772 | |||
773 | dbri_cmdsend(dbri, cmd); | ||
774 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
775 | } | ||
776 | |||
777 | /* | ||
778 | **************************************************************************** | ||
779 | ************************** DBRI data pipe management *********************** | ||
780 | **************************************************************************** | ||
781 | |||
782 | While DBRI control functions use the command and interrupt buffers, the | ||
783 | main data path takes the form of data pipes, which can be short (command | ||
784 | and interrupt driven), or long (attached to DMA buffers). These functions | ||
785 | provide a rudimentary means of setting up and managing the DBRI's pipes, | ||
786 | but the calling functions have to make sure they respect the pipes' linked | ||
787 | list ordering, among other things. The transmit and receive functions | ||
788 | here interface closely with the transmit and receive interrupt code. | ||
789 | |||
790 | */ | ||
791 | static int pipe_active(snd_dbri_t * dbri, int pipe) | ||
792 | { | ||
793 | return ((pipe >= 0) && (dbri->pipes[pipe].desc != -1)); | ||
794 | } | ||
795 | |||
796 | /* reset_pipe(dbri, pipe) | ||
797 | * | ||
798 | * Called on an in-use pipe to clear anything being transmitted or received | ||
799 | * Lock must be held before calling this. | ||
800 | */ | ||
801 | static void reset_pipe(snd_dbri_t * dbri, int pipe) | ||
802 | { | ||
803 | int sdp; | ||
804 | int desc; | ||
805 | volatile int *cmd; | ||
806 | |||
807 | if (pipe < 0 || pipe > 31) { | ||
808 | printk("DBRI: reset_pipe called with illegal pipe number\n"); | ||
809 | return; | ||
810 | } | ||
811 | |||
812 | sdp = dbri->pipes[pipe].sdp; | ||
813 | if (sdp == 0) { | ||
814 | printk("DBRI: reset_pipe called on uninitialized pipe\n"); | ||
815 | return; | ||
816 | } | ||
817 | |||
818 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
819 | *(cmd++) = DBRI_CMD(D_SDP, 0, sdp | D_SDP_C | D_SDP_P); | ||
820 | *(cmd++) = 0; | ||
821 | dbri_cmdsend(dbri, cmd); | ||
822 | |||
823 | desc = dbri->pipes[pipe].first_desc; | ||
824 | while (desc != -1) { | ||
825 | dbri->descs[desc].inuse = 0; | ||
826 | desc = dbri->descs[desc].next; | ||
827 | } | ||
828 | |||
829 | dbri->pipes[pipe].desc = -1; | ||
830 | dbri->pipes[pipe].first_desc = -1; | ||
831 | } | ||
832 | |||
833 | /* FIXME: direction as an argument? */ | ||
834 | static void setup_pipe(snd_dbri_t * dbri, int pipe, int sdp) | ||
835 | { | ||
836 | if (pipe < 0 || pipe > 31) { | ||
837 | printk("DBRI: setup_pipe called with illegal pipe number\n"); | ||
838 | return; | ||
839 | } | ||
840 | |||
841 | if ((sdp & 0xf800) != sdp) { | ||
842 | printk("DBRI: setup_pipe called with strange SDP value\n"); | ||
843 | /* sdp &= 0xf800; */ | ||
844 | } | ||
845 | |||
846 | /* If this is a fixed receive pipe, arrange for an interrupt | ||
847 | * every time its data changes | ||
848 | */ | ||
849 | if (D_SDP_MODE(sdp) == D_SDP_FIXED && !(sdp & D_SDP_TO_SER)) | ||
850 | sdp |= D_SDP_CHANGE; | ||
851 | |||
852 | sdp |= D_PIPE(pipe); | ||
853 | dbri->pipes[pipe].sdp = sdp; | ||
854 | dbri->pipes[pipe].desc = -1; | ||
855 | dbri->pipes[pipe].first_desc = -1; | ||
856 | if (sdp & D_SDP_TO_SER) | ||
857 | dbri->pipes[pipe].direction = PIPEoutput; | ||
858 | else | ||
859 | dbri->pipes[pipe].direction = PIPEinput; | ||
860 | |||
861 | reset_pipe(dbri, pipe); | ||
862 | } | ||
863 | |||
864 | /* FIXME: direction not needed */ | ||
865 | static void link_time_slot(snd_dbri_t * dbri, int pipe, | ||
866 | enum in_or_out direction, int basepipe, | ||
867 | int length, int cycle) | ||
868 | { | ||
869 | volatile s32 *cmd; | ||
870 | int val; | ||
871 | int prevpipe; | ||
872 | int nextpipe; | ||
873 | |||
874 | if (pipe < 0 || pipe > 31 || basepipe < 0 || basepipe > 31) { | ||
875 | printk | ||
876 | ("DBRI: link_time_slot called with illegal pipe number\n"); | ||
877 | return; | ||
878 | } | ||
879 | |||
880 | if (dbri->pipes[pipe].sdp == 0 || dbri->pipes[basepipe].sdp == 0) { | ||
881 | printk("DBRI: link_time_slot called on uninitialized pipe\n"); | ||
882 | return; | ||
883 | } | ||
884 | |||
885 | /* Deal with CHI special case: | ||
886 | * "If transmission on edges 0 or 1 is desired, then cycle n | ||
887 | * (where n = # of bit times per frame...) must be used." | ||
888 | * - DBRI data sheet, page 11 | ||
889 | */ | ||
890 | if (basepipe == 16 && direction == PIPEoutput && cycle == 0) | ||
891 | cycle = dbri->chi_bpf; | ||
892 | |||
893 | if (basepipe == pipe) { | ||
894 | prevpipe = pipe; | ||
895 | nextpipe = pipe; | ||
896 | } else { | ||
897 | /* We're not initializing a new linked list (basepipe != pipe), | ||
898 | * so run through the linked list and find where this pipe | ||
899 | * should be sloted in, based on its cycle. CHI confuses | ||
900 | * things a bit, since it has a single anchor for both its | ||
901 | * transmit and receive lists. | ||
902 | */ | ||
903 | if (basepipe == 16) { | ||
904 | if (direction == PIPEinput) { | ||
905 | prevpipe = dbri->chi_in_pipe; | ||
906 | } else { | ||
907 | prevpipe = dbri->chi_out_pipe; | ||
908 | } | ||
909 | } else { | ||
910 | prevpipe = basepipe; | ||
911 | } | ||
912 | |||
913 | nextpipe = dbri->pipes[prevpipe].nextpipe; | ||
914 | |||
915 | while (dbri->pipes[nextpipe].cycle < cycle | ||
916 | && dbri->pipes[nextpipe].nextpipe != basepipe) { | ||
917 | prevpipe = nextpipe; | ||
918 | nextpipe = dbri->pipes[nextpipe].nextpipe; | ||
919 | } | ||
920 | } | ||
921 | |||
922 | if (prevpipe == 16) { | ||
923 | if (direction == PIPEinput) { | ||
924 | dbri->chi_in_pipe = pipe; | ||
925 | } else { | ||
926 | dbri->chi_out_pipe = pipe; | ||
927 | } | ||
928 | } else { | ||
929 | dbri->pipes[prevpipe].nextpipe = pipe; | ||
930 | } | ||
931 | |||
932 | dbri->pipes[pipe].nextpipe = nextpipe; | ||
933 | dbri->pipes[pipe].cycle = cycle; | ||
934 | dbri->pipes[pipe].length = length; | ||
935 | |||
936 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
937 | |||
938 | if (direction == PIPEinput) { | ||
939 | val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(prevpipe) | pipe; | ||
940 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
941 | *(cmd++) = | ||
942 | D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe); | ||
943 | *(cmd++) = 0; | ||
944 | } else { | ||
945 | val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(prevpipe) | pipe; | ||
946 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
947 | *(cmd++) = 0; | ||
948 | *(cmd++) = | ||
949 | D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe); | ||
950 | } | ||
951 | |||
952 | dbri_cmdsend(dbri, cmd); | ||
953 | } | ||
954 | |||
955 | static void unlink_time_slot(snd_dbri_t * dbri, int pipe, | ||
956 | enum in_or_out direction, int prevpipe, | ||
957 | int nextpipe) | ||
958 | { | ||
959 | volatile s32 *cmd; | ||
960 | int val; | ||
961 | |||
962 | if (pipe < 0 || pipe > 31 || prevpipe < 0 || prevpipe > 31) { | ||
963 | printk | ||
964 | ("DBRI: unlink_time_slot called with illegal pipe number\n"); | ||
965 | return; | ||
966 | } | ||
967 | |||
968 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
969 | |||
970 | if (direction == PIPEinput) { | ||
971 | val = D_DTS_VI | D_DTS_DEL | D_DTS_PRVIN(prevpipe) | pipe; | ||
972 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
973 | *(cmd++) = D_TS_NEXT(nextpipe); | ||
974 | *(cmd++) = 0; | ||
975 | } else { | ||
976 | val = D_DTS_VO | D_DTS_DEL | D_DTS_PRVOUT(prevpipe) | pipe; | ||
977 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
978 | *(cmd++) = 0; | ||
979 | *(cmd++) = D_TS_NEXT(nextpipe); | ||
980 | } | ||
981 | |||
982 | dbri_cmdsend(dbri, cmd); | ||
983 | } | ||
984 | |||
985 | /* xmit_fixed() / recv_fixed() | ||
986 | * | ||
987 | * Transmit/receive data on a "fixed" pipe - i.e, one whose contents are not | ||
988 | * expected to change much, and which we don't need to buffer. | ||
989 | * The DBRI only interrupts us when the data changes (receive pipes), | ||
990 | * or only changes the data when this function is called (transmit pipes). | ||
991 | * Only short pipes (numbers 16-31) can be used in fixed data mode. | ||
992 | * | ||
993 | * These function operate on a 32-bit field, no matter how large | ||
994 | * the actual time slot is. The interrupt handler takes care of bit | ||
995 | * ordering and alignment. An 8-bit time slot will always end up | ||
996 | * in the low-order 8 bits, filled either MSB-first or LSB-first, | ||
997 | * depending on the settings passed to setup_pipe() | ||
998 | */ | ||
999 | static void xmit_fixed(snd_dbri_t * dbri, int pipe, unsigned int data) | ||
1000 | { | ||
1001 | volatile s32 *cmd; | ||
1002 | |||
1003 | if (pipe < 16 || pipe > 31) { | ||
1004 | printk("DBRI: xmit_fixed: Illegal pipe number\n"); | ||
1005 | return; | ||
1006 | } | ||
1007 | |||
1008 | if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) { | ||
1009 | printk("DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe); | ||
1010 | return; | ||
1011 | } | ||
1012 | |||
1013 | if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) { | ||
1014 | printk("DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe); | ||
1015 | return; | ||
1016 | } | ||
1017 | |||
1018 | if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) { | ||
1019 | printk("DBRI: xmit_fixed: Called on receive pipe %d\n", pipe); | ||
1020 | return; | ||
1021 | } | ||
1022 | |||
1023 | /* DBRI short pipes always transmit LSB first */ | ||
1024 | |||
1025 | if (dbri->pipes[pipe].sdp & D_SDP_MSB) | ||
1026 | data = reverse_bytes(data, dbri->pipes[pipe].length); | ||
1027 | |||
1028 | cmd = dbri_cmdlock(dbri, GetLock); | ||
1029 | |||
1030 | *(cmd++) = DBRI_CMD(D_SSP, 0, pipe); | ||
1031 | *(cmd++) = data; | ||
1032 | |||
1033 | dbri_cmdsend(dbri, cmd); | ||
1034 | } | ||
1035 | |||
1036 | static void recv_fixed(snd_dbri_t * dbri, int pipe, volatile __u32 * ptr) | ||
1037 | { | ||
1038 | if (pipe < 16 || pipe > 31) { | ||
1039 | printk("DBRI: recv_fixed called with illegal pipe number\n"); | ||
1040 | return; | ||
1041 | } | ||
1042 | |||
1043 | if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) { | ||
1044 | printk("DBRI: recv_fixed called on non-fixed pipe %d\n", pipe); | ||
1045 | return; | ||
1046 | } | ||
1047 | |||
1048 | if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) { | ||
1049 | printk("DBRI: recv_fixed called on transmit pipe %d\n", pipe); | ||
1050 | return; | ||
1051 | } | ||
1052 | |||
1053 | dbri->pipes[pipe].recv_fixed_ptr = ptr; | ||
1054 | } | ||
1055 | |||
1056 | /* setup_descs() | ||
1057 | * | ||
1058 | * Setup transmit/receive data on a "long" pipe - i.e, one associated | ||
1059 | * with a DMA buffer. | ||
1060 | * | ||
1061 | * Only pipe numbers 0-15 can be used in this mode. | ||
1062 | * | ||
1063 | * This function takes a stream number pointing to a data buffer, | ||
1064 | * and work by building chains of descriptors which identify the | ||
1065 | * data buffers. Buffers too large for a single descriptor will | ||
1066 | * be spread across multiple descriptors. | ||
1067 | */ | ||
1068 | static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period) | ||
1069 | { | ||
1070 | dbri_streaminfo_t *info = &dbri->stream_info[streamno]; | ||
1071 | __u32 dvma_buffer; | ||
1072 | int desc = 0; | ||
1073 | int len; | ||
1074 | int first_desc = -1; | ||
1075 | int last_desc = -1; | ||
1076 | |||
1077 | if (info->pipe < 0 || info->pipe > 15) { | ||
1078 | printk("DBRI: setup_descs: Illegal pipe number\n"); | ||
1079 | return -2; | ||
1080 | } | ||
1081 | |||
1082 | if (dbri->pipes[info->pipe].sdp == 0) { | ||
1083 | printk("DBRI: setup_descs: Uninitialized pipe %d\n", | ||
1084 | info->pipe); | ||
1085 | return -2; | ||
1086 | } | ||
1087 | |||
1088 | dvma_buffer = info->dvma_buffer; | ||
1089 | len = info->size; | ||
1090 | |||
1091 | if (streamno == DBRI_PLAY) { | ||
1092 | if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) { | ||
1093 | printk("DBRI: setup_descs: Called on receive pipe %d\n", | ||
1094 | info->pipe); | ||
1095 | return -2; | ||
1096 | } | ||
1097 | } else { | ||
1098 | if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) { | ||
1099 | printk | ||
1100 | ("DBRI: setup_descs: Called on transmit pipe %d\n", | ||
1101 | info->pipe); | ||
1102 | return -2; | ||
1103 | } | ||
1104 | /* Should be able to queue multiple buffers to receive on a pipe */ | ||
1105 | if (pipe_active(dbri, info->pipe)) { | ||
1106 | printk("DBRI: recv_on_pipe: Called on active pipe %d\n", | ||
1107 | info->pipe); | ||
1108 | return -2; | ||
1109 | } | ||
1110 | |||
1111 | /* Make sure buffer size is multiple of four */ | ||
1112 | len &= ~3; | ||
1113 | } | ||
1114 | |||
1115 | while (len > 0) { | ||
1116 | int mylen; | ||
1117 | |||
1118 | for (; desc < DBRI_NO_DESCS; desc++) { | ||
1119 | if (!dbri->descs[desc].inuse) | ||
1120 | break; | ||
1121 | } | ||
1122 | if (desc == DBRI_NO_DESCS) { | ||
1123 | printk("DBRI: setup_descs: No descriptors\n"); | ||
1124 | return -1; | ||
1125 | } | ||
1126 | |||
1127 | if (len > DBRI_TD_MAXCNT) { | ||
1128 | mylen = DBRI_TD_MAXCNT; /* 8KB - 1 */ | ||
1129 | } else { | ||
1130 | mylen = len; | ||
1131 | } | ||
1132 | if (mylen > period) { | ||
1133 | mylen = period; | ||
1134 | } | ||
1135 | |||
1136 | dbri->descs[desc].inuse = 1; | ||
1137 | dbri->descs[desc].next = -1; | ||
1138 | dbri->dma->desc[desc].ba = dvma_buffer; | ||
1139 | dbri->dma->desc[desc].nda = 0; | ||
1140 | |||
1141 | if (streamno == DBRI_PLAY) { | ||
1142 | dbri->descs[desc].len = mylen; | ||
1143 | dbri->dma->desc[desc].word1 = DBRI_TD_CNT(mylen); | ||
1144 | dbri->dma->desc[desc].word4 = 0; | ||
1145 | if (first_desc != -1) | ||
1146 | dbri->dma->desc[desc].word1 |= DBRI_TD_M; | ||
1147 | } else { | ||
1148 | dbri->descs[desc].len = 0; | ||
1149 | dbri->dma->desc[desc].word1 = 0; | ||
1150 | dbri->dma->desc[desc].word4 = | ||
1151 | DBRI_RD_B | DBRI_RD_BCNT(mylen); | ||
1152 | } | ||
1153 | |||
1154 | if (first_desc == -1) { | ||
1155 | first_desc = desc; | ||
1156 | } else { | ||
1157 | dbri->descs[last_desc].next = desc; | ||
1158 | dbri->dma->desc[last_desc].nda = | ||
1159 | dbri->dma_dvma + dbri_dma_off(desc, desc); | ||
1160 | } | ||
1161 | |||
1162 | last_desc = desc; | ||
1163 | dvma_buffer += mylen; | ||
1164 | len -= mylen; | ||
1165 | } | ||
1166 | |||
1167 | if (first_desc == -1 || last_desc == -1) { | ||
1168 | printk("DBRI: setup_descs: Not enough descriptors available\n"); | ||
1169 | return -1; | ||
1170 | } | ||
1171 | |||
1172 | dbri->dma->desc[last_desc].word1 &= ~DBRI_TD_M; | ||
1173 | if (streamno == DBRI_PLAY) { | ||
1174 | dbri->dma->desc[last_desc].word1 |= | ||
1175 | DBRI_TD_I | DBRI_TD_F | DBRI_TD_B; | ||
1176 | } | ||
1177 | dbri->pipes[info->pipe].first_desc = first_desc; | ||
1178 | dbri->pipes[info->pipe].desc = first_desc; | ||
1179 | |||
1180 | for (desc = first_desc; desc != -1; desc = dbri->descs[desc].next) { | ||
1181 | dprintk(D_DESC, "DESC %d: %08x %08x %08x %08x\n", | ||
1182 | desc, | ||
1183 | dbri->dma->desc[desc].word1, | ||
1184 | dbri->dma->desc[desc].ba, | ||
1185 | dbri->dma->desc[desc].nda, dbri->dma->desc[desc].word4); | ||
1186 | } | ||
1187 | return 0; | ||
1188 | } | ||
1189 | |||
1190 | /* | ||
1191 | **************************************************************************** | ||
1192 | ************************** DBRI - CHI interface **************************** | ||
1193 | **************************************************************************** | ||
1194 | |||
1195 | The CHI is a four-wire (clock, frame sync, data in, data out) time-division | ||
1196 | multiplexed serial interface which the DBRI can operate in either master | ||
1197 | (give clock/frame sync) or slave (take clock/frame sync) mode. | ||
1198 | |||
1199 | */ | ||
1200 | |||
1201 | enum master_or_slave { CHImaster, CHIslave }; | ||
1202 | |||
1203 | static void reset_chi(snd_dbri_t * dbri, enum master_or_slave master_or_slave, | ||
1204 | int bits_per_frame) | ||
1205 | { | ||
1206 | volatile s32 *cmd; | ||
1207 | int val; | ||
1208 | static int chi_initialized = 0; /* FIXME: mutex? */ | ||
1209 | |||
1210 | if (!chi_initialized) { | ||
1211 | |||
1212 | cmd = dbri_cmdlock(dbri, GetLock); | ||
1213 | |||
1214 | /* Set CHI Anchor: Pipe 16 */ | ||
1215 | |||
1216 | val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(16) | D_PIPE(16); | ||
1217 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
1218 | *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); | ||
1219 | *(cmd++) = 0; | ||
1220 | |||
1221 | val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(16) | D_PIPE(16); | ||
1222 | *(cmd++) = DBRI_CMD(D_DTS, 0, val); | ||
1223 | *(cmd++) = 0; | ||
1224 | *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); | ||
1225 | |||
1226 | dbri->pipes[16].sdp = 1; | ||
1227 | dbri->pipes[16].nextpipe = 16; | ||
1228 | dbri->chi_in_pipe = 16; | ||
1229 | dbri->chi_out_pipe = 16; | ||
1230 | |||
1231 | #if 0 | ||
1232 | chi_initialized++; | ||
1233 | #endif | ||
1234 | } else { | ||
1235 | int pipe; | ||
1236 | |||
1237 | for (pipe = dbri->chi_in_pipe; | ||
1238 | pipe != 16; pipe = dbri->pipes[pipe].nextpipe) { | ||
1239 | unlink_time_slot(dbri, pipe, PIPEinput, | ||
1240 | 16, dbri->pipes[pipe].nextpipe); | ||
1241 | } | ||
1242 | for (pipe = dbri->chi_out_pipe; | ||
1243 | pipe != 16; pipe = dbri->pipes[pipe].nextpipe) { | ||
1244 | unlink_time_slot(dbri, pipe, PIPEoutput, | ||
1245 | 16, dbri->pipes[pipe].nextpipe); | ||
1246 | } | ||
1247 | |||
1248 | dbri->chi_in_pipe = 16; | ||
1249 | dbri->chi_out_pipe = 16; | ||
1250 | |||
1251 | cmd = dbri_cmdlock(dbri, GetLock); | ||
1252 | } | ||
1253 | |||
1254 | if (master_or_slave == CHIslave) { | ||
1255 | /* Setup DBRI for CHI Slave - receive clock, frame sync (FS) | ||
1256 | * | ||
1257 | * CHICM = 0 (slave mode, 8 kHz frame rate) | ||
1258 | * IR = give immediate CHI status interrupt | ||
1259 | * EN = give CHI status interrupt upon change | ||
1260 | */ | ||
1261 | *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(0)); | ||
1262 | } else { | ||
1263 | /* Setup DBRI for CHI Master - generate clock, FS | ||
1264 | * | ||
1265 | * BPF = bits per 8 kHz frame | ||
1266 | * 12.288 MHz / CHICM_divisor = clock rate | ||
1267 | * FD = 1 - drive CHIFS on rising edge of CHICK | ||
1268 | */ | ||
1269 | int clockrate = bits_per_frame * 8; | ||
1270 | int divisor = 12288 / clockrate; | ||
1271 | |||
1272 | if (divisor > 255 || divisor * clockrate != 12288) | ||
1273 | printk("DBRI: illegal bits_per_frame in setup_chi\n"); | ||
1274 | |||
1275 | *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD | ||
1276 | | D_CHI_BPF(bits_per_frame)); | ||
1277 | } | ||
1278 | |||
1279 | dbri->chi_bpf = bits_per_frame; | ||
1280 | |||
1281 | /* CHI Data Mode | ||
1282 | * | ||
1283 | * RCE = 0 - receive on falling edge of CHICK | ||
1284 | * XCE = 1 - transmit on rising edge of CHICK | ||
1285 | * XEN = 1 - enable transmitter | ||
1286 | * REN = 1 - enable receiver | ||
1287 | */ | ||
1288 | |||
1289 | *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); | ||
1290 | *(cmd++) = DBRI_CMD(D_CDM, 0, D_CDM_XCE | D_CDM_XEN | D_CDM_REN); | ||
1291 | |||
1292 | dbri_cmdsend(dbri, cmd); | ||
1293 | } | ||
1294 | |||
1295 | /* | ||
1296 | **************************************************************************** | ||
1297 | *********************** CS4215 audio codec management ********************** | ||
1298 | **************************************************************************** | ||
1299 | |||
1300 | In the standard SPARC audio configuration, the CS4215 codec is attached | ||
1301 | to the DBRI via the CHI interface and few of the DBRI's PIO pins. | ||
1302 | |||
1303 | */ | ||
1304 | static void cs4215_setup_pipes(snd_dbri_t * dbri) | ||
1305 | { | ||
1306 | /* | ||
1307 | * Data mode: | ||
1308 | * Pipe 4: Send timeslots 1-4 (audio data) | ||
1309 | * Pipe 20: Send timeslots 5-8 (part of ctrl data) | ||
1310 | * Pipe 6: Receive timeslots 1-4 (audio data) | ||
1311 | * Pipe 21: Receive timeslots 6-7. We can only receive 20 bits via | ||
1312 | * interrupt, and the rest of the data (slot 5 and 8) is | ||
1313 | * not relevant for us (only for doublechecking). | ||
1314 | * | ||
1315 | * Control mode: | ||
1316 | * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly) | ||
1317 | * Pipe 18: Receive timeslot 1 (clb). | ||
1318 | * Pipe 19: Receive timeslot 7 (version). | ||
1319 | */ | ||
1320 | |||
1321 | setup_pipe(dbri, 4, D_SDP_MEM | D_SDP_TO_SER | D_SDP_MSB); | ||
1322 | setup_pipe(dbri, 20, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); | ||
1323 | setup_pipe(dbri, 6, D_SDP_MEM | D_SDP_FROM_SER | D_SDP_MSB); | ||
1324 | setup_pipe(dbri, 21, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); | ||
1325 | |||
1326 | setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); | ||
1327 | setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); | ||
1328 | setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); | ||
1329 | } | ||
1330 | |||
1331 | static int cs4215_init_data(struct cs4215 *mm) | ||
1332 | { | ||
1333 | /* | ||
1334 | * No action, memory resetting only. | ||
1335 | * | ||
1336 | * Data Time Slot 5-8 | ||
1337 | * Speaker,Line and Headphone enable. Gain set to the half. | ||
1338 | * Input is mike. | ||
1339 | */ | ||
1340 | mm->data[0] = CS4215_LO(0x20) | CS4215_HE | CS4215_LE; | ||
1341 | mm->data[1] = CS4215_RO(0x20) | CS4215_SE; | ||
1342 | mm->data[2] = CS4215_LG(0x8) | CS4215_IS | CS4215_PIO0 | CS4215_PIO1; | ||
1343 | mm->data[3] = CS4215_RG(0x8) | CS4215_MA(0xf); | ||
1344 | |||
1345 | /* | ||
1346 | * Control Time Slot 1-4 | ||
1347 | * 0: Default I/O voltage scale | ||
1348 | * 1: 8 bit ulaw, 8kHz, mono, high pass filter disabled | ||
1349 | * 2: Serial enable, CHI master, 128 bits per frame, clock 1 | ||
1350 | * 3: Tests disabled | ||
1351 | */ | ||
1352 | mm->ctrl[0] = CS4215_RSRVD_1 | CS4215_MLB; | ||
1353 | mm->ctrl[1] = CS4215_DFR_ULAW | CS4215_FREQ[0].csval; | ||
1354 | mm->ctrl[2] = CS4215_XCLK | CS4215_BSEL_128 | CS4215_FREQ[0].xtal; | ||
1355 | mm->ctrl[3] = 0; | ||
1356 | |||
1357 | mm->status = 0; | ||
1358 | mm->version = 0xff; | ||
1359 | mm->precision = 8; /* For ULAW */ | ||
1360 | mm->channels = 2; | ||
1361 | |||
1362 | return 0; | ||
1363 | } | ||
1364 | |||
1365 | static void cs4215_setdata(snd_dbri_t * dbri, int muted) | ||
1366 | { | ||
1367 | if (muted) { | ||
1368 | dbri->mm.data[0] |= 63; | ||
1369 | dbri->mm.data[1] |= 63; | ||
1370 | dbri->mm.data[2] &= ~15; | ||
1371 | dbri->mm.data[3] &= ~15; | ||
1372 | } else { | ||
1373 | /* Start by setting the playback attenuation. */ | ||
1374 | dbri_streaminfo_t *info = &dbri->stream_info[DBRI_PLAY]; | ||
1375 | int left_gain = info->left_gain % 64; | ||
1376 | int right_gain = info->right_gain % 64; | ||
1377 | |||
1378 | if (info->balance < DBRI_MID_BALANCE) { | ||
1379 | right_gain *= info->balance; | ||
1380 | right_gain /= DBRI_MID_BALANCE; | ||
1381 | } else { | ||
1382 | left_gain *= DBRI_RIGHT_BALANCE - info->balance; | ||
1383 | left_gain /= DBRI_MID_BALANCE; | ||
1384 | } | ||
1385 | |||
1386 | dbri->mm.data[0] &= ~0x3f; /* Reset the volume bits */ | ||
1387 | dbri->mm.data[1] &= ~0x3f; | ||
1388 | dbri->mm.data[0] |= (DBRI_MAX_VOLUME - left_gain); | ||
1389 | dbri->mm.data[1] |= (DBRI_MAX_VOLUME - right_gain); | ||
1390 | |||
1391 | /* Now set the recording gain. */ | ||
1392 | info = &dbri->stream_info[DBRI_REC]; | ||
1393 | left_gain = info->left_gain % 16; | ||
1394 | right_gain = info->right_gain % 16; | ||
1395 | dbri->mm.data[2] |= CS4215_LG(left_gain); | ||
1396 | dbri->mm.data[3] |= CS4215_RG(right_gain); | ||
1397 | } | ||
1398 | |||
1399 | xmit_fixed(dbri, 20, *(int *)dbri->mm.data); | ||
1400 | } | ||
1401 | |||
1402 | /* | ||
1403 | * Set the CS4215 to data mode. | ||
1404 | */ | ||
1405 | static void cs4215_open(snd_dbri_t * dbri) | ||
1406 | { | ||
1407 | int data_width; | ||
1408 | u32 tmp; | ||
1409 | |||
1410 | dprintk(D_MM, "cs4215_open: %d channels, %d bits\n", | ||
1411 | dbri->mm.channels, dbri->mm.precision); | ||
1412 | |||
1413 | /* Temporarily mute outputs, and wait 1/8000 sec (125 us) | ||
1414 | * to make sure this takes. This avoids clicking noises. | ||
1415 | */ | ||
1416 | |||
1417 | cs4215_setdata(dbri, 1); | ||
1418 | udelay(125); | ||
1419 | |||
1420 | /* | ||
1421 | * Data mode: | ||
1422 | * Pipe 4: Send timeslots 1-4 (audio data) | ||
1423 | * Pipe 20: Send timeslots 5-8 (part of ctrl data) | ||
1424 | * Pipe 6: Receive timeslots 1-4 (audio data) | ||
1425 | * Pipe 21: Receive timeslots 6-7. We can only receive 20 bits via | ||
1426 | * interrupt, and the rest of the data (slot 5 and 8) is | ||
1427 | * not relevant for us (only for doublechecking). | ||
1428 | * | ||
1429 | * Just like in control mode, the time slots are all offset by eight | ||
1430 | * bits. The CS4215, it seems, observes TSIN (the delayed signal) | ||
1431 | * even if it's the CHI master. Don't ask me... | ||
1432 | */ | ||
1433 | tmp = sbus_readl(dbri->regs + REG0); | ||
1434 | tmp &= ~(D_C); /* Disable CHI */ | ||
1435 | sbus_writel(tmp, dbri->regs + REG0); | ||
1436 | |||
1437 | /* Switch CS4215 to data mode - set PIO3 to 1 */ | ||
1438 | sbus_writel(D_ENPIO | D_PIO1 | D_PIO3 | | ||
1439 | (dbri->mm.onboard ? D_PIO0 : D_PIO2), dbri->regs + REG2); | ||
1440 | |||
1441 | reset_chi(dbri, CHIslave, 128); | ||
1442 | |||
1443 | /* Note: this next doesn't work for 8-bit stereo, because the two | ||
1444 | * channels would be on timeslots 1 and 3, with 2 and 4 idle. | ||
1445 | * (See CS4215 datasheet Fig 15) | ||
1446 | * | ||
1447 | * DBRI non-contiguous mode would be required to make this work. | ||
1448 | */ | ||
1449 | data_width = dbri->mm.channels * dbri->mm.precision; | ||
1450 | |||
1451 | link_time_slot(dbri, 20, PIPEoutput, 16, 32, dbri->mm.offset + 32); | ||
1452 | link_time_slot(dbri, 4, PIPEoutput, 16, data_width, dbri->mm.offset); | ||
1453 | link_time_slot(dbri, 6, PIPEinput, 16, data_width, dbri->mm.offset); | ||
1454 | link_time_slot(dbri, 21, PIPEinput, 16, 16, dbri->mm.offset + 40); | ||
1455 | |||
1456 | /* FIXME: enable CHI after _setdata? */ | ||
1457 | tmp = sbus_readl(dbri->regs + REG0); | ||
1458 | tmp |= D_C; /* Enable CHI */ | ||
1459 | sbus_writel(tmp, dbri->regs + REG0); | ||
1460 | |||
1461 | cs4215_setdata(dbri, 0); | ||
1462 | } | ||
1463 | |||
1464 | /* | ||
1465 | * Send the control information (i.e. audio format) | ||
1466 | */ | ||
1467 | static int cs4215_setctrl(snd_dbri_t * dbri) | ||
1468 | { | ||
1469 | int i, val; | ||
1470 | u32 tmp; | ||
1471 | |||
1472 | /* FIXME - let the CPU do something useful during these delays */ | ||
1473 | |||
1474 | /* Temporarily mute outputs, and wait 1/8000 sec (125 us) | ||
1475 | * to make sure this takes. This avoids clicking noises. | ||
1476 | */ | ||
1477 | |||
1478 | cs4215_setdata(dbri, 1); | ||
1479 | udelay(125); | ||
1480 | |||
1481 | /* | ||
1482 | * Enable Control mode: Set DBRI's PIO3 (4215's D/~C) to 0, then wait | ||
1483 | * 12 cycles <= 12/(5512.5*64) sec = 34.01 usec | ||
1484 | */ | ||
1485 | val = D_ENPIO | D_PIO1 | (dbri->mm.onboard ? D_PIO0 : D_PIO2); | ||
1486 | sbus_writel(val, dbri->regs + REG2); | ||
1487 | dprintk(D_MM, "cs4215_setctrl: reg2=0x%x\n", val); | ||
1488 | udelay(34); | ||
1489 | |||
1490 | /* In Control mode, the CS4215 is a slave device, so the DBRI must | ||
1491 | * operate as CHI master, supplying clocking and frame synchronization. | ||
1492 | * | ||
1493 | * In Data mode, however, the CS4215 must be CHI master to insure | ||
1494 | * that its data stream is synchronous with its codec. | ||
1495 | * | ||
1496 | * The upshot of all this? We start by putting the DBRI into master | ||
1497 | * mode, program the CS4215 in Control mode, then switch the CS4215 | ||
1498 | * into Data mode and put the DBRI into slave mode. Various timing | ||
1499 | * requirements must be observed along the way. | ||
1500 | * | ||
1501 | * Oh, and one more thing, on a SPARCStation 20 (and maybe | ||
1502 | * others?), the addressing of the CS4215's time slots is | ||
1503 | * offset by eight bits, so we add eight to all the "cycle" | ||
1504 | * values in the Define Time Slot (DTS) commands. This is | ||
1505 | * done in hardware by a TI 248 that delays the DBRI->4215 | ||
1506 | * frame sync signal by eight clock cycles. Anybody know why? | ||
1507 | */ | ||
1508 | tmp = sbus_readl(dbri->regs + REG0); | ||
1509 | tmp &= ~D_C; /* Disable CHI */ | ||
1510 | sbus_writel(tmp, dbri->regs + REG0); | ||
1511 | |||
1512 | reset_chi(dbri, CHImaster, 128); | ||
1513 | |||
1514 | /* | ||
1515 | * Control mode: | ||
1516 | * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly) | ||
1517 | * Pipe 18: Receive timeslot 1 (clb). | ||
1518 | * Pipe 19: Receive timeslot 7 (version). | ||
1519 | */ | ||
1520 | |||
1521 | link_time_slot(dbri, 17, PIPEoutput, 16, 32, dbri->mm.offset); | ||
1522 | link_time_slot(dbri, 18, PIPEinput, 16, 8, dbri->mm.offset); | ||
1523 | link_time_slot(dbri, 19, PIPEinput, 16, 8, dbri->mm.offset + 48); | ||
1524 | |||
1525 | /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */ | ||
1526 | dbri->mm.ctrl[0] &= ~CS4215_CLB; | ||
1527 | xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); | ||
1528 | |||
1529 | tmp = sbus_readl(dbri->regs + REG0); | ||
1530 | tmp |= D_C; /* Enable CHI */ | ||
1531 | sbus_writel(tmp, dbri->regs + REG0); | ||
1532 | |||
1533 | for (i = 64; ((dbri->mm.status & 0xe4) != 0x20); --i) { | ||
1534 | udelay(125); | ||
1535 | } | ||
1536 | if (i == 0) { | ||
1537 | dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n", | ||
1538 | dbri->mm.status); | ||
1539 | return -1; | ||
1540 | } | ||
1541 | |||
1542 | /* Disable changes to our copy of the version number, as we are about | ||
1543 | * to leave control mode. | ||
1544 | */ | ||
1545 | recv_fixed(dbri, 19, NULL); | ||
1546 | |||
1547 | /* Terminate CS4215 control mode - data sheet says | ||
1548 | * "Set CLB=1 and send two more frames of valid control info" | ||
1549 | */ | ||
1550 | dbri->mm.ctrl[0] |= CS4215_CLB; | ||
1551 | xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); | ||
1552 | |||
1553 | /* Two frames of control info @ 8kHz frame rate = 250 us delay */ | ||
1554 | udelay(250); | ||
1555 | |||
1556 | cs4215_setdata(dbri, 0); | ||
1557 | |||
1558 | return 0; | ||
1559 | } | ||
1560 | |||
1561 | /* | ||
1562 | * Setup the codec with the sampling rate, audio format and number of | ||
1563 | * channels. | ||
1564 | * As part of the process we resend the settings for the data | ||
1565 | * timeslots as well. | ||
1566 | */ | ||
1567 | static int cs4215_prepare(snd_dbri_t * dbri, unsigned int rate, | ||
1568 | snd_pcm_format_t format, unsigned int channels) | ||
1569 | { | ||
1570 | int freq_idx; | ||
1571 | int ret = 0; | ||
1572 | |||
1573 | /* Lookup index for this rate */ | ||
1574 | for (freq_idx = 0; CS4215_FREQ[freq_idx].freq != 0; freq_idx++) { | ||
1575 | if (CS4215_FREQ[freq_idx].freq == rate) | ||
1576 | break; | ||
1577 | } | ||
1578 | if (CS4215_FREQ[freq_idx].freq != rate) { | ||
1579 | printk(KERN_WARNING "DBRI: Unsupported rate %d Hz\n", rate); | ||
1580 | return -1; | ||
1581 | } | ||
1582 | |||
1583 | switch (format) { | ||
1584 | case SNDRV_PCM_FORMAT_MU_LAW: | ||
1585 | dbri->mm.ctrl[1] = CS4215_DFR_ULAW; | ||
1586 | dbri->mm.precision = 8; | ||
1587 | break; | ||
1588 | case SNDRV_PCM_FORMAT_A_LAW: | ||
1589 | dbri->mm.ctrl[1] = CS4215_DFR_ALAW; | ||
1590 | dbri->mm.precision = 8; | ||
1591 | break; | ||
1592 | case SNDRV_PCM_FORMAT_U8: | ||
1593 | dbri->mm.ctrl[1] = CS4215_DFR_LINEAR8; | ||
1594 | dbri->mm.precision = 8; | ||
1595 | break; | ||
1596 | case SNDRV_PCM_FORMAT_S16_BE: | ||
1597 | dbri->mm.ctrl[1] = CS4215_DFR_LINEAR16; | ||
1598 | dbri->mm.precision = 16; | ||
1599 | break; | ||
1600 | default: | ||
1601 | printk(KERN_WARNING "DBRI: Unsupported format %d\n", format); | ||
1602 | return -1; | ||
1603 | } | ||
1604 | |||
1605 | /* Add rate parameters */ | ||
1606 | dbri->mm.ctrl[1] |= CS4215_FREQ[freq_idx].csval; | ||
1607 | dbri->mm.ctrl[2] = CS4215_XCLK | | ||
1608 | CS4215_BSEL_128 | CS4215_FREQ[freq_idx].xtal; | ||
1609 | |||
1610 | dbri->mm.channels = channels; | ||
1611 | /* Stereo bit: 8 bit stereo not working yet. */ | ||
1612 | if ((channels > 1) && (dbri->mm.precision == 16)) | ||
1613 | dbri->mm.ctrl[1] |= CS4215_DFR_STEREO; | ||
1614 | |||
1615 | ret = cs4215_setctrl(dbri); | ||
1616 | if (ret == 0) | ||
1617 | cs4215_open(dbri); /* set codec to data mode */ | ||
1618 | |||
1619 | return ret; | ||
1620 | } | ||
1621 | |||
1622 | /* | ||
1623 | * | ||
1624 | */ | ||
1625 | static int cs4215_init(snd_dbri_t * dbri) | ||
1626 | { | ||
1627 | u32 reg2 = sbus_readl(dbri->regs + REG2); | ||
1628 | dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2); | ||
1629 | |||
1630 | /* Look for the cs4215 chips */ | ||
1631 | if (reg2 & D_PIO2) { | ||
1632 | dprintk(D_MM, "Onboard CS4215 detected\n"); | ||
1633 | dbri->mm.onboard = 1; | ||
1634 | } | ||
1635 | if (reg2 & D_PIO0) { | ||
1636 | dprintk(D_MM, "Speakerbox detected\n"); | ||
1637 | dbri->mm.onboard = 0; | ||
1638 | |||
1639 | if (reg2 & D_PIO2) { | ||
1640 | printk(KERN_INFO "DBRI: Using speakerbox / " | ||
1641 | "ignoring onboard mmcodec.\n"); | ||
1642 | sbus_writel(D_ENPIO2, dbri->regs + REG2); | ||
1643 | } | ||
1644 | } | ||
1645 | |||
1646 | if (!(reg2 & (D_PIO0 | D_PIO2))) { | ||
1647 | printk(KERN_ERR "DBRI: no mmcodec found.\n"); | ||
1648 | return -EIO; | ||
1649 | } | ||
1650 | |||
1651 | cs4215_setup_pipes(dbri); | ||
1652 | |||
1653 | cs4215_init_data(&dbri->mm); | ||
1654 | |||
1655 | /* Enable capture of the status & version timeslots. */ | ||
1656 | recv_fixed(dbri, 18, &dbri->mm.status); | ||
1657 | recv_fixed(dbri, 19, &dbri->mm.version); | ||
1658 | |||
1659 | dbri->mm.offset = dbri->mm.onboard ? 0 : 8; | ||
1660 | if (cs4215_setctrl(dbri) == -1 || dbri->mm.version == 0xff) { | ||
1661 | dprintk(D_MM, "CS4215 failed probe at offset %d\n", | ||
1662 | dbri->mm.offset); | ||
1663 | return -EIO; | ||
1664 | } | ||
1665 | dprintk(D_MM, "Found CS4215 at offset %d\n", dbri->mm.offset); | ||
1666 | |||
1667 | return 0; | ||
1668 | } | ||
1669 | |||
1670 | /* | ||
1671 | **************************************************************************** | ||
1672 | *************************** DBRI interrupt handler ************************* | ||
1673 | **************************************************************************** | ||
1674 | |||
1675 | The DBRI communicates with the CPU mainly via a circular interrupt | ||
1676 | buffer. When an interrupt is signaled, the CPU walks through the | ||
1677 | buffer and calls dbri_process_one_interrupt() for each interrupt word. | ||
1678 | Complicated interrupts are handled by dedicated functions (which | ||
1679 | appear first in this file). Any pending interrupts can be serviced by | ||
1680 | calling dbri_process_interrupt_buffer(), which works even if the CPU's | ||
1681 | interrupts are disabled. This function is used by dbri_cmdsend() | ||
1682 | to make sure we're synced up with the chip after each command sequence, | ||
1683 | even if we're running cli'ed. | ||
1684 | |||
1685 | */ | ||
1686 | |||
1687 | /* xmit_descs() | ||
1688 | * | ||
1689 | * Transmit the current TD's for recording/playing, if needed. | ||
1690 | * For playback, ALSA has filled the DMA memory with new data (we hope). | ||
1691 | */ | ||
1692 | static void xmit_descs(unsigned long data) | ||
1693 | { | ||
1694 | snd_dbri_t *dbri = (snd_dbri_t *) data; | ||
1695 | dbri_streaminfo_t *info; | ||
1696 | volatile s32 *cmd; | ||
1697 | unsigned long flags; | ||
1698 | int first_td; | ||
1699 | |||
1700 | if (dbri == NULL) | ||
1701 | return; /* Disabled */ | ||
1702 | |||
1703 | /* First check the recording stream for buffer overflow */ | ||
1704 | info = &dbri->stream_info[DBRI_REC]; | ||
1705 | spin_lock_irqsave(&dbri->lock, flags); | ||
1706 | |||
1707 | if ((info->left >= info->size) && (info->pipe >= 0)) { | ||
1708 | first_td = dbri->pipes[info->pipe].first_desc; | ||
1709 | |||
1710 | dprintk(D_DESC, "xmit_descs rec @ TD %d\n", first_td); | ||
1711 | |||
1712 | /* Stream could be closed by the time we run. */ | ||
1713 | if (first_td < 0) { | ||
1714 | goto play; | ||
1715 | } | ||
1716 | |||
1717 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
1718 | *(cmd++) = DBRI_CMD(D_SDP, 0, | ||
1719 | dbri->pipes[info->pipe].sdp | ||
1720 | | D_SDP_P | D_SDP_EVERY | D_SDP_C); | ||
1721 | *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); | ||
1722 | dbri_cmdsend(dbri, cmd); | ||
1723 | |||
1724 | /* Reset our admin of the pipe & bytes read. */ | ||
1725 | dbri->pipes[info->pipe].desc = first_td; | ||
1726 | info->left = 0; | ||
1727 | } | ||
1728 | |||
1729 | play: | ||
1730 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1731 | |||
1732 | /* Now check the playback stream for buffer underflow */ | ||
1733 | info = &dbri->stream_info[DBRI_PLAY]; | ||
1734 | spin_lock_irqsave(&dbri->lock, flags); | ||
1735 | |||
1736 | if ((info->left <= 0) && (info->pipe >= 0)) { | ||
1737 | first_td = dbri->pipes[info->pipe].first_desc; | ||
1738 | |||
1739 | dprintk(D_DESC, "xmit_descs play @ TD %d\n", first_td); | ||
1740 | |||
1741 | /* Stream could be closed by the time we run. */ | ||
1742 | if (first_td < 0) { | ||
1743 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1744 | return; | ||
1745 | } | ||
1746 | |||
1747 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
1748 | *(cmd++) = DBRI_CMD(D_SDP, 0, | ||
1749 | dbri->pipes[info->pipe].sdp | ||
1750 | | D_SDP_P | D_SDP_EVERY | D_SDP_C); | ||
1751 | *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); | ||
1752 | dbri_cmdsend(dbri, cmd); | ||
1753 | |||
1754 | /* Reset our admin of the pipe & bytes written. */ | ||
1755 | dbri->pipes[info->pipe].desc = first_td; | ||
1756 | info->left = info->size; | ||
1757 | } | ||
1758 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
1759 | } | ||
1760 | |||
1761 | DECLARE_TASKLET(xmit_descs_task, xmit_descs, 0); | ||
1762 | |||
1763 | /* transmission_complete_intr() | ||
1764 | * | ||
1765 | * Called by main interrupt handler when DBRI signals transmission complete | ||
1766 | * on a pipe (interrupt triggered by the B bit in a transmit descriptor). | ||
1767 | * | ||
1768 | * Walks through the pipe's list of transmit buffer descriptors, releasing | ||
1769 | * each one's DMA buffer (if present), flagging the descriptor available, | ||
1770 | * and signaling its callback routine (if present), before proceeding | ||
1771 | * to the next one. Stops when the first descriptor is found without | ||
1772 | * TBC (Transmit Buffer Complete) set, or we've run through them all. | ||
1773 | */ | ||
1774 | |||
1775 | static void transmission_complete_intr(snd_dbri_t * dbri, int pipe) | ||
1776 | { | ||
1777 | dbri_streaminfo_t *info; | ||
1778 | int td; | ||
1779 | int status; | ||
1780 | |||
1781 | info = &dbri->stream_info[DBRI_PLAY]; | ||
1782 | |||
1783 | td = dbri->pipes[pipe].desc; | ||
1784 | while (td >= 0) { | ||
1785 | if (td >= DBRI_NO_DESCS) { | ||
1786 | printk(KERN_ERR "DBRI: invalid td on pipe %d\n", pipe); | ||
1787 | return; | ||
1788 | } | ||
1789 | |||
1790 | status = DBRI_TD_STATUS(dbri->dma->desc[td].word4); | ||
1791 | if (!(status & DBRI_TD_TBC)) { | ||
1792 | break; | ||
1793 | } | ||
1794 | |||
1795 | dprintk(D_INT, "TD %d, status 0x%02x\n", td, status); | ||
1796 | |||
1797 | dbri->dma->desc[td].word4 = 0; /* Reset it for next time. */ | ||
1798 | info->offset += dbri->descs[td].len; | ||
1799 | info->left -= dbri->descs[td].len; | ||
1800 | |||
1801 | /* On the last TD, transmit them all again. */ | ||
1802 | if (dbri->descs[td].next == -1) { | ||
1803 | if (info->left > 0) { | ||
1804 | printk(KERN_WARNING | ||
1805 | "%d bytes left after last transfer.\n", | ||
1806 | info->left); | ||
1807 | info->left = 0; | ||
1808 | } | ||
1809 | tasklet_schedule(&xmit_descs_task); | ||
1810 | } | ||
1811 | |||
1812 | td = dbri->descs[td].next; | ||
1813 | dbri->pipes[pipe].desc = td; | ||
1814 | } | ||
1815 | |||
1816 | /* Notify ALSA */ | ||
1817 | if (spin_is_locked(&dbri->lock)) { | ||
1818 | spin_unlock(&dbri->lock); | ||
1819 | snd_pcm_period_elapsed(info->substream); | ||
1820 | spin_lock(&dbri->lock); | ||
1821 | } else | ||
1822 | snd_pcm_period_elapsed(info->substream); | ||
1823 | } | ||
1824 | |||
1825 | static void reception_complete_intr(snd_dbri_t * dbri, int pipe) | ||
1826 | { | ||
1827 | dbri_streaminfo_t *info; | ||
1828 | int rd = dbri->pipes[pipe].desc; | ||
1829 | s32 status; | ||
1830 | |||
1831 | if (rd < 0 || rd >= DBRI_NO_DESCS) { | ||
1832 | printk(KERN_ERR "DBRI: invalid rd on pipe %d\n", pipe); | ||
1833 | return; | ||
1834 | } | ||
1835 | |||
1836 | dbri->descs[rd].inuse = 0; | ||
1837 | dbri->pipes[pipe].desc = dbri->descs[rd].next; | ||
1838 | status = dbri->dma->desc[rd].word1; | ||
1839 | dbri->dma->desc[rd].word1 = 0; /* Reset it for next time. */ | ||
1840 | |||
1841 | info = &dbri->stream_info[DBRI_REC]; | ||
1842 | info->offset += DBRI_RD_CNT(status); | ||
1843 | info->left += DBRI_RD_CNT(status); | ||
1844 | |||
1845 | /* FIXME: Check status */ | ||
1846 | |||
1847 | dprintk(D_INT, "Recv RD %d, status 0x%02x, len %d\n", | ||
1848 | rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status)); | ||
1849 | |||
1850 | /* On the last TD, transmit them all again. */ | ||
1851 | if (dbri->descs[rd].next == -1) { | ||
1852 | if (info->left > info->size) { | ||
1853 | printk(KERN_WARNING | ||
1854 | "%d bytes recorded in %d size buffer.\n", | ||
1855 | info->left, info->size); | ||
1856 | } | ||
1857 | tasklet_schedule(&xmit_descs_task); | ||
1858 | } | ||
1859 | |||
1860 | /* Notify ALSA */ | ||
1861 | if (spin_is_locked(&dbri->lock)) { | ||
1862 | spin_unlock(&dbri->lock); | ||
1863 | snd_pcm_period_elapsed(info->substream); | ||
1864 | spin_lock(&dbri->lock); | ||
1865 | } else | ||
1866 | snd_pcm_period_elapsed(info->substream); | ||
1867 | } | ||
1868 | |||
1869 | static void dbri_process_one_interrupt(snd_dbri_t * dbri, int x) | ||
1870 | { | ||
1871 | int val = D_INTR_GETVAL(x); | ||
1872 | int channel = D_INTR_GETCHAN(x); | ||
1873 | int command = D_INTR_GETCMD(x); | ||
1874 | int code = D_INTR_GETCODE(x); | ||
1875 | #ifdef DBRI_DEBUG | ||
1876 | int rval = D_INTR_GETRVAL(x); | ||
1877 | #endif | ||
1878 | |||
1879 | if (channel == D_INTR_CMD) { | ||
1880 | dprintk(D_CMD, "INTR: Command: %-5s Value:%d\n", | ||
1881 | cmds[command], val); | ||
1882 | } else { | ||
1883 | dprintk(D_INT, "INTR: Chan:%d Code:%d Val:%#x\n", | ||
1884 | channel, code, rval); | ||
1885 | } | ||
1886 | |||
1887 | if (channel == D_INTR_CMD && command == D_WAIT) { | ||
1888 | dbri->wait_seen++; | ||
1889 | return; | ||
1890 | } | ||
1891 | |||
1892 | switch (code) { | ||
1893 | case D_INTR_BRDY: | ||
1894 | reception_complete_intr(dbri, channel); | ||
1895 | break; | ||
1896 | case D_INTR_XCMP: | ||
1897 | case D_INTR_MINT: | ||
1898 | transmission_complete_intr(dbri, channel); | ||
1899 | break; | ||
1900 | case D_INTR_UNDR: | ||
1901 | /* UNDR - Transmission underrun | ||
1902 | * resend SDP command with clear pipe bit (C) set | ||
1903 | */ | ||
1904 | { | ||
1905 | volatile s32 *cmd; | ||
1906 | |||
1907 | int pipe = channel; | ||
1908 | int td = dbri->pipes[pipe].desc; | ||
1909 | |||
1910 | dbri->dma->desc[td].word4 = 0; | ||
1911 | cmd = dbri_cmdlock(dbri, NoGetLock); | ||
1912 | *(cmd++) = DBRI_CMD(D_SDP, 0, | ||
1913 | dbri->pipes[pipe].sdp | ||
1914 | | D_SDP_P | D_SDP_C | D_SDP_2SAME); | ||
1915 | *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, td); | ||
1916 | dbri_cmdsend(dbri, cmd); | ||
1917 | } | ||
1918 | break; | ||
1919 | case D_INTR_FXDT: | ||
1920 | /* FXDT - Fixed data change */ | ||
1921 | if (dbri->pipes[channel].sdp & D_SDP_MSB) | ||
1922 | val = reverse_bytes(val, dbri->pipes[channel].length); | ||
1923 | |||
1924 | if (dbri->pipes[channel].recv_fixed_ptr) | ||
1925 | *(dbri->pipes[channel].recv_fixed_ptr) = val; | ||
1926 | break; | ||
1927 | default: | ||
1928 | if (channel != D_INTR_CMD) | ||
1929 | printk(KERN_WARNING | ||
1930 | "DBRI: Ignored Interrupt: %d (0x%x)\n", code, x); | ||
1931 | } | ||
1932 | } | ||
1933 | |||
1934 | /* dbri_process_interrupt_buffer advances through the DBRI's interrupt | ||
1935 | * buffer until it finds a zero word (indicating nothing more to do | ||
1936 | * right now). Non-zero words require processing and are handed off | ||
1937 | * to dbri_process_one_interrupt AFTER advancing the pointer. This | ||
1938 | * order is important since we might recurse back into this function | ||
1939 | * and need to make sure the pointer has been advanced first. | ||
1940 | */ | ||
1941 | static void dbri_process_interrupt_buffer(snd_dbri_t * dbri) | ||
1942 | { | ||
1943 | s32 x; | ||
1944 | |||
1945 | while ((x = dbri->dma->intr[dbri->dbri_irqp]) != 0) { | ||
1946 | dbri->dma->intr[dbri->dbri_irqp] = 0; | ||
1947 | dbri->dbri_irqp++; | ||
1948 | if (dbri->dbri_irqp == (DBRI_NO_INTS * DBRI_INT_BLK)) | ||
1949 | dbri->dbri_irqp = 1; | ||
1950 | else if ((dbri->dbri_irqp & (DBRI_INT_BLK - 1)) == 0) | ||
1951 | dbri->dbri_irqp++; | ||
1952 | |||
1953 | dbri_process_one_interrupt(dbri, x); | ||
1954 | } | ||
1955 | } | ||
1956 | |||
1957 | static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id, | ||
1958 | struct pt_regs *regs) | ||
1959 | { | ||
1960 | snd_dbri_t *dbri = dev_id; | ||
1961 | static int errcnt = 0; | ||
1962 | int x; | ||
1963 | |||
1964 | if (dbri == NULL) | ||
1965 | return IRQ_NONE; | ||
1966 | spin_lock(&dbri->lock); | ||
1967 | |||
1968 | /* | ||
1969 | * Read it, so the interrupt goes away. | ||
1970 | */ | ||
1971 | x = sbus_readl(dbri->regs + REG1); | ||
1972 | |||
1973 | if (x & (D_MRR | D_MLE | D_LBG | D_MBE)) { | ||
1974 | u32 tmp; | ||
1975 | |||
1976 | if (x & D_MRR) | ||
1977 | printk(KERN_ERR | ||
1978 | "DBRI: Multiple Error Ack on SBus reg1=0x%x\n", | ||
1979 | x); | ||
1980 | if (x & D_MLE) | ||
1981 | printk(KERN_ERR | ||
1982 | "DBRI: Multiple Late Error on SBus reg1=0x%x\n", | ||
1983 | x); | ||
1984 | if (x & D_LBG) | ||
1985 | printk(KERN_ERR | ||
1986 | "DBRI: Lost Bus Grant on SBus reg1=0x%x\n", x); | ||
1987 | if (x & D_MBE) | ||
1988 | printk(KERN_ERR | ||
1989 | "DBRI: Burst Error on SBus reg1=0x%x\n", x); | ||
1990 | |||
1991 | /* Some of these SBus errors cause the chip's SBus circuitry | ||
1992 | * to be disabled, so just re-enable and try to keep going. | ||
1993 | * | ||
1994 | * The only one I've seen is MRR, which will be triggered | ||
1995 | * if you let a transmit pipe underrun, then try to CDP it. | ||
1996 | * | ||
1997 | * If these things persist, we should probably reset | ||
1998 | * and re-init the chip. | ||
1999 | */ | ||
2000 | if ((++errcnt) % 10 == 0) { | ||
2001 | dprintk(D_INT, "Interrupt errors exceeded.\n"); | ||
2002 | dbri_reset(dbri); | ||
2003 | } else { | ||
2004 | tmp = sbus_readl(dbri->regs + REG0); | ||
2005 | tmp &= ~(D_D); | ||
2006 | sbus_writel(tmp, dbri->regs + REG0); | ||
2007 | } | ||
2008 | } | ||
2009 | |||
2010 | dbri_process_interrupt_buffer(dbri); | ||
2011 | |||
2012 | /* FIXME: Write 0 into regs to ACK interrupt */ | ||
2013 | |||
2014 | spin_unlock(&dbri->lock); | ||
2015 | |||
2016 | return IRQ_HANDLED; | ||
2017 | } | ||
2018 | |||
2019 | /**************************************************************************** | ||
2020 | PCM Interface | ||
2021 | ****************************************************************************/ | ||
2022 | static snd_pcm_hardware_t snd_dbri_pcm_hw = { | ||
2023 | .info = (SNDRV_PCM_INFO_MMAP | | ||
2024 | SNDRV_PCM_INFO_INTERLEAVED | | ||
2025 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
2026 | SNDRV_PCM_INFO_MMAP_VALID), | ||
2027 | .formats = SNDRV_PCM_FMTBIT_MU_LAW | | ||
2028 | SNDRV_PCM_FMTBIT_A_LAW | | ||
2029 | SNDRV_PCM_FMTBIT_U8 | | ||
2030 | SNDRV_PCM_FMTBIT_S16_BE, | ||
2031 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
2032 | .rate_min = 8000, | ||
2033 | .rate_max = 48000, | ||
2034 | .channels_min = 1, | ||
2035 | .channels_max = 2, | ||
2036 | .buffer_bytes_max = (64 * 1024), | ||
2037 | .period_bytes_min = 1, | ||
2038 | .period_bytes_max = DBRI_TD_MAXCNT, | ||
2039 | .periods_min = 1, | ||
2040 | .periods_max = 1024, | ||
2041 | }; | ||
2042 | |||
2043 | static int snd_dbri_open(snd_pcm_substream_t * substream) | ||
2044 | { | ||
2045 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2046 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
2047 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2048 | unsigned long flags; | ||
2049 | |||
2050 | dprintk(D_USR, "open audio output.\n"); | ||
2051 | runtime->hw = snd_dbri_pcm_hw; | ||
2052 | |||
2053 | spin_lock_irqsave(&dbri->lock, flags); | ||
2054 | info->substream = substream; | ||
2055 | info->left = 0; | ||
2056 | info->offset = 0; | ||
2057 | info->dvma_buffer = 0; | ||
2058 | info->pipe = -1; | ||
2059 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
2060 | |||
2061 | cs4215_open(dbri); | ||
2062 | |||
2063 | return 0; | ||
2064 | } | ||
2065 | |||
2066 | static int snd_dbri_close(snd_pcm_substream_t * substream) | ||
2067 | { | ||
2068 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2069 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2070 | |||
2071 | dprintk(D_USR, "close audio output.\n"); | ||
2072 | info->substream = NULL; | ||
2073 | info->left = 0; | ||
2074 | info->offset = 0; | ||
2075 | |||
2076 | return 0; | ||
2077 | } | ||
2078 | |||
2079 | static int snd_dbri_hw_params(snd_pcm_substream_t * substream, | ||
2080 | snd_pcm_hw_params_t * hw_params) | ||
2081 | { | ||
2082 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
2083 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2084 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2085 | int direction; | ||
2086 | int ret; | ||
2087 | |||
2088 | /* set sampling rate, audio format and number of channels */ | ||
2089 | ret = cs4215_prepare(dbri, params_rate(hw_params), | ||
2090 | params_format(hw_params), | ||
2091 | params_channels(hw_params)); | ||
2092 | if (ret != 0) | ||
2093 | return ret; | ||
2094 | |||
2095 | if ((ret = snd_pcm_lib_malloc_pages(substream, | ||
2096 | params_buffer_bytes(hw_params))) < 0) { | ||
2097 | snd_printk(KERN_ERR "malloc_pages failed with %d\n", ret); | ||
2098 | return ret; | ||
2099 | } | ||
2100 | |||
2101 | /* hw_params can get called multiple times. Only map the DMA once. | ||
2102 | */ | ||
2103 | if (info->dvma_buffer == 0) { | ||
2104 | if (DBRI_STREAMNO(substream) == DBRI_PLAY) | ||
2105 | direction = SBUS_DMA_TODEVICE; | ||
2106 | else | ||
2107 | direction = SBUS_DMA_FROMDEVICE; | ||
2108 | |||
2109 | info->dvma_buffer = sbus_map_single(dbri->sdev, | ||
2110 | runtime->dma_area, | ||
2111 | params_buffer_bytes(hw_params), | ||
2112 | direction); | ||
2113 | } | ||
2114 | |||
2115 | direction = params_buffer_bytes(hw_params); | ||
2116 | dprintk(D_USR, "hw_params: %d bytes, dvma=%x\n", | ||
2117 | direction, info->dvma_buffer); | ||
2118 | return 0; | ||
2119 | } | ||
2120 | |||
2121 | static int snd_dbri_hw_free(snd_pcm_substream_t * substream) | ||
2122 | { | ||
2123 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2124 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2125 | int direction; | ||
2126 | dprintk(D_USR, "hw_free.\n"); | ||
2127 | |||
2128 | /* hw_free can get called multiple times. Only unmap the DMA once. | ||
2129 | */ | ||
2130 | if (info->dvma_buffer) { | ||
2131 | if (DBRI_STREAMNO(substream) == DBRI_PLAY) | ||
2132 | direction = SBUS_DMA_TODEVICE; | ||
2133 | else | ||
2134 | direction = SBUS_DMA_FROMDEVICE; | ||
2135 | |||
2136 | sbus_unmap_single(dbri->sdev, info->dvma_buffer, | ||
2137 | substream->runtime->buffer_size, direction); | ||
2138 | info->dvma_buffer = 0; | ||
2139 | } | ||
2140 | info->pipe = -1; | ||
2141 | |||
2142 | return snd_pcm_lib_free_pages(substream); | ||
2143 | } | ||
2144 | |||
2145 | static int snd_dbri_prepare(snd_pcm_substream_t * substream) | ||
2146 | { | ||
2147 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2148 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2149 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
2150 | int ret; | ||
2151 | |||
2152 | info->size = snd_pcm_lib_buffer_bytes(substream); | ||
2153 | if (DBRI_STREAMNO(substream) == DBRI_PLAY) | ||
2154 | info->pipe = 4; /* Send pipe */ | ||
2155 | else { | ||
2156 | info->pipe = 6; /* Receive pipe */ | ||
2157 | info->left = info->size; /* To trigger submittal */ | ||
2158 | } | ||
2159 | |||
2160 | spin_lock_irq(&dbri->lock); | ||
2161 | |||
2162 | /* Setup the all the transmit/receive desciptors to cover the | ||
2163 | * whole DMA buffer. | ||
2164 | */ | ||
2165 | ret = setup_descs(dbri, DBRI_STREAMNO(substream), | ||
2166 | snd_pcm_lib_period_bytes(substream)); | ||
2167 | |||
2168 | runtime->stop_threshold = DBRI_TD_MAXCNT / runtime->channels; | ||
2169 | |||
2170 | spin_unlock_irq(&dbri->lock); | ||
2171 | |||
2172 | dprintk(D_USR, "prepare audio output. %d bytes\n", info->size); | ||
2173 | return ret; | ||
2174 | } | ||
2175 | |||
2176 | static int snd_dbri_trigger(snd_pcm_substream_t * substream, int cmd) | ||
2177 | { | ||
2178 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2179 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2180 | int ret = 0; | ||
2181 | |||
2182 | switch (cmd) { | ||
2183 | case SNDRV_PCM_TRIGGER_START: | ||
2184 | dprintk(D_USR, "start audio, period is %d bytes\n", | ||
2185 | (int)snd_pcm_lib_period_bytes(substream)); | ||
2186 | /* Enable & schedule the tasklet that re-submits the TDs. */ | ||
2187 | xmit_descs_task.data = (unsigned long)dbri; | ||
2188 | tasklet_schedule(&xmit_descs_task); | ||
2189 | break; | ||
2190 | case SNDRV_PCM_TRIGGER_STOP: | ||
2191 | dprintk(D_USR, "stop audio.\n"); | ||
2192 | /* Make the tasklet bail out immediately. */ | ||
2193 | xmit_descs_task.data = 0; | ||
2194 | reset_pipe(dbri, info->pipe); | ||
2195 | break; | ||
2196 | default: | ||
2197 | ret = -EINVAL; | ||
2198 | } | ||
2199 | |||
2200 | return ret; | ||
2201 | } | ||
2202 | |||
2203 | static snd_pcm_uframes_t snd_dbri_pointer(snd_pcm_substream_t * substream) | ||
2204 | { | ||
2205 | snd_dbri_t *dbri = snd_pcm_substream_chip(substream); | ||
2206 | dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream); | ||
2207 | snd_pcm_uframes_t ret; | ||
2208 | |||
2209 | ret = bytes_to_frames(substream->runtime, info->offset) | ||
2210 | % substream->runtime->buffer_size; | ||
2211 | dprintk(D_USR, "I/O pointer: %ld frames, %d bytes left.\n", | ||
2212 | ret, info->left); | ||
2213 | return ret; | ||
2214 | } | ||
2215 | |||
2216 | static snd_pcm_ops_t snd_dbri_ops = { | ||
2217 | .open = snd_dbri_open, | ||
2218 | .close = snd_dbri_close, | ||
2219 | .ioctl = snd_pcm_lib_ioctl, | ||
2220 | .hw_params = snd_dbri_hw_params, | ||
2221 | .hw_free = snd_dbri_hw_free, | ||
2222 | .prepare = snd_dbri_prepare, | ||
2223 | .trigger = snd_dbri_trigger, | ||
2224 | .pointer = snd_dbri_pointer, | ||
2225 | }; | ||
2226 | |||
2227 | static int __devinit snd_dbri_pcm(snd_dbri_t * dbri) | ||
2228 | { | ||
2229 | snd_pcm_t *pcm; | ||
2230 | int err; | ||
2231 | |||
2232 | if ((err = snd_pcm_new(dbri->card, | ||
2233 | /* ID */ "sun_dbri", | ||
2234 | /* device */ 0, | ||
2235 | /* playback count */ 1, | ||
2236 | /* capture count */ 1, &pcm)) < 0) | ||
2237 | return err; | ||
2238 | snd_assert(pcm != NULL, return -EINVAL); | ||
2239 | |||
2240 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops); | ||
2241 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops); | ||
2242 | |||
2243 | pcm->private_data = dbri; | ||
2244 | pcm->info_flags = 0; | ||
2245 | strcpy(pcm->name, dbri->card->shortname); | ||
2246 | dbri->pcm = pcm; | ||
2247 | |||
2248 | if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
2249 | SNDRV_DMA_TYPE_CONTINUOUS, | ||
2250 | snd_dma_continuous_data(GFP_KERNEL), | ||
2251 | 64 * 1024, 64 * 1024)) < 0) { | ||
2252 | return err; | ||
2253 | } | ||
2254 | |||
2255 | return 0; | ||
2256 | } | ||
2257 | |||
2258 | /***************************************************************************** | ||
2259 | Mixer interface | ||
2260 | *****************************************************************************/ | ||
2261 | |||
2262 | static int snd_cs4215_info_volume(snd_kcontrol_t * kcontrol, | ||
2263 | snd_ctl_elem_info_t * uinfo) | ||
2264 | { | ||
2265 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2266 | uinfo->count = 2; | ||
2267 | uinfo->value.integer.min = 0; | ||
2268 | if (kcontrol->private_value == DBRI_PLAY) { | ||
2269 | uinfo->value.integer.max = DBRI_MAX_VOLUME; | ||
2270 | } else { | ||
2271 | uinfo->value.integer.max = DBRI_MAX_GAIN; | ||
2272 | } | ||
2273 | return 0; | ||
2274 | } | ||
2275 | |||
2276 | static int snd_cs4215_get_volume(snd_kcontrol_t * kcontrol, | ||
2277 | snd_ctl_elem_value_t * ucontrol) | ||
2278 | { | ||
2279 | snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol); | ||
2280 | dbri_streaminfo_t *info; | ||
2281 | snd_assert(dbri != NULL, return -EINVAL); | ||
2282 | info = &dbri->stream_info[kcontrol->private_value]; | ||
2283 | snd_assert(info != NULL, return -EINVAL); | ||
2284 | |||
2285 | ucontrol->value.integer.value[0] = info->left_gain; | ||
2286 | ucontrol->value.integer.value[1] = info->right_gain; | ||
2287 | return 0; | ||
2288 | } | ||
2289 | |||
2290 | static int snd_cs4215_put_volume(snd_kcontrol_t * kcontrol, | ||
2291 | snd_ctl_elem_value_t * ucontrol) | ||
2292 | { | ||
2293 | snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol); | ||
2294 | dbri_streaminfo_t *info = &dbri->stream_info[kcontrol->private_value]; | ||
2295 | unsigned long flags; | ||
2296 | int changed = 0; | ||
2297 | |||
2298 | if (info->left_gain != ucontrol->value.integer.value[0]) { | ||
2299 | info->left_gain = ucontrol->value.integer.value[0]; | ||
2300 | changed = 1; | ||
2301 | } | ||
2302 | if (info->right_gain != ucontrol->value.integer.value[1]) { | ||
2303 | info->right_gain = ucontrol->value.integer.value[1]; | ||
2304 | changed = 1; | ||
2305 | } | ||
2306 | if (changed == 1) { | ||
2307 | /* First mute outputs, and wait 1/8000 sec (125 us) | ||
2308 | * to make sure this takes. This avoids clicking noises. | ||
2309 | */ | ||
2310 | spin_lock_irqsave(&dbri->lock, flags); | ||
2311 | |||
2312 | cs4215_setdata(dbri, 1); | ||
2313 | udelay(125); | ||
2314 | cs4215_setdata(dbri, 0); | ||
2315 | |||
2316 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
2317 | } | ||
2318 | return changed; | ||
2319 | } | ||
2320 | |||
2321 | static int snd_cs4215_info_single(snd_kcontrol_t * kcontrol, | ||
2322 | snd_ctl_elem_info_t * uinfo) | ||
2323 | { | ||
2324 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
2325 | |||
2326 | uinfo->type = (mask == 1) ? | ||
2327 | SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2328 | uinfo->count = 1; | ||
2329 | uinfo->value.integer.min = 0; | ||
2330 | uinfo->value.integer.max = mask; | ||
2331 | return 0; | ||
2332 | } | ||
2333 | |||
2334 | static int snd_cs4215_get_single(snd_kcontrol_t * kcontrol, | ||
2335 | snd_ctl_elem_value_t * ucontrol) | ||
2336 | { | ||
2337 | snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol); | ||
2338 | int elem = kcontrol->private_value & 0xff; | ||
2339 | int shift = (kcontrol->private_value >> 8) & 0xff; | ||
2340 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
2341 | int invert = (kcontrol->private_value >> 24) & 1; | ||
2342 | snd_assert(dbri != NULL, return -EINVAL); | ||
2343 | |||
2344 | if (elem < 4) { | ||
2345 | ucontrol->value.integer.value[0] = | ||
2346 | (dbri->mm.data[elem] >> shift) & mask; | ||
2347 | } else { | ||
2348 | ucontrol->value.integer.value[0] = | ||
2349 | (dbri->mm.ctrl[elem - 4] >> shift) & mask; | ||
2350 | } | ||
2351 | |||
2352 | if (invert == 1) { | ||
2353 | ucontrol->value.integer.value[0] = | ||
2354 | mask - ucontrol->value.integer.value[0]; | ||
2355 | } | ||
2356 | return 0; | ||
2357 | } | ||
2358 | |||
2359 | static int snd_cs4215_put_single(snd_kcontrol_t * kcontrol, | ||
2360 | snd_ctl_elem_value_t * ucontrol) | ||
2361 | { | ||
2362 | snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol); | ||
2363 | unsigned long flags; | ||
2364 | int elem = kcontrol->private_value & 0xff; | ||
2365 | int shift = (kcontrol->private_value >> 8) & 0xff; | ||
2366 | int mask = (kcontrol->private_value >> 16) & 0xff; | ||
2367 | int invert = (kcontrol->private_value >> 24) & 1; | ||
2368 | int changed = 0; | ||
2369 | unsigned short val; | ||
2370 | snd_assert(dbri != NULL, return -EINVAL); | ||
2371 | |||
2372 | val = (ucontrol->value.integer.value[0] & mask); | ||
2373 | if (invert == 1) | ||
2374 | val = mask - val; | ||
2375 | val <<= shift; | ||
2376 | |||
2377 | if (elem < 4) { | ||
2378 | dbri->mm.data[elem] = (dbri->mm.data[elem] & | ||
2379 | ~(mask << shift)) | val; | ||
2380 | changed = (val != dbri->mm.data[elem]); | ||
2381 | } else { | ||
2382 | dbri->mm.ctrl[elem - 4] = (dbri->mm.ctrl[elem - 4] & | ||
2383 | ~(mask << shift)) | val; | ||
2384 | changed = (val != dbri->mm.ctrl[elem - 4]); | ||
2385 | } | ||
2386 | |||
2387 | dprintk(D_GEN, "put_single: mask=0x%x, changed=%d, " | ||
2388 | "mixer-value=%ld, mm-value=0x%x\n", | ||
2389 | mask, changed, ucontrol->value.integer.value[0], | ||
2390 | dbri->mm.data[elem & 3]); | ||
2391 | |||
2392 | if (changed) { | ||
2393 | /* First mute outputs, and wait 1/8000 sec (125 us) | ||
2394 | * to make sure this takes. This avoids clicking noises. | ||
2395 | */ | ||
2396 | spin_lock_irqsave(&dbri->lock, flags); | ||
2397 | |||
2398 | cs4215_setdata(dbri, 1); | ||
2399 | udelay(125); | ||
2400 | cs4215_setdata(dbri, 0); | ||
2401 | |||
2402 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
2403 | } | ||
2404 | return changed; | ||
2405 | } | ||
2406 | |||
2407 | /* Entries 0-3 map to the 4 data timeslots, entries 4-7 map to the 4 control | ||
2408 | timeslots. Shift is the bit offset in the timeslot, mask defines the | ||
2409 | number of bits. invert is a boolean for use with attenuation. | ||
2410 | */ | ||
2411 | #define CS4215_SINGLE(xname, entry, shift, mask, invert) \ | ||
2412 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
2413 | .info = snd_cs4215_info_single, \ | ||
2414 | .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \ | ||
2415 | .private_value = entry | (shift << 8) | (mask << 16) | (invert << 24) }, | ||
2416 | |||
2417 | static snd_kcontrol_new_t dbri_controls[] __devinitdata = { | ||
2418 | { | ||
2419 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2420 | .name = "Playback Volume", | ||
2421 | .info = snd_cs4215_info_volume, | ||
2422 | .get = snd_cs4215_get_volume, | ||
2423 | .put = snd_cs4215_put_volume, | ||
2424 | .private_value = DBRI_PLAY, | ||
2425 | }, | ||
2426 | CS4215_SINGLE("Headphone switch", 0, 7, 1, 0) | ||
2427 | CS4215_SINGLE("Line out switch", 0, 6, 1, 0) | ||
2428 | CS4215_SINGLE("Speaker switch", 1, 6, 1, 0) | ||
2429 | { | ||
2430 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2431 | .name = "Capture Volume", | ||
2432 | .info = snd_cs4215_info_volume, | ||
2433 | .get = snd_cs4215_get_volume, | ||
2434 | .put = snd_cs4215_put_volume, | ||
2435 | .private_value = DBRI_REC, | ||
2436 | }, | ||
2437 | /* FIXME: mic/line switch */ | ||
2438 | CS4215_SINGLE("Line in switch", 2, 4, 1, 0) | ||
2439 | CS4215_SINGLE("High Pass Filter switch", 5, 7, 1, 0) | ||
2440 | CS4215_SINGLE("Monitor Volume", 3, 4, 0xf, 1) | ||
2441 | CS4215_SINGLE("Mic boost", 4, 4, 1, 1) | ||
2442 | }; | ||
2443 | |||
2444 | #define NUM_CS4215_CONTROLS (sizeof(dbri_controls)/sizeof(snd_kcontrol_new_t)) | ||
2445 | |||
2446 | static int __init snd_dbri_mixer(snd_dbri_t * dbri) | ||
2447 | { | ||
2448 | snd_card_t *card; | ||
2449 | int idx, err; | ||
2450 | |||
2451 | snd_assert(dbri != NULL && dbri->card != NULL, return -EINVAL); | ||
2452 | |||
2453 | card = dbri->card; | ||
2454 | strcpy(card->mixername, card->shortname); | ||
2455 | |||
2456 | for (idx = 0; idx < NUM_CS4215_CONTROLS; idx++) { | ||
2457 | if ((err = snd_ctl_add(card, | ||
2458 | snd_ctl_new1(&dbri_controls[idx], | ||
2459 | dbri))) < 0) | ||
2460 | return err; | ||
2461 | } | ||
2462 | |||
2463 | for (idx = DBRI_REC; idx < DBRI_NO_STREAMS; idx++) { | ||
2464 | dbri->stream_info[idx].left_gain = 0; | ||
2465 | dbri->stream_info[idx].right_gain = 0; | ||
2466 | dbri->stream_info[idx].balance = DBRI_MID_BALANCE; | ||
2467 | } | ||
2468 | |||
2469 | return 0; | ||
2470 | } | ||
2471 | |||
2472 | /**************************************************************************** | ||
2473 | /proc interface | ||
2474 | ****************************************************************************/ | ||
2475 | static void dbri_regs_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer) | ||
2476 | { | ||
2477 | snd_dbri_t *dbri = entry->private_data; | ||
2478 | |||
2479 | snd_iprintf(buffer, "REG0: 0x%x\n", sbus_readl(dbri->regs + REG0)); | ||
2480 | snd_iprintf(buffer, "REG2: 0x%x\n", sbus_readl(dbri->regs + REG2)); | ||
2481 | snd_iprintf(buffer, "REG8: 0x%x\n", sbus_readl(dbri->regs + REG8)); | ||
2482 | snd_iprintf(buffer, "REG9: 0x%x\n", sbus_readl(dbri->regs + REG9)); | ||
2483 | } | ||
2484 | |||
2485 | #ifdef DBRI_DEBUG | ||
2486 | static void dbri_debug_read(snd_info_entry_t * entry, | ||
2487 | snd_info_buffer_t * buffer) | ||
2488 | { | ||
2489 | snd_dbri_t *dbri = entry->private_data; | ||
2490 | int pipe; | ||
2491 | snd_iprintf(buffer, "debug=%d\n", dbri_debug); | ||
2492 | |||
2493 | snd_iprintf(buffer, "CHI pipe in=%d, out=%d\n", | ||
2494 | dbri->chi_in_pipe, dbri->chi_out_pipe); | ||
2495 | for (pipe = 0; pipe < 32; pipe++) { | ||
2496 | if (pipe_active(dbri, pipe)) { | ||
2497 | struct dbri_pipe *pptr = &dbri->pipes[pipe]; | ||
2498 | snd_iprintf(buffer, | ||
2499 | "Pipe %d: %s SDP=0x%x desc=%d, " | ||
2500 | "len=%d @ %d prev: %d next %d\n", | ||
2501 | pipe, | ||
2502 | (pptr->direction == | ||
2503 | PIPEinput ? "input" : "output"), pptr->sdp, | ||
2504 | pptr->desc, pptr->length, pptr->cycle, | ||
2505 | pptr->prevpipe, pptr->nextpipe); | ||
2506 | } | ||
2507 | } | ||
2508 | } | ||
2509 | |||
2510 | static void dbri_debug_write(snd_info_entry_t * entry, | ||
2511 | snd_info_buffer_t * buffer) | ||
2512 | { | ||
2513 | char line[80]; | ||
2514 | int i; | ||
2515 | |||
2516 | if (snd_info_get_line(buffer, line, 80) == 0) { | ||
2517 | sscanf(line, "%d\n", &i); | ||
2518 | dbri_debug = i & 0x3f; | ||
2519 | } | ||
2520 | } | ||
2521 | #endif | ||
2522 | |||
2523 | void snd_dbri_proc(snd_dbri_t * dbri) | ||
2524 | { | ||
2525 | snd_info_entry_t *entry; | ||
2526 | int err; | ||
2527 | |||
2528 | err = snd_card_proc_new(dbri->card, "regs", &entry); | ||
2529 | snd_info_set_text_ops(entry, dbri, 1024, dbri_regs_read); | ||
2530 | |||
2531 | #ifdef DBRI_DEBUG | ||
2532 | err = snd_card_proc_new(dbri->card, "debug", &entry); | ||
2533 | snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read); | ||
2534 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; /* Writable for root */ | ||
2535 | entry->c.text.write_size = 256; | ||
2536 | entry->c.text.write = dbri_debug_write; | ||
2537 | #endif | ||
2538 | } | ||
2539 | |||
2540 | /* | ||
2541 | **************************************************************************** | ||
2542 | **************************** Initialization ******************************** | ||
2543 | **************************************************************************** | ||
2544 | */ | ||
2545 | static void snd_dbri_free(snd_dbri_t * dbri); | ||
2546 | |||
2547 | static int __init snd_dbri_create(snd_card_t * card, | ||
2548 | struct sbus_dev *sdev, | ||
2549 | struct linux_prom_irqs *irq, int dev) | ||
2550 | { | ||
2551 | snd_dbri_t *dbri = card->private_data; | ||
2552 | int err; | ||
2553 | |||
2554 | spin_lock_init(&dbri->lock); | ||
2555 | dbri->card = card; | ||
2556 | dbri->sdev = sdev; | ||
2557 | dbri->irq = irq->pri; | ||
2558 | dbri->dbri_version = sdev->prom_name[9]; | ||
2559 | |||
2560 | dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), | ||
2561 | &dbri->dma_dvma); | ||
2562 | memset((void *)dbri->dma, 0, sizeof(struct dbri_dma)); | ||
2563 | |||
2564 | dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n", | ||
2565 | dbri->dma, dbri->dma_dvma); | ||
2566 | |||
2567 | /* Map the registers into memory. */ | ||
2568 | dbri->regs_size = sdev->reg_addrs[0].reg_size; | ||
2569 | dbri->regs = sbus_ioremap(&sdev->resource[0], 0, | ||
2570 | dbri->regs_size, "DBRI Registers"); | ||
2571 | if (!dbri->regs) { | ||
2572 | printk(KERN_ERR "DBRI: could not allocate registers\n"); | ||
2573 | sbus_free_consistent(sdev, sizeof(struct dbri_dma), | ||
2574 | (void *)dbri->dma, dbri->dma_dvma); | ||
2575 | return -EIO; | ||
2576 | } | ||
2577 | |||
2578 | err = request_irq(dbri->irq, snd_dbri_interrupt, SA_SHIRQ, | ||
2579 | "DBRI audio", dbri); | ||
2580 | if (err) { | ||
2581 | printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq); | ||
2582 | sbus_iounmap(dbri->regs, dbri->regs_size); | ||
2583 | sbus_free_consistent(sdev, sizeof(struct dbri_dma), | ||
2584 | (void *)dbri->dma, dbri->dma_dvma); | ||
2585 | return err; | ||
2586 | } | ||
2587 | |||
2588 | /* Do low level initialization of the DBRI and CS4215 chips */ | ||
2589 | dbri_initialize(dbri); | ||
2590 | err = cs4215_init(dbri); | ||
2591 | if (err) { | ||
2592 | snd_dbri_free(dbri); | ||
2593 | return err; | ||
2594 | } | ||
2595 | |||
2596 | dbri->next = dbri_list; | ||
2597 | dbri_list = dbri; | ||
2598 | |||
2599 | return 0; | ||
2600 | } | ||
2601 | |||
2602 | static void snd_dbri_free(snd_dbri_t * dbri) | ||
2603 | { | ||
2604 | dprintk(D_GEN, "snd_dbri_free\n"); | ||
2605 | dbri_reset(dbri); | ||
2606 | |||
2607 | if (dbri->irq) | ||
2608 | free_irq(dbri->irq, dbri); | ||
2609 | |||
2610 | if (dbri->regs) | ||
2611 | sbus_iounmap(dbri->regs, dbri->regs_size); | ||
2612 | |||
2613 | if (dbri->dma) | ||
2614 | sbus_free_consistent(dbri->sdev, sizeof(struct dbri_dma), | ||
2615 | (void *)dbri->dma, dbri->dma_dvma); | ||
2616 | } | ||
2617 | |||
2618 | static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) | ||
2619 | { | ||
2620 | snd_dbri_t *dbri; | ||
2621 | struct linux_prom_irqs irq; | ||
2622 | struct resource *rp; | ||
2623 | snd_card_t *card; | ||
2624 | static int dev = 0; | ||
2625 | int err; | ||
2626 | |||
2627 | if (sdev->prom_name[9] < 'e') { | ||
2628 | printk(KERN_ERR "DBRI: unsupported chip version %c found.\n", | ||
2629 | sdev->prom_name[9]); | ||
2630 | return -EIO; | ||
2631 | } | ||
2632 | |||
2633 | if (dev >= SNDRV_CARDS) | ||
2634 | return -ENODEV; | ||
2635 | if (!enable[dev]) { | ||
2636 | dev++; | ||
2637 | return -ENOENT; | ||
2638 | } | ||
2639 | |||
2640 | prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq)); | ||
2641 | |||
2642 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | ||
2643 | sizeof(snd_dbri_t)); | ||
2644 | if (card == NULL) | ||
2645 | return -ENOMEM; | ||
2646 | |||
2647 | strcpy(card->driver, "DBRI"); | ||
2648 | strcpy(card->shortname, "Sun DBRI"); | ||
2649 | rp = &sdev->resource[0]; | ||
2650 | sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s", | ||
2651 | card->shortname, | ||
2652 | rp->flags & 0xffL, rp->start, __irq_itoa(irq.pri)); | ||
2653 | |||
2654 | if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) { | ||
2655 | snd_card_free(card); | ||
2656 | return err; | ||
2657 | } | ||
2658 | |||
2659 | dbri = (snd_dbri_t *) card->private_data; | ||
2660 | if ((err = snd_dbri_pcm(dbri)) < 0) { | ||
2661 | snd_dbri_free(dbri); | ||
2662 | snd_card_free(card); | ||
2663 | return err; | ||
2664 | } | ||
2665 | |||
2666 | if ((err = snd_dbri_mixer(dbri)) < 0) { | ||
2667 | snd_dbri_free(dbri); | ||
2668 | snd_card_free(card); | ||
2669 | return err; | ||
2670 | } | ||
2671 | |||
2672 | /* /proc file handling */ | ||
2673 | snd_dbri_proc(dbri); | ||
2674 | |||
2675 | if ((err = snd_card_register(card)) < 0) { | ||
2676 | snd_dbri_free(dbri); | ||
2677 | snd_card_free(card); | ||
2678 | return err; | ||
2679 | } | ||
2680 | |||
2681 | printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n", | ||
2682 | dev, dbri->regs, | ||
2683 | dbri->irq, dbri->dbri_version, dbri->mm.version); | ||
2684 | dev++; | ||
2685 | |||
2686 | return 0; | ||
2687 | } | ||
2688 | |||
2689 | /* Probe for the dbri chip and then attach the driver. */ | ||
2690 | static int __init dbri_init(void) | ||
2691 | { | ||
2692 | struct sbus_bus *sbus; | ||
2693 | struct sbus_dev *sdev; | ||
2694 | int found = 0; | ||
2695 | |||
2696 | /* Probe each SBUS for the DBRI chip(s). */ | ||
2697 | for_all_sbusdev(sdev, sbus) { | ||
2698 | /* | ||
2699 | * The version is coded in the last character | ||
2700 | */ | ||
2701 | if (!strncmp(sdev->prom_name, "SUNW,DBRI", 9)) { | ||
2702 | dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", | ||
2703 | sdev->prom_name, sdev->slot); | ||
2704 | |||
2705 | if (dbri_attach(sdev->prom_node, sdev) == 0) | ||
2706 | found++; | ||
2707 | } | ||
2708 | } | ||
2709 | |||
2710 | return (found > 0) ? 0 : -EIO; | ||
2711 | } | ||
2712 | |||
2713 | static void __exit dbri_exit(void) | ||
2714 | { | ||
2715 | snd_dbri_t *this = dbri_list; | ||
2716 | |||
2717 | while (this != NULL) { | ||
2718 | snd_dbri_t *next = this->next; | ||
2719 | snd_card_t *card = this->card; | ||
2720 | |||
2721 | snd_dbri_free(this); | ||
2722 | snd_card_free(card); | ||
2723 | this = next; | ||
2724 | } | ||
2725 | dbri_list = NULL; | ||
2726 | } | ||
2727 | |||
2728 | module_init(dbri_init); | ||
2729 | module_exit(dbri_exit); | ||
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index b5e734d975e0..8298c462c291 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -153,6 +153,7 @@ struct snd_usb_substream { | |||
153 | unsigned int format; /* USB data format */ | 153 | unsigned int format; /* USB data format */ |
154 | unsigned int datapipe; /* the data i/o pipe */ | 154 | unsigned int datapipe; /* the data i/o pipe */ |
155 | unsigned int syncpipe; /* 1 - async out or adaptive in */ | 155 | unsigned int syncpipe; /* 1 - async out or adaptive in */ |
156 | unsigned int datainterval; /* log_2 of data packet interval */ | ||
156 | unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ | 157 | unsigned int syncinterval; /* P for adaptive mode, 0 otherwise */ |
157 | unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */ | 158 | unsigned int freqn; /* nominal sampling rate in fs/fps in Q16.16 format */ |
158 | unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */ | 159 | unsigned int freqm; /* momentary sampling rate in fs/fps in Q16.16 format */ |
@@ -518,7 +519,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs, | |||
518 | if (subs->fill_max) | 519 | if (subs->fill_max) |
519 | counts = subs->maxframesize; /* fixed */ | 520 | counts = subs->maxframesize; /* fixed */ |
520 | else { | 521 | else { |
521 | subs->phase = (subs->phase & 0xffff) + subs->freqm; | 522 | subs->phase = (subs->phase & 0xffff) |
523 | + (subs->freqm << subs->datainterval); | ||
522 | counts = subs->phase >> 16; | 524 | counts = subs->phase >> 16; |
523 | if (counts > subs->maxframesize) | 525 | if (counts > subs->maxframesize) |
524 | counts = subs->maxframesize; | 526 | counts = subs->maxframesize; |
@@ -790,7 +792,7 @@ static int start_urbs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime) | |||
790 | */ | 792 | */ |
791 | static int wait_clear_urbs(snd_usb_substream_t *subs) | 793 | static int wait_clear_urbs(snd_usb_substream_t *subs) |
792 | { | 794 | { |
793 | int timeout = HZ; | 795 | unsigned long end_time = jiffies + msecs_to_jiffies(1000); |
794 | unsigned int i; | 796 | unsigned int i; |
795 | int alive; | 797 | int alive; |
796 | 798 | ||
@@ -810,7 +812,7 @@ static int wait_clear_urbs(snd_usb_substream_t *subs) | |||
810 | break; | 812 | break; |
811 | set_current_state(TASK_UNINTERRUPTIBLE); | 813 | set_current_state(TASK_UNINTERRUPTIBLE); |
812 | schedule_timeout(1); | 814 | schedule_timeout(1); |
813 | } while (--timeout > 0); | 815 | } while (time_before(jiffies, end_time)); |
814 | if (alive) | 816 | if (alive) |
815 | snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); | 817 | snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); |
816 | return 0; | 818 | return 0; |
@@ -899,16 +901,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
899 | else | 901 | else |
900 | subs->freqn = get_usb_high_speed_rate(rate); | 902 | subs->freqn = get_usb_high_speed_rate(rate); |
901 | subs->freqm = subs->freqn; | 903 | subs->freqm = subs->freqn; |
902 | subs->freqmax = subs->freqn + (subs->freqn >> 2); /* max. allowed frequency */ | 904 | /* calculate max. frequency */ |
903 | subs->phase = 0; | 905 | if (subs->maxpacksize) { |
904 | 906 | /* whatever fits into a max. size packet */ | |
905 | /* calculate the max. size of packet */ | ||
906 | maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) >> 16; | ||
907 | if (subs->maxpacksize && maxsize > subs->maxpacksize) { | ||
908 | //snd_printd(KERN_DEBUG "maxsize %d is greater than defined size %d\n", | ||
909 | // maxsize, subs->maxpacksize); | ||
910 | maxsize = subs->maxpacksize; | 907 | maxsize = subs->maxpacksize; |
908 | subs->freqmax = (maxsize / (frame_bits >> 3)) | ||
909 | << (16 - subs->datainterval); | ||
910 | } else { | ||
911 | /* no max. packet size: just take 25% higher than nominal */ | ||
912 | subs->freqmax = subs->freqn + (subs->freqn >> 2); | ||
913 | maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3)) | ||
914 | >> (16 - subs->datainterval); | ||
911 | } | 915 | } |
916 | subs->phase = 0; | ||
912 | 917 | ||
913 | if (subs->fill_max) | 918 | if (subs->fill_max) |
914 | subs->curpacksize = subs->maxpacksize; | 919 | subs->curpacksize = subs->maxpacksize; |
@@ -918,7 +923,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
918 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 923 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) |
919 | urb_packs = nrpacks; | 924 | urb_packs = nrpacks; |
920 | else | 925 | else |
921 | urb_packs = nrpacks * 8; | 926 | urb_packs = (nrpacks * 8) >> subs->datainterval; |
922 | 927 | ||
923 | /* allocate a temporary buffer for playback */ | 928 | /* allocate a temporary buffer for playback */ |
924 | if (is_playback) { | 929 | if (is_playback) { |
@@ -991,7 +996,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by | |||
991 | u->urb->pipe = subs->datapipe; | 996 | u->urb->pipe = subs->datapipe; |
992 | u->urb->transfer_flags = URB_ISO_ASAP; | 997 | u->urb->transfer_flags = URB_ISO_ASAP; |
993 | u->urb->number_of_packets = u->packets; | 998 | u->urb->number_of_packets = u->packets; |
994 | u->urb->interval = 1; | 999 | u->urb->interval = 1 << subs->datainterval; |
995 | u->urb->context = u; | 1000 | u->urb->context = u; |
996 | u->urb->complete = snd_usb_complete_callback(snd_complete_urb); | 1001 | u->urb->complete = snd_usb_complete_callback(snd_complete_urb); |
997 | } | 1002 | } |
@@ -1195,6 +1200,12 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt) | |||
1195 | subs->datapipe = usb_sndisocpipe(dev, ep); | 1200 | subs->datapipe = usb_sndisocpipe(dev, ep); |
1196 | else | 1201 | else |
1197 | subs->datapipe = usb_rcvisocpipe(dev, ep); | 1202 | subs->datapipe = usb_rcvisocpipe(dev, ep); |
1203 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH && | ||
1204 | get_endpoint(alts, 0)->bInterval >= 1 && | ||
1205 | get_endpoint(alts, 0)->bInterval <= 4) | ||
1206 | subs->datainterval = get_endpoint(alts, 0)->bInterval - 1; | ||
1207 | else | ||
1208 | subs->datainterval = 0; | ||
1198 | subs->syncpipe = subs->syncinterval = 0; | 1209 | subs->syncpipe = subs->syncinterval = 0; |
1199 | subs->maxpacksize = fmt->maxpacksize; | 1210 | subs->maxpacksize = fmt->maxpacksize; |
1200 | subs->fill_max = 0; | 1211 | subs->fill_max = 0; |
@@ -2397,10 +2408,9 @@ static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp, | |||
2397 | if (chip->usb_id == USB_ID(0x041e, 0x3000) || | 2408 | if (chip->usb_id == USB_ID(0x041e, 0x3000) || |
2398 | chip->usb_id == USB_ID(0x041e, 0x3020)) { | 2409 | chip->usb_id == USB_ID(0x041e, 0x3020)) { |
2399 | if (fmt[3] == USB_FORMAT_TYPE_I && | 2410 | if (fmt[3] == USB_FORMAT_TYPE_I && |
2400 | stream == SNDRV_PCM_STREAM_PLAYBACK && | ||
2401 | fp->rates != SNDRV_PCM_RATE_48000 && | 2411 | fp->rates != SNDRV_PCM_RATE_48000 && |
2402 | fp->rates != SNDRV_PCM_RATE_96000) | 2412 | fp->rates != SNDRV_PCM_RATE_96000) |
2403 | return -1; /* use 48k only */ | 2413 | return -1; |
2404 | } | 2414 | } |
2405 | #endif | 2415 | #endif |
2406 | return 0; | 2416 | return 0; |
@@ -2492,8 +2502,10 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no) | |||
2492 | fp->altset_idx = i; | 2502 | fp->altset_idx = i; |
2493 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; | 2503 | fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; |
2494 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; | 2504 | fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; |
2495 | /* FIXME: decode wMaxPacketSize of high bandwith endpoints */ | ||
2496 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); | 2505 | fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); |
2506 | if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) | ||
2507 | fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) | ||
2508 | * (fp->maxpacksize & 0x7ff); | ||
2497 | fp->attributes = csep[3]; | 2509 | fp->attributes = csep[3]; |
2498 | 2510 | ||
2499 | /* some quirks for attributes here */ | 2511 | /* some quirks for attributes here */ |
@@ -2723,7 +2735,8 @@ static int create_standard_interface_quirk(snd_usb_audio_t *chip, | |||
2723 | * to detect the sample rate is by looking at wMaxPacketSize. | 2735 | * to detect the sample rate is by looking at wMaxPacketSize. |
2724 | */ | 2736 | */ |
2725 | static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, | 2737 | static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, |
2726 | struct usb_interface *iface) | 2738 | struct usb_interface *iface, |
2739 | const snd_usb_audio_quirk_t *quirk) | ||
2727 | { | 2740 | { |
2728 | static const struct audioformat ua_format = { | 2741 | static const struct audioformat ua_format = { |
2729 | .format = SNDRV_PCM_FORMAT_S24_3LE, | 2742 | .format = SNDRV_PCM_FORMAT_S24_3LE, |
@@ -2814,7 +2827,9 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip, | |||
2814 | /* | 2827 | /* |
2815 | * Create a stream for an Edirol UA-1000 interface. | 2828 | * Create a stream for an Edirol UA-1000 interface. |
2816 | */ | 2829 | */ |
2817 | static int create_ua1000_quirk(snd_usb_audio_t *chip, struct usb_interface *iface) | 2830 | static int create_ua1000_quirk(snd_usb_audio_t *chip, |
2831 | struct usb_interface *iface, | ||
2832 | const snd_usb_audio_quirk_t *quirk) | ||
2818 | { | 2833 | { |
2819 | static const struct audioformat ua1000_format = { | 2834 | static const struct audioformat ua1000_format = { |
2820 | .format = SNDRV_PCM_FORMAT_S32_LE, | 2835 | .format = SNDRV_PCM_FORMAT_S32_LE, |
@@ -2891,6 +2906,13 @@ static int create_composite_quirk(snd_usb_audio_t *chip, | |||
2891 | return 0; | 2906 | return 0; |
2892 | } | 2907 | } |
2893 | 2908 | ||
2909 | static int ignore_interface_quirk(snd_usb_audio_t *chip, | ||
2910 | struct usb_interface *iface, | ||
2911 | const snd_usb_audio_quirk_t *quirk) | ||
2912 | { | ||
2913 | return 0; | ||
2914 | } | ||
2915 | |||
2894 | 2916 | ||
2895 | /* | 2917 | /* |
2896 | * boot quirks | 2918 | * boot quirks |
@@ -2926,8 +2948,6 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac | |||
2926 | 2948 | ||
2927 | static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) | 2949 | static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) |
2928 | { | 2950 | { |
2929 | #if 0 | ||
2930 | /* TODO: enable this when high speed synchronization actually works */ | ||
2931 | u8 buf = 1; | 2951 | u8 buf = 1; |
2932 | 2952 | ||
2933 | snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a, | 2953 | snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a, |
@@ -2939,7 +2959,6 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) | |||
2939 | 1, 2000, NULL, 0, 1000); | 2959 | 1, 2000, NULL, 0, 1000); |
2940 | return -ENODEV; | 2960 | return -ENODEV; |
2941 | } | 2961 | } |
2942 | #endif | ||
2943 | return 0; | 2962 | return 0; |
2944 | } | 2963 | } |
2945 | 2964 | ||
@@ -2956,28 +2975,28 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip, | |||
2956 | struct usb_interface *iface, | 2975 | struct usb_interface *iface, |
2957 | const snd_usb_audio_quirk_t *quirk) | 2976 | const snd_usb_audio_quirk_t *quirk) |
2958 | { | 2977 | { |
2959 | switch (quirk->type) { | 2978 | typedef int (*quirk_func_t)(snd_usb_audio_t *, struct usb_interface *, |
2960 | case QUIRK_MIDI_FIXED_ENDPOINT: | 2979 | const snd_usb_audio_quirk_t *); |
2961 | case QUIRK_MIDI_YAMAHA: | 2980 | static const quirk_func_t quirk_funcs[] = { |
2962 | case QUIRK_MIDI_MIDIMAN: | 2981 | [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, |
2963 | case QUIRK_MIDI_NOVATION: | 2982 | [QUIRK_COMPOSITE] = create_composite_quirk, |
2964 | case QUIRK_MIDI_MOTU: | 2983 | [QUIRK_MIDI_STANDARD_INTERFACE] = snd_usb_create_midi_interface, |
2965 | case QUIRK_MIDI_EMAGIC: | 2984 | [QUIRK_MIDI_FIXED_ENDPOINT] = snd_usb_create_midi_interface, |
2966 | return snd_usb_create_midi_interface(chip, iface, quirk); | 2985 | [QUIRK_MIDI_YAMAHA] = snd_usb_create_midi_interface, |
2967 | case QUIRK_COMPOSITE: | 2986 | [QUIRK_MIDI_MIDIMAN] = snd_usb_create_midi_interface, |
2968 | return create_composite_quirk(chip, iface, quirk); | 2987 | [QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface, |
2969 | case QUIRK_AUDIO_FIXED_ENDPOINT: | 2988 | [QUIRK_MIDI_RAW] = snd_usb_create_midi_interface, |
2970 | return create_fixed_stream_quirk(chip, iface, quirk); | 2989 | [QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface, |
2971 | case QUIRK_AUDIO_STANDARD_INTERFACE: | 2990 | [QUIRK_MIDI_MIDITECH] = snd_usb_create_midi_interface, |
2972 | case QUIRK_MIDI_STANDARD_INTERFACE: | 2991 | [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_interface_quirk, |
2973 | return create_standard_interface_quirk(chip, iface, quirk); | 2992 | [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, |
2974 | case QUIRK_AUDIO_EDIROL_UA700_UA25: | 2993 | [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, |
2975 | return create_ua700_ua25_quirk(chip, iface); | 2994 | [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, |
2976 | case QUIRK_AUDIO_EDIROL_UA1000: | 2995 | }; |
2977 | return create_ua1000_quirk(chip, iface); | 2996 | |
2978 | case QUIRK_IGNORE_INTERFACE: | 2997 | if (quirk->type < QUIRK_TYPE_COUNT) { |
2979 | return 0; | 2998 | return quirk_funcs[quirk->type](chip, iface, quirk); |
2980 | default: | 2999 | } else { |
2981 | snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); | 3000 | snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); |
2982 | return -ENXIO; | 3001 | return -ENXIO; |
2983 | } | 3002 | } |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index aedb42aaa749..ad9eab211d8f 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -153,20 +153,24 @@ struct snd_usb_audio { | |||
153 | #define QUIRK_NO_INTERFACE -2 | 153 | #define QUIRK_NO_INTERFACE -2 |
154 | #define QUIRK_ANY_INTERFACE -1 | 154 | #define QUIRK_ANY_INTERFACE -1 |
155 | 155 | ||
156 | /* quirk type */ | 156 | enum quirk_type { |
157 | #define QUIRK_MIDI_FIXED_ENDPOINT 0 | 157 | QUIRK_IGNORE_INTERFACE, |
158 | #define QUIRK_MIDI_YAMAHA 1 | 158 | QUIRK_COMPOSITE, |
159 | #define QUIRK_MIDI_MIDIMAN 2 | 159 | QUIRK_MIDI_STANDARD_INTERFACE, |
160 | #define QUIRK_COMPOSITE 3 | 160 | QUIRK_MIDI_FIXED_ENDPOINT, |
161 | #define QUIRK_AUDIO_FIXED_ENDPOINT 4 | 161 | QUIRK_MIDI_YAMAHA, |
162 | #define QUIRK_AUDIO_STANDARD_INTERFACE 5 | 162 | QUIRK_MIDI_MIDIMAN, |
163 | #define QUIRK_MIDI_STANDARD_INTERFACE 6 | 163 | QUIRK_MIDI_NOVATION, |
164 | #define QUIRK_AUDIO_EDIROL_UA700_UA25 7 | 164 | QUIRK_MIDI_RAW, |
165 | #define QUIRK_AUDIO_EDIROL_UA1000 8 | 165 | QUIRK_MIDI_EMAGIC, |
166 | #define QUIRK_IGNORE_INTERFACE 9 | 166 | QUIRK_MIDI_MIDITECH, |
167 | #define QUIRK_MIDI_NOVATION 10 | 167 | QUIRK_AUDIO_STANDARD_INTERFACE, |
168 | #define QUIRK_MIDI_MOTU 11 | 168 | QUIRK_AUDIO_FIXED_ENDPOINT, |
169 | #define QUIRK_MIDI_EMAGIC 12 | 169 | QUIRK_AUDIO_EDIROL_UA700_UA25, |
170 | QUIRK_AUDIO_EDIROL_UA1000, | ||
171 | |||
172 | QUIRK_TYPE_COUNT | ||
173 | }; | ||
170 | 174 | ||
171 | typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t; | 175 | typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t; |
172 | typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t; | 176 | typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t; |
@@ -175,7 +179,7 @@ struct snd_usb_audio_quirk { | |||
175 | const char *vendor_name; | 179 | const char *vendor_name; |
176 | const char *product_name; | 180 | const char *product_name; |
177 | int16_t ifnum; | 181 | int16_t ifnum; |
178 | int16_t type; | 182 | uint16_t type; |
179 | const void *data; | 183 | const void *data; |
180 | }; | 184 | }; |
181 | 185 | ||
@@ -205,11 +209,13 @@ struct snd_usb_midi_endpoint_info { | |||
205 | 209 | ||
206 | /* for QUIRK_IGNORE_INTERFACE, data is NULL */ | 210 | /* for QUIRK_IGNORE_INTERFACE, data is NULL */ |
207 | 211 | ||
208 | /* for QUIRK_MIDI_NOVATION and _MOTU, data is NULL */ | 212 | /* for QUIRK_MIDI_NOVATION and _RAW, data is NULL */ |
209 | 213 | ||
210 | /* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info | 214 | /* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info |
211 | * structure (out_cables and in_cables only) */ | 215 | * structure (out_cables and in_cables only) */ |
212 | 216 | ||
217 | /* for QUIRK_MIDI_MIDITECH, data is NULL */ | ||
218 | |||
213 | /* | 219 | /* |
214 | */ | 220 | */ |
215 | 221 | ||
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index bee70068dce0..5778a9b725ec 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c | |||
@@ -524,16 +524,16 @@ static struct usb_protocol_ops snd_usbmidi_novation_ops = { | |||
524 | }; | 524 | }; |
525 | 525 | ||
526 | /* | 526 | /* |
527 | * Mark of the Unicorn USB MIDI protocol: raw MIDI. | 527 | * "raw" protocol: used by the MOTU FastLane. |
528 | */ | 528 | */ |
529 | 529 | ||
530 | static void snd_usbmidi_motu_input(snd_usb_midi_in_endpoint_t* ep, | 530 | static void snd_usbmidi_raw_input(snd_usb_midi_in_endpoint_t* ep, |
531 | uint8_t* buffer, int buffer_length) | 531 | uint8_t* buffer, int buffer_length) |
532 | { | 532 | { |
533 | snd_usbmidi_input_data(ep, 0, buffer, buffer_length); | 533 | snd_usbmidi_input_data(ep, 0, buffer, buffer_length); |
534 | } | 534 | } |
535 | 535 | ||
536 | static void snd_usbmidi_motu_output(snd_usb_midi_out_endpoint_t* ep) | 536 | static void snd_usbmidi_raw_output(snd_usb_midi_out_endpoint_t* ep) |
537 | { | 537 | { |
538 | int count; | 538 | int count; |
539 | 539 | ||
@@ -549,9 +549,9 @@ static void snd_usbmidi_motu_output(snd_usb_midi_out_endpoint_t* ep) | |||
549 | ep->urb->transfer_buffer_length = count; | 549 | ep->urb->transfer_buffer_length = count; |
550 | } | 550 | } |
551 | 551 | ||
552 | static struct usb_protocol_ops snd_usbmidi_motu_ops = { | 552 | static struct usb_protocol_ops snd_usbmidi_raw_ops = { |
553 | .input = snd_usbmidi_motu_input, | 553 | .input = snd_usbmidi_raw_input, |
554 | .output = snd_usbmidi_motu_output, | 554 | .output = snd_usbmidi_raw_output, |
555 | }; | 555 | }; |
556 | 556 | ||
557 | /* | 557 | /* |
@@ -1505,8 +1505,8 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip, | |||
1505 | umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; | 1505 | umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; |
1506 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | 1506 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); |
1507 | break; | 1507 | break; |
1508 | case QUIRK_MIDI_MOTU: | 1508 | case QUIRK_MIDI_RAW: |
1509 | umidi->usb_protocol_ops = &snd_usbmidi_motu_ops; | 1509 | umidi->usb_protocol_ops = &snd_usbmidi_raw_ops; |
1510 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | 1510 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); |
1511 | break; | 1511 | break; |
1512 | case QUIRK_MIDI_EMAGIC: | 1512 | case QUIRK_MIDI_EMAGIC: |
@@ -1515,6 +1515,9 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip, | |||
1515 | sizeof(snd_usb_midi_endpoint_info_t)); | 1515 | sizeof(snd_usb_midi_endpoint_info_t)); |
1516 | err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); | 1516 | err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1); |
1517 | break; | 1517 | break; |
1518 | case QUIRK_MIDI_MIDITECH: | ||
1519 | err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); | ||
1520 | break; | ||
1518 | default: | 1521 | default: |
1519 | snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); | 1522 | snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type); |
1520 | err = -ENXIO; | 1523 | err = -ENXIO; |
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index f5135641b3e2..f74e652a1e51 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h | |||
@@ -116,6 +116,7 @@ YAMAHA_DEVICE(0x1039, NULL), | |||
116 | YAMAHA_DEVICE(0x103a, NULL), | 116 | YAMAHA_DEVICE(0x103a, NULL), |
117 | YAMAHA_DEVICE(0x103b, NULL), | 117 | YAMAHA_DEVICE(0x103b, NULL), |
118 | YAMAHA_DEVICE(0x103c, NULL), | 118 | YAMAHA_DEVICE(0x103c, NULL), |
119 | YAMAHA_DEVICE(0x103d, NULL), | ||
119 | YAMAHA_DEVICE(0x2000, "DGP-7"), | 120 | YAMAHA_DEVICE(0x2000, "DGP-7"), |
120 | YAMAHA_DEVICE(0x2001, "DGP-5"), | 121 | YAMAHA_DEVICE(0x2001, "DGP-5"), |
121 | YAMAHA_DEVICE(0x2002, NULL), | 122 | YAMAHA_DEVICE(0x2002, NULL), |
@@ -1259,7 +1260,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1259 | /* Mark of the Unicorn devices */ | 1260 | /* Mark of the Unicorn devices */ |
1260 | { | 1261 | { |
1261 | /* thanks to Robert A. Lerche <ral 'at' msbit.com> */ | 1262 | /* thanks to Robert A. Lerche <ral 'at' msbit.com> */ |
1262 | USB_DEVICE(0x07fd, 0x0001), | 1263 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | |
1264 | USB_DEVICE_ID_MATCH_PRODUCT | | ||
1265 | USB_DEVICE_ID_MATCH_DEV_SUBCLASS, | ||
1266 | .idVendor = 0x07fd, | ||
1267 | .idProduct = 0x0001, | ||
1268 | .bDeviceSubClass = 2, | ||
1263 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | 1269 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { |
1264 | .vendor_name = "MOTU", | 1270 | .vendor_name = "MOTU", |
1265 | .product_name = "Fastlane", | 1271 | .product_name = "Fastlane", |
@@ -1268,7 +1274,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1268 | .data = & (const snd_usb_audio_quirk_t[]) { | 1274 | .data = & (const snd_usb_audio_quirk_t[]) { |
1269 | { | 1275 | { |
1270 | .ifnum = 0, | 1276 | .ifnum = 0, |
1271 | .type = QUIRK_MIDI_MOTU | 1277 | .type = QUIRK_MIDI_RAW |
1272 | }, | 1278 | }, |
1273 | { | 1279 | { |
1274 | .ifnum = 1, | 1280 | .ifnum = 1, |
@@ -1373,6 +1379,25 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1373 | }, | 1379 | }, |
1374 | 1380 | ||
1375 | { | 1381 | { |
1382 | USB_DEVICE(0x4752, 0x0011), | ||
1383 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | ||
1384 | .vendor_name = "Miditech", | ||
1385 | .product_name = "Midistart-2", | ||
1386 | .ifnum = 0, | ||
1387 | .type = QUIRK_MIDI_MIDITECH | ||
1388 | } | ||
1389 | }, | ||
1390 | { | ||
1391 | USB_DEVICE(0x7104, 0x2202), | ||
1392 | .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { | ||
1393 | .vendor_name = "Miditech", | ||
1394 | .product_name = "MidiStudio-2", | ||
1395 | .ifnum = 0, | ||
1396 | .type = QUIRK_MIDI_MIDITECH | ||
1397 | } | ||
1398 | }, | ||
1399 | |||
1400 | { | ||
1376 | /* | 1401 | /* |
1377 | * Some USB MIDI devices don't have an audio control interface, | 1402 | * Some USB MIDI devices don't have an audio control interface, |
1378 | * so we have to grab MIDI streaming interfaces here. | 1403 | * so we have to grab MIDI streaming interfaces here. |
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index bef9b0c142c4..0281a362857a 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c | |||
@@ -232,8 +232,7 @@ static int snd_usX2Y_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp) | |||
232 | if (err) | 232 | if (err) |
233 | return err; | 233 | return err; |
234 | if (dsp->index == 1) { | 234 | if (dsp->index == 1) { |
235 | set_current_state(TASK_UNINTERRUPTIBLE); | 235 | msleep(250); // give the device some time |
236 | schedule_timeout(HZ/4); // give the device some time | ||
237 | err = usX2Y_AsyncSeq04_init(priv); | 236 | err = usX2Y_AsyncSeq04_init(priv); |
238 | if (err) { | 237 | if (err) { |
239 | snd_printk("usX2Y_AsyncSeq04_init error \n"); | 238 | snd_printk("usX2Y_AsyncSeq04_init error \n"); |
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index bb2c8e9000c6..ef28061287f2 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c | |||
@@ -50,6 +50,7 @@ | |||
50 | Currently rawusb dma pcm buffer transport (this file) is only available to snd-usb-usx2y. | 50 | Currently rawusb dma pcm buffer transport (this file) is only available to snd-usb-usx2y. |
51 | */ | 51 | */ |
52 | 52 | ||
53 | #include <linux/delay.h> | ||
53 | #include "usbusx2yaudio.c" | 54 | #include "usbusx2yaudio.c" |
54 | 55 | ||
55 | #if defined(USX2Y_NRPACKS_VARIABLE) || (!defined(USX2Y_NRPACKS_VARIABLE) && USX2Y_NRPACKS == 1) | 56 | #if defined(USX2Y_NRPACKS_VARIABLE) || (!defined(USX2Y_NRPACKS_VARIABLE) && USX2Y_NRPACKS == 1) |
@@ -520,11 +521,8 @@ static int snd_usX2Y_usbpcm_prepare(snd_pcm_substream_t *substream) | |||
520 | usX2Y->hwdep_pcm_shm->playback_iso_start = -1; | 521 | usX2Y->hwdep_pcm_shm->playback_iso_start = -1; |
521 | if (atomic_read(&subs->state) < state_PREPARED) { | 522 | if (atomic_read(&subs->state) < state_PREPARED) { |
522 | while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > usX2Y->hwdep_pcm_shm->captured_iso_frames) { | 523 | while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > usX2Y->hwdep_pcm_shm->captured_iso_frames) { |
523 | signed long timeout; | ||
524 | snd_printd("Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", usX2Y_iso_frames_per_buffer(runtime, usX2Y), usX2Y->hwdep_pcm_shm->captured_iso_frames); | 524 | snd_printd("Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", usX2Y_iso_frames_per_buffer(runtime, usX2Y), usX2Y->hwdep_pcm_shm->captured_iso_frames); |
525 | set_current_state(TASK_INTERRUPTIBLE); | 525 | if (msleep_interruptible(10)) { |
526 | timeout = schedule_timeout(HZ/100 + 1); | ||
527 | if (signal_pending(current)) { | ||
528 | err = -ERESTARTSYS; | 526 | err = -ERESTARTSYS; |
529 | goto up_prepare_mutex; | 527 | goto up_prepare_mutex; |
530 | } | 528 | } |