aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCedric Bregardis <cedric.bregardis@free.fr>2008-02-20 06:05:13 -0500
committerTakashi Iwai <tiwai@suse.de>2008-04-24 06:00:13 -0400
commit98f2a97f207a776603173ee96327d977e592579d (patch)
treef7e313b4a33b7ebe2a493e009f53eecb446cd676
parent67ebcb0311110dc7268bb5b135bf437d8033337e (diff)
[ALSA] Emagic Audiowerk 2 ALSA driver.
Signed-off-by: Cedric Bregardis <cedric.bregardis@free.fr> Signed-off-by: Jean-Christian Hassler <jhassler@free.fr> Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/Kconfig15
-rw-r--r--sound/pci/Makefile1
-rw-r--r--sound/pci/aw2/Makefile3
-rw-r--r--sound/pci/aw2/aw2-alsa.c787
-rw-r--r--sound/pci/aw2/aw2-saa7146.c464
-rw-r--r--sound/pci/aw2/aw2-saa7146.h105
-rw-r--r--sound/pci/aw2/aw2-tsl.h116
-rw-r--r--sound/pci/aw2/saa7146.h168
8 files changed, 1659 insertions, 0 deletions
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index b05435cfee1e..868183bef243 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -122,6 +122,21 @@ config SND_AU8830
122 To compile this driver as a module, choose M here: the module 122 To compile this driver as a module, choose M here: the module
123 will be called snd-au8830. 123 will be called snd-au8830.
124 124
125config SND_AW2
126 tristate "Emagic Audiowerk 2"
127 depends on SND
128 help
129 Say Y here to include support for Emagic Audiowerk 2 soundcards.
130
131 Supported features: Analog and SPDIF output. Analog or SPDIF input.
132 Note: Switch between analog and digital input does not always work.
133 It can produce continuous noise. The workaround is to switch again
134 (and again) between digital and analog input until it works.
135
136 To compile this driver as a module, choose M here: the module
137 will be called snd-aw2.
138
139
125config SND_AZT3328 140config SND_AZT3328
126 tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)" 141 tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
127 depends on SND && EXPERIMENTAL 142 depends on SND && EXPERIMENTAL
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index 2d42fd28f4e7..85ef14bc8056 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_SND) += \
58 ac97/ \ 58 ac97/ \
59 ali5451/ \ 59 ali5451/ \
60 au88x0/ \ 60 au88x0/ \
61 aw2/ \
61 ca0106/ \ 62 ca0106/ \
62 cs46xx/ \ 63 cs46xx/ \
63 cs5535audio/ \ 64 cs5535audio/ \
diff --git a/sound/pci/aw2/Makefile b/sound/pci/aw2/Makefile
new file mode 100644
index 000000000000..842335d3b735
--- /dev/null
+++ b/sound/pci/aw2/Makefile
@@ -0,0 +1,3 @@
1snd-aw2-objs := aw2-alsa.o aw2-saa7146.o
2
3obj-$(CONFIG_SND_AW2) += snd-aw2.o
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
new file mode 100644
index 000000000000..74af639b9132
--- /dev/null
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -0,0 +1,787 @@
1/*****************************************************************************
2 *
3 * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
4 * Jean-Christian Hassler <jhassler@free.fr>
5 *
6 * This file is part of the Audiowerk2 ALSA driver
7 *
8 * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.
11 *
12 * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
21 *
22 *****************************************************************************/
23#include <linux/init.h>
24#include <linux/pci.h>
25#include <linux/slab.h>
26#include <linux/interrupt.h>
27#include <linux/delay.h>
28#include <asm/io.h>
29#include <sound/core.h>
30#include <sound/initval.h>
31#include <sound/pcm.h>
32#include <sound/pcm_params.h>
33#include <sound/control.h>
34
35#include "saa7146.h"
36#include "aw2-saa7146.h"
37
38MODULE_LICENSE("GPL");
39MODULE_AUTHOR("Cedric Bregardis <cedric.bregardis@free.fr>, "
40 "Jean-Christian Hassler <jhassler@free.fr>");
41MODULE_DESCRIPTION("Emagic Audiowerk 2 sound driver");
42MODULE_LICENSE("GPL");
43
44/*********************************
45 * DEFINES
46 ********************************/
47#define PCI_VENDOR_ID_SAA7146 0x1131
48#define PCI_DEVICE_ID_SAA7146 0x7146
49
50#define CTL_ROUTE_ANALOG 0
51#define CTL_ROUTE_DIGITAL 1
52
53/*********************************
54 * TYPEDEFS
55 ********************************/
56 /* hardware definition */
57static struct snd_pcm_hardware snd_aw2_playback_hw = {
58 .info = (SNDRV_PCM_INFO_MMAP |
59 SNDRV_PCM_INFO_INTERLEAVED |
60 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
61 .formats = SNDRV_PCM_FMTBIT_S16_LE,
62 .rates = SNDRV_PCM_RATE_44100,
63 .rate_min = 44100,
64 .rate_max = 44100,
65 .channels_min = 2,
66 .channels_max = 4,
67 .buffer_bytes_max = 32768,
68 .period_bytes_min = 4096,
69 .period_bytes_max = 32768,
70 .periods_min = 1,
71 .periods_max = 1024,
72};
73
74static struct snd_pcm_hardware snd_aw2_capture_hw = {
75 .info = (SNDRV_PCM_INFO_MMAP |
76 SNDRV_PCM_INFO_INTERLEAVED |
77 SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
78 .formats = SNDRV_PCM_FMTBIT_S16_LE,
79 .rates = SNDRV_PCM_RATE_44100,
80 .rate_min = 44100,
81 .rate_max = 44100,
82 .channels_min = 2,
83 .channels_max = 2,
84 .buffer_bytes_max = 32768,
85 .period_bytes_min = 4096,
86 .period_bytes_max = 32768,
87 .periods_min = 1,
88 .periods_max = 1024,
89};
90
91struct aw2_pcm_device {
92 struct snd_pcm *pcm;
93 unsigned int stream_number;
94 struct aw2 *chip;
95};
96
97struct aw2 {
98 struct snd_aw2_saa7146 saa7146;
99
100 struct pci_dev *pci;
101 int irq;
102 spinlock_t reg_lock;
103 struct mutex mtx;
104
105 unsigned long iobase_phys;
106 void __iomem *iobase_virt;
107
108 struct snd_card *card;
109
110 struct aw2_pcm_device device_playback[NB_STREAM_PLAYBACK];
111 struct aw2_pcm_device device_capture[NB_STREAM_CAPTURE];
112};
113
114/*********************************
115 * FUNCTION DECLARATIONS
116 ********************************/
117static int __init alsa_card_aw2_init(void);
118static void __exit alsa_card_aw2_exit(void);
119static int snd_aw2_dev_free(struct snd_device *device);
120static int __devinit snd_aw2_create(struct snd_card *card,
121 struct pci_dev *pci, struct aw2 **rchip);
122static int __devinit snd_aw2_probe(struct pci_dev *pci,
123 const struct pci_device_id *pci_id);
124static void __devexit snd_aw2_remove(struct pci_dev *pci);
125static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
126static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
127static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
128static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream);
129static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
130 struct snd_pcm_hw_params *hw_params);
131static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream);
132static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream);
133static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream);
134static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
135 int cmd);
136static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
137 int cmd);
138static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
139 *substream);
140static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
141 *substream);
142static int __devinit snd_aw2_new_pcm(struct aw2 *chip);
143
144static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
145 struct snd_ctl_elem_info *uinfo);
146static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
147 struct snd_ctl_elem_value
148 *ucontrol);
149static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
150 struct snd_ctl_elem_value
151 *ucontrol);
152
153/*********************************
154 * VARIABLES
155 ********************************/
156static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
157static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
158static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
159
160static struct pci_device_id snd_aw2_ids[] = {
161 {PCI_VENDOR_ID_SAA7146, PCI_DEVICE_ID_SAA7146, PCI_ANY_ID, PCI_ANY_ID,
162 0, 0, 0},
163 {0}
164};
165
166MODULE_DEVICE_TABLE(pci, snd_aw2_ids);
167
168/* pci_driver definition */
169static struct pci_driver driver = {
170 .name = "Emagic Audiowerk 2",
171 .id_table = snd_aw2_ids,
172 .probe = snd_aw2_probe,
173 .remove = __devexit_p(snd_aw2_remove),
174};
175
176/* operators for playback PCM alsa interface */
177static struct snd_pcm_ops snd_aw2_playback_ops = {
178 .open = snd_aw2_pcm_playback_open,
179 .close = snd_aw2_pcm_playback_close,
180 .ioctl = snd_pcm_lib_ioctl,
181 .hw_params = snd_aw2_pcm_hw_params,
182 .hw_free = snd_aw2_pcm_hw_free,
183 .prepare = snd_aw2_pcm_prepare_playback,
184 .trigger = snd_aw2_pcm_trigger_playback,
185 .pointer = snd_aw2_pcm_pointer_playback,
186};
187
188/* operators for capture PCM alsa interface */
189static struct snd_pcm_ops snd_aw2_capture_ops = {
190 .open = snd_aw2_pcm_capture_open,
191 .close = snd_aw2_pcm_capture_close,
192 .ioctl = snd_pcm_lib_ioctl,
193 .hw_params = snd_aw2_pcm_hw_params,
194 .hw_free = snd_aw2_pcm_hw_free,
195 .prepare = snd_aw2_pcm_prepare_capture,
196 .trigger = snd_aw2_pcm_trigger_capture,
197 .pointer = snd_aw2_pcm_pointer_capture,
198};
199
200static struct snd_kcontrol_new aw2_control __devinitdata = {
201 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
202 .name = "PCM Capture Route",
203 .index = 0,
204 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
205 .private_value = 0xffff,
206 .info = snd_aw2_control_switch_capture_info,
207 .get = snd_aw2_control_switch_capture_get,
208 .put = snd_aw2_control_switch_capture_put
209};
210
211/*********************************
212 * FUNCTION IMPLEMENTATIONS
213 ********************************/
214
215/* initialization of the module */
216static int __init alsa_card_aw2_init(void)
217{
218 snd_printdd(KERN_DEBUG "aw2: Load aw2 module\n");
219 return pci_register_driver(&driver);
220}
221
222/* clean up the module */
223static void __exit alsa_card_aw2_exit(void)
224{
225 snd_printdd(KERN_DEBUG "aw2: Unload aw2 module\n");
226 pci_unregister_driver(&driver);
227}
228
229module_init(alsa_card_aw2_init);
230module_exit(alsa_card_aw2_exit);
231
232/* component-destructor */
233static int snd_aw2_dev_free(struct snd_device *device)
234{
235 struct aw2 *chip = device->device_data;
236
237 /* Free hardware */
238 snd_aw2_saa7146_free(&chip->saa7146);
239
240 /* release the irq */
241 if (chip->irq >= 0)
242 free_irq(chip->irq, (void *)chip);
243 /* release the i/o ports & memory */
244 if (chip->iobase_virt)
245 iounmap(chip->iobase_virt);
246
247 pci_release_regions(chip->pci);
248 /* disable the PCI entry */
249 pci_disable_device(chip->pci);
250 /* release the data */
251 kfree(chip);
252
253 return 0;
254}
255
256/* chip-specific constructor */
257static int __devinit snd_aw2_create(struct snd_card *card,
258 struct pci_dev *pci, struct aw2 **rchip)
259{
260 struct aw2 *chip;
261 int err;
262 static struct snd_device_ops ops = {
263 .dev_free = snd_aw2_dev_free,
264 };
265
266 *rchip = NULL;
267
268 /* initialize the PCI entry */
269 err = pci_enable_device(pci);
270 if (err < 0)
271 return err;
272 pci_set_master(pci);
273
274 /* check PCI availability (32bit DMA) */
275 if ((pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) ||
276 (pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0)) {
277 printk(KERN_ERR "aw2: Impossible to set 32bit mask DMA\n");
278 pci_disable_device(pci);
279 return -ENXIO;
280 }
281 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
282 if (chip == NULL) {
283 pci_disable_device(pci);
284 return -ENOMEM;
285 }
286
287 /* initialize the stuff */
288 chip->card = card;
289 chip->pci = pci;
290 chip->irq = -1;
291
292 /* (1) PCI resource allocation */
293 err = pci_request_regions(pci, "Audiowerk2");
294 if (err < 0) {
295 pci_disable_device(pci);
296 kfree(chip);
297 return err;
298 }
299 chip->iobase_phys = pci_resource_start(pci, 0);
300 chip->iobase_virt =
301 ioremap_nocache(chip->iobase_phys,
302 pci_resource_len(pci, 0));
303
304 if (chip->iobase_virt == NULL) {
305 printk(KERN_ERR "aw2: unable to remap memory region");
306 pci_release_regions(pci);
307 pci_disable_device(pci);
308 kfree(chip);
309 return -ENOMEM;
310 }
311
312
313 if (request_irq(pci->irq, snd_aw2_saa7146_interrupt,
314 IRQF_SHARED, "Audiowerk2", chip)) {
315 printk(KERN_ERR "aw2: Cannot grab irq %d\n", pci->irq);
316
317 iounmap(chip->iobase_virt);
318 pci_release_regions(chip->pci);
319 pci_disable_device(chip->pci);
320 kfree(chip);
321 return -EBUSY;
322 }
323 chip->irq = pci->irq;
324
325 /* (2) initialization of the chip hardware */
326 snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
327 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
328 if (err < 0) {
329 free_irq(chip->irq, (void *)chip);
330 iounmap(chip->iobase_virt);
331 pci_release_regions(chip->pci);
332 pci_disable_device(chip->pci);
333 kfree(chip);
334 return err;
335 }
336
337 snd_card_set_dev(card, &pci->dev);
338 *rchip = chip;
339
340 printk(KERN_INFO
341 "Audiowerk 2 sound card (saa7146 chipset) detected and "
342 "managed\n");
343 return 0;
344}
345
346/* constructor */
347static int __devinit snd_aw2_probe(struct pci_dev *pci,
348 const struct pci_device_id *pci_id)
349{
350 static int dev;
351 struct snd_card *card;
352 struct aw2 *chip;
353 int err;
354
355 /* (1) Continue if device is not enabled, else inc dev */
356 if (dev >= SNDRV_CARDS)
357 return -ENODEV;
358 if (!enable[dev]) {
359 dev++;
360 return -ENOENT;
361 }
362
363 /* (2) Create card instance */
364 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
365 if (card == NULL)
366 return -ENOMEM;
367
368 /* (3) Create main component */
369 err = snd_aw2_create(card, pci, &chip);
370 if (err < 0) {
371 snd_card_free(card);
372 return err;
373 }
374
375 /* initialize mutex */
376 mutex_init(&chip->mtx);
377 /* init spinlock */
378 spin_lock_init(&chip->reg_lock);
379 /* (4) Define driver ID and name string */
380 strcpy(card->driver, "aw2");
381 strcpy(card->shortname, "Audiowerk2");
382
383 sprintf(card->longname, "%s with SAA7146 irq %i",
384 card->shortname, chip->irq);
385
386 /* (5) Create other components */
387 snd_aw2_new_pcm(chip);
388
389 /* (6) Register card instance */
390 err = snd_card_register(card);
391 if (err < 0) {
392 snd_card_free(card);
393 return err;
394 }
395
396 /* (7) Set PCI driver data */
397 pci_set_drvdata(pci, card);
398
399 dev++;
400 return 0;
401}
402
403/* destructor */
404static void __devexit snd_aw2_remove(struct pci_dev *pci)
405{
406 snd_card_free(pci_get_drvdata(pci));
407 pci_set_drvdata(pci, NULL);
408}
409
410/* open callback */
411static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream)
412{
413 struct snd_pcm_runtime *runtime = substream->runtime;
414
415 snd_printdd(KERN_DEBUG "aw2: Playback_open \n");
416 runtime->hw = snd_aw2_playback_hw;
417 return 0;
418}
419
420/* close callback */
421static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream)
422{
423 return 0;
424
425}
426
427static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream)
428{
429 struct snd_pcm_runtime *runtime = substream->runtime;
430
431 snd_printdd(KERN_DEBUG "aw2: Capture_open \n");
432 runtime->hw = snd_aw2_capture_hw;
433 return 0;
434}
435
436/* close callback */
437static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream)
438{
439 /* TODO: something to do ? */
440 return 0;
441}
442
443 /* hw_params callback */
444static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
445 struct snd_pcm_hw_params *hw_params)
446{
447 return snd_pcm_lib_malloc_pages(substream,
448 params_buffer_bytes(hw_params));
449}
450
451/* hw_free callback */
452static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream)
453{
454 return snd_pcm_lib_free_pages(substream);
455}
456
457/* prepare callback for playback */
458static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream)
459{
460 struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
461 struct aw2 *chip = pcm_device->chip;
462 struct snd_pcm_runtime *runtime = substream->runtime;
463 unsigned long period_size, buffer_size;
464
465 mutex_lock(&chip->mtx);
466
467 period_size = snd_pcm_lib_period_bytes(substream);
468 buffer_size = snd_pcm_lib_buffer_bytes(substream);
469
470 snd_aw2_saa7146_pcm_init_playback(&chip->saa7146,
471 pcm_device->stream_number,
472 runtime->dma_addr, period_size,
473 buffer_size);
474
475 /* Define Interrupt callback */
476 snd_aw2_saa7146_define_it_playback_callback(pcm_device->stream_number,
477 (snd_aw2_saa7146_it_cb)
478 snd_pcm_period_elapsed,
479 (void *)substream);
480
481 mutex_unlock(&chip->mtx);
482
483 return 0;
484}
485
486/* prepare callback for capture */
487static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream)
488{
489 struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
490 struct aw2 *chip = pcm_device->chip;
491 struct snd_pcm_runtime *runtime = substream->runtime;
492 unsigned long period_size, buffer_size;
493
494 mutex_lock(&chip->mtx);
495
496 period_size = snd_pcm_lib_period_bytes(substream);
497 buffer_size = snd_pcm_lib_buffer_bytes(substream);
498
499 snd_aw2_saa7146_pcm_init_capture(&chip->saa7146,
500 pcm_device->stream_number,
501 runtime->dma_addr, period_size,
502 buffer_size);
503
504 /* Define Interrupt callback */
505 snd_aw2_saa7146_define_it_capture_callback(pcm_device->stream_number,
506 (snd_aw2_saa7146_it_cb)
507 snd_pcm_period_elapsed,
508 (void *)substream);
509
510 mutex_unlock(&chip->mtx);
511
512 return 0;
513}
514
515/* playback trigger callback */
516static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
517 int cmd)
518{
519 int status = 0;
520 struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
521 struct aw2 *chip = pcm_device->chip;
522 spin_lock(&chip->reg_lock);
523 switch (cmd) {
524 case SNDRV_PCM_TRIGGER_START:
525 snd_aw2_saa7146_pcm_trigger_start_playback(&chip->saa7146,
526 pcm_device->
527 stream_number);
528 break;
529 case SNDRV_PCM_TRIGGER_STOP:
530 snd_aw2_saa7146_pcm_trigger_stop_playback(&chip->saa7146,
531 pcm_device->
532 stream_number);
533 break;
534 default:
535 status = -EINVAL;
536 }
537 spin_unlock(&chip->reg_lock);
538 return status;
539}
540
541/* capture trigger callback */
542static int snd_aw2_pcm_trigger_capture(struct snd_pcm_substream *substream,
543 int cmd)
544{
545 int status = 0;
546 struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
547 struct aw2 *chip = pcm_device->chip;
548 spin_lock(&chip->reg_lock);
549 switch (cmd) {
550 case SNDRV_PCM_TRIGGER_START:
551 snd_aw2_saa7146_pcm_trigger_start_capture(&chip->saa7146,
552 pcm_device->
553 stream_number);
554 break;
555 case SNDRV_PCM_TRIGGER_STOP:
556 snd_aw2_saa7146_pcm_trigger_stop_capture(&chip->saa7146,
557 pcm_device->
558 stream_number);
559 break;
560 default:
561 status = -EINVAL;
562 }
563 spin_unlock(&chip->reg_lock);
564 return status;
565}
566
567/* playback pointer callback */
568static snd_pcm_uframes_t snd_aw2_pcm_pointer_playback(struct snd_pcm_substream
569 *substream)
570{
571 struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
572 struct aw2 *chip = pcm_device->chip;
573 unsigned int current_ptr;
574
575 /* get the current hardware pointer */
576 struct snd_pcm_runtime *runtime = substream->runtime;
577 current_ptr =
578 snd_aw2_saa7146_get_hw_ptr_playback(&chip->saa7146,
579 pcm_device->stream_number,
580 runtime->dma_area,
581 runtime->buffer_size);
582
583 return bytes_to_frames(substream->runtime, current_ptr);
584}
585
586/* capture pointer callback */
587static snd_pcm_uframes_t snd_aw2_pcm_pointer_capture(struct snd_pcm_substream
588 *substream)
589{
590 struct aw2_pcm_device *pcm_device = snd_pcm_substream_chip(substream);
591 struct aw2 *chip = pcm_device->chip;
592 unsigned int current_ptr;
593
594 /* get the current hardware pointer */
595 struct snd_pcm_runtime *runtime = substream->runtime;
596 current_ptr =
597 snd_aw2_saa7146_get_hw_ptr_capture(&chip->saa7146,
598 pcm_device->stream_number,
599 runtime->dma_area,
600 runtime->buffer_size);
601
602 return bytes_to_frames(substream->runtime, current_ptr);
603}
604
605/* create a pcm device */
606static int __devinit snd_aw2_new_pcm(struct aw2 *chip)
607{
608 struct snd_pcm *pcm_playback_ana;
609 struct snd_pcm *pcm_playback_num;
610 struct snd_pcm *pcm_capture;
611 struct aw2_pcm_device *pcm_device;
612 int err = 0;
613
614 /* Create new Alsa PCM device */
615
616 err = snd_pcm_new(chip->card, "Audiowerk2 analog playback", 0, 1, 0,
617 &pcm_playback_ana);
618 if (err < 0) {
619 printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
620 return err;
621 }
622
623 /* Creation ok */
624 pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_ANA];
625
626 /* Set PCM device name */
627 strcpy(pcm_playback_ana->name, "Analog playback");
628 /* Associate private data to PCM device */
629 pcm_playback_ana->private_data = pcm_device;
630 /* set operators of PCM device */
631 snd_pcm_set_ops(pcm_playback_ana, SNDRV_PCM_STREAM_PLAYBACK,
632 &snd_aw2_playback_ops);
633 /* store PCM device */
634 pcm_device->pcm = pcm_playback_ana;
635 /* give base chip pointer to our internal pcm device
636 structure */
637 pcm_device->chip = chip;
638 /* Give stream number to PCM device */
639 pcm_device->stream_number = NUM_STREAM_PLAYBACK_ANA;
640
641 /* pre-allocation of buffers */
642 /* Preallocate continuous pages. */
643 err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_ana,
644 SNDRV_DMA_TYPE_DEV,
645 snd_dma_pci_data
646 (chip->pci),
647 64 * 1024, 64 * 1024);
648 if (err)
649 printk(KERN_ERR "aw2: snd_pcm_lib_preallocate_pages_for_all "
650 "error (0x%X)\n", err);
651
652 err = snd_pcm_new(chip->card, "Audiowerk2 digital playback", 1, 1, 0,
653 &pcm_playback_num);
654
655 if (err < 0) {
656 printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
657 return err;
658 }
659 /* Creation ok */
660 pcm_device = &chip->device_playback[NUM_STREAM_PLAYBACK_DIG];
661
662 /* Set PCM device name */
663 strcpy(pcm_playback_num->name, "Digital playback");
664 /* Associate private data to PCM device */
665 pcm_playback_num->private_data = pcm_device;
666 /* set operators of PCM device */
667 snd_pcm_set_ops(pcm_playback_num, SNDRV_PCM_STREAM_PLAYBACK,
668 &snd_aw2_playback_ops);
669 /* store PCM device */
670 pcm_device->pcm = pcm_playback_num;
671 /* give base chip pointer to our internal pcm device
672 structure */
673 pcm_device->chip = chip;
674 /* Give stream number to PCM device */
675 pcm_device->stream_number = NUM_STREAM_PLAYBACK_DIG;
676
677 /* pre-allocation of buffers */
678 /* Preallocate continuous pages. */
679 err = snd_pcm_lib_preallocate_pages_for_all(pcm_playback_num,
680 SNDRV_DMA_TYPE_DEV,
681 snd_dma_pci_data
682 (chip->pci),
683 64 * 1024, 64 * 1024);
684 if (err)
685 printk(KERN_ERR
686 "aw2: snd_pcm_lib_preallocate_pages_for_all error "
687 "(0x%X)\n", err);
688
689
690
691 err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1,
692 &pcm_capture);
693
694 if (err < 0) {
695 printk(KERN_ERR "aw2: snd_pcm_new error (0x%X)\n", err);
696 return err;
697 }
698
699 /* Creation ok */
700 pcm_device = &chip->device_capture[NUM_STREAM_CAPTURE_ANA];
701
702 /* Set PCM device name */
703 strcpy(pcm_capture->name, "Capture");
704 /* Associate private data to PCM device */
705 pcm_capture->private_data = pcm_device;
706 /* set operators of PCM device */
707 snd_pcm_set_ops(pcm_capture, SNDRV_PCM_STREAM_CAPTURE,
708 &snd_aw2_capture_ops);
709 /* store PCM device */
710 pcm_device->pcm = pcm_capture;
711 /* give base chip pointer to our internal pcm device
712 structure */
713 pcm_device->chip = chip;
714 /* Give stream number to PCM device */
715 pcm_device->stream_number = NUM_STREAM_CAPTURE_ANA;
716
717 /* pre-allocation of buffers */
718 /* Preallocate continuous pages. */
719 err = snd_pcm_lib_preallocate_pages_for_all(pcm_capture,
720 SNDRV_DMA_TYPE_DEV,
721 snd_dma_pci_data
722 (chip->pci),
723 64 * 1024, 64 * 1024);
724 if (err)
725 printk(KERN_ERR
726 "aw2: snd_pcm_lib_preallocate_pages_for_all error "
727 "(0x%X)\n", err);
728
729
730 /* Create control */
731 err = snd_ctl_add(chip->card, snd_ctl_new1(&aw2_control, chip));
732 if (err < 0) {
733 printk(KERN_ERR "aw2: snd_ctl_add error (0x%X)\n", err);
734 return err;
735 }
736
737 return 0;
738}
739
740static int snd_aw2_control_switch_capture_info(struct snd_kcontrol *kcontrol,
741 struct snd_ctl_elem_info *uinfo)
742{
743 static char *texts[2] = {
744 "Analog", "Digital"
745 };
746 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
747 uinfo->count = 1;
748 uinfo->value.enumerated.items = 2;
749 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) {
750 uinfo->value.enumerated.item =
751 uinfo->value.enumerated.items - 1;
752 }
753 strcpy(uinfo->value.enumerated.name,
754 texts[uinfo->value.enumerated.item]);
755 return 0;
756}
757
758static int snd_aw2_control_switch_capture_get(struct snd_kcontrol *kcontrol,
759 struct snd_ctl_elem_value
760 *ucontrol)
761{
762 struct aw2 *chip = snd_kcontrol_chip(kcontrol);
763 if (snd_aw2_saa7146_is_using_digital_input(&chip->saa7146))
764 ucontrol->value.enumerated.item[0] = CTL_ROUTE_DIGITAL;
765 else
766 ucontrol->value.enumerated.item[0] = CTL_ROUTE_ANALOG;
767 return 0;
768}
769
770static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
771 struct snd_ctl_elem_value
772 *ucontrol)
773{
774 struct aw2 *chip = snd_kcontrol_chip(kcontrol);
775 int changed = 0;
776 int is_disgital =
777 snd_aw2_saa7146_is_using_digital_input(&chip->saa7146);
778
779 if (((ucontrol->value.integer.value[0] == CTL_ROUTE_DIGITAL)
780 && !is_disgital)
781 || ((ucontrol->value.integer.value[0] == CTL_ROUTE_ANALOG)
782 && is_disgital)) {
783 snd_aw2_saa7146_use_digital_input(&chip->saa7146, !is_disgital);
784 changed = 1;
785 }
786 return changed;
787}
diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c
new file mode 100644
index 000000000000..f20f213489a3
--- /dev/null
+++ b/sound/pci/aw2/aw2-saa7146.c
@@ -0,0 +1,464 @@
1/*****************************************************************************
2 *
3 * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
4 * Jean-Christian Hassler <jhassler@free.fr>
5 *
6 * This file is part of the Audiowerk2 ALSA driver
7 *
8 * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.
11 *
12 * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
21 *
22 *****************************************************************************/
23
24#define AW2_SAA7146_M
25
26#include <linux/init.h>
27#include <linux/pci.h>
28#include <linux/slab.h>
29#include <linux/interrupt.h>
30#include <linux/delay.h>
31#include <asm/system.h>
32#include <asm/io.h>
33#include <sound/core.h>
34#include <sound/initval.h>
35#include <sound/pcm.h>
36#include <sound/pcm_params.h>
37
38#include "aw2-tsl.h"
39#include "saa7146.h"
40#include "aw2-saa7146.h"
41
42#define WRITEREG(value, addr) writel((value), chip->base_addr + (addr))
43#define READREG(addr) readl(chip->base_addr + (addr))
44
45static struct snd_aw2_saa7146_cb_param
46 arr_substream_it_playback_cb[NB_STREAM_PLAYBACK];
47static struct snd_aw2_saa7146_cb_param
48 arr_substream_it_capture_cb[NB_STREAM_CAPTURE];
49
50static int snd_aw2_saa7146_get_limit(int size);
51
52/* chip-specific destructor */
53int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip)
54{
55 /* disable all irqs */
56 WRITEREG(0, IER);
57
58 /* reset saa7146 */
59 WRITEREG((MRST_N << 16), MC1);
60
61 /* Unset base addr */
62 chip->base_addr = NULL;
63
64 return 0;
65}
66
67void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
68 void __iomem *pci_base_addr)
69{
70 /* set PCI burst/threshold
71
72 Burst length definition
73 VALUE BURST LENGTH
74 000 1 Dword
75 001 2 Dwords
76 010 4 Dwords
77 011 8 Dwords
78 100 16 Dwords
79 101 32 Dwords
80 110 64 Dwords
81 111 128 Dwords
82
83 Threshold definition
84 VALUE WRITE MODE READ MODE
85 00 1 Dword of valid data 1 empty Dword
86 01 4 Dwords of valid data 4 empty Dwords
87 10 8 Dwords of valid data 8 empty Dwords
88 11 16 Dwords of valid data 16 empty Dwords */
89
90 unsigned int acon2;
91 unsigned int acon1 = 0;
92 int i;
93
94 /* Set base addr */
95 chip->base_addr = pci_base_addr;
96
97 /* disable all irqs */
98 WRITEREG(0, IER);
99
100 /* reset saa7146 */
101 WRITEREG((MRST_N << 16), MC1);
102
103 /* enable audio interface */
104#ifdef __BIG_ENDIAN
105 acon1 |= A1_SWAP;
106 acon1 |= A2_SWAP;
107#endif
108 /* WS0_CTRL, WS0_SYNC: input TSL1, I2S */
109
110 /* At initialization WS1 and WS2 are disbaled (configured as input */
111 acon1 |= 0 * WS1_CTRL;
112 acon1 |= 0 * WS2_CTRL;
113
114 /* WS4 is not used. So it must not restart A2.
115 This is why it is configured as output (force to low) */
116 acon1 |= 3 * WS4_CTRL;
117
118 /* WS3_CTRL, WS3_SYNC: output TSL2, I2S */
119 acon1 |= 2 * WS3_CTRL;
120
121 /* A1 and A2 are active and asynchronous */
122 acon1 |= 3 * AUDIO_MODE;
123 WRITEREG(acon1, ACON1);
124
125 /* The following comes from original windows driver.
126 It is needed to have a correct behavior of input and output
127 simultenously, but I don't know why ! */
128 WRITEREG(3 * (BurstA1_in) + 3 * (ThreshA1_in) +
129 3 * (BurstA1_out) + 3 * (ThreshA1_out) +
130 3 * (BurstA2_out) + 3 * (ThreshA2_out), PCI_BT_A);
131
132 /* enable audio port pins */
133 WRITEREG((EAP << 16) | EAP, MC1);
134
135 /* enable I2C */
136 WRITEREG((EI2C << 16) | EI2C, MC1);
137 /* enable interrupts */
138 WRITEREG(A1_out | A2_out | A1_in | IIC_S | IIC_E, IER);
139
140 /* audio configuration */
141 acon2 = A2_CLKSRC | BCLK1_OEN;
142 WRITEREG(acon2, ACON2);
143
144 /* By default use analog input */
145 snd_aw2_saa7146_use_digital_input(chip, 0);
146
147 /* TSL setup */
148 for (i = 0; i < 8; ++i) {
149 WRITEREG(tsl1[i], TSL1 + (i * 4));
150 WRITEREG(tsl2[i], TSL2 + (i * 4));
151 }
152
153}
154
155void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
156 int stream_number,
157 unsigned long dma_addr,
158 unsigned long period_size,
159 unsigned long buffer_size)
160{
161 unsigned long dw_page, dw_limit;
162
163 /* Configure DMA for substream
164 Configuration informations: ALSA has allocated continuous memory
165 pages. So we don't need to use MMU of saa7146.
166 */
167
168 /* No MMU -> nothing to do with PageA1, we only configure the limit of
169 PageAx_out register */
170 /* Disable MMU */
171 dw_page = (0L << 11);
172
173 /* Configure Limit for DMA access.
174 The limit register defines an address limit, which generates
175 an interrupt if passed by the actual PCI address pointer.
176 '0001' means an interrupt will be generated if the lower
177 6 bits (64 bytes) of the PCI address are zero. '0010'
178 defines a limit of 128 bytes, '0011' one of 256 bytes, and
179 so on up to 1 Mbyte defined by '1111'. This interrupt range
180 can be calculated as follows:
181 Range = 2^(5 + Limit) bytes.
182 */
183 dw_limit = snd_aw2_saa7146_get_limit(period_size);
184 dw_page |= (dw_limit << 4);
185
186 if (stream_number == 0) {
187 WRITEREG(dw_page, PageA2_out);
188
189 /* Base address for DMA transfert. */
190 /* This address has been reserved by ALSA. */
191 /* This is a physical address */
192 WRITEREG(dma_addr, BaseA2_out);
193
194 /* Define upper limit for DMA access */
195 WRITEREG(dma_addr + buffer_size, ProtA2_out);
196
197 } else if (stream_number == 1) {
198 WRITEREG(dw_page, PageA1_out);
199
200 /* Base address for DMA transfert. */
201 /* This address has been reserved by ALSA. */
202 /* This is a physical address */
203 WRITEREG(dma_addr, BaseA1_out);
204
205 /* Define upper limit for DMA access */
206 WRITEREG(dma_addr + buffer_size, ProtA1_out);
207 } else {
208 printk(KERN_ERR
209 "aw2: snd_aw2_saa7146_pcm_init_playback: "
210 "Substream number is not 0 or 1 -> not managed\n");
211 }
212}
213
214void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
215 int stream_number, unsigned long dma_addr,
216 unsigned long period_size,
217 unsigned long buffer_size)
218{
219 unsigned long dw_page, dw_limit;
220
221 /* Configure DMA for substream
222 Configuration informations: ALSA has allocated continuous memory
223 pages. So we don't need to use MMU of saa7146.
224 */
225
226 /* No MMU -> nothing to do with PageA1, we only configure the limit of
227 PageAx_out register */
228 /* Disable MMU */
229 dw_page = (0L << 11);
230
231 /* Configure Limit for DMA access.
232 The limit register defines an address limit, which generates
233 an interrupt if passed by the actual PCI address pointer.
234 '0001' means an interrupt will be generated if the lower
235 6 bits (64 bytes) of the PCI address are zero. '0010'
236 defines a limit of 128 bytes, '0011' one of 256 bytes, and
237 so on up to 1 Mbyte defined by '1111'. This interrupt range
238 can be calculated as follows:
239 Range = 2^(5 + Limit) bytes.
240 */
241 dw_limit = snd_aw2_saa7146_get_limit(period_size);
242 dw_page |= (dw_limit << 4);
243
244 if (stream_number == 0) {
245 WRITEREG(dw_page, PageA1_in);
246
247 /* Base address for DMA transfert. */
248 /* This address has been reserved by ALSA. */
249 /* This is a physical address */
250 WRITEREG(dma_addr, BaseA1_in);
251
252 /* Define upper limit for DMA access */
253 WRITEREG(dma_addr + buffer_size, ProtA1_in);
254 } else {
255 printk(KERN_ERR
256 "aw2: snd_aw2_saa7146_pcm_init_capture: "
257 "Substream number is not 0 -> not managed\n");
258 }
259}
260
261void snd_aw2_saa7146_define_it_playback_callback(unsigned int stream_number,
262 snd_aw2_saa7146_it_cb
263 p_it_callback,
264 void *p_callback_param)
265{
266 if (stream_number < NB_STREAM_PLAYBACK) {
267 arr_substream_it_playback_cb[stream_number].p_it_callback =
268 (snd_aw2_saa7146_it_cb) p_it_callback;
269 arr_substream_it_playback_cb[stream_number].p_callback_param =
270 (void *)p_callback_param;
271 }
272}
273
274void snd_aw2_saa7146_define_it_capture_callback(unsigned int stream_number,
275 snd_aw2_saa7146_it_cb
276 p_it_callback,
277 void *p_callback_param)
278{
279 if (stream_number < NB_STREAM_CAPTURE) {
280 arr_substream_it_capture_cb[stream_number].p_it_callback =
281 (snd_aw2_saa7146_it_cb) p_it_callback;
282 arr_substream_it_capture_cb[stream_number].p_callback_param =
283 (void *)p_callback_param;
284 }
285}
286
287void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146 *chip,
288 int stream_number)
289{
290 unsigned int acon1 = 0;
291 /* In aw8 driver, dma transfert is always active. It is
292 started and stopped in a larger "space" */
293 acon1 = READREG(ACON1);
294 if (stream_number == 0) {
295 WRITEREG((TR_E_A2_OUT << 16) | TR_E_A2_OUT, MC1);
296
297 /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
298 acon1 |= 2 * WS2_CTRL;
299 WRITEREG(acon1, ACON1);
300
301 } else if (stream_number == 1) {
302 WRITEREG((TR_E_A1_OUT << 16) | TR_E_A1_OUT, MC1);
303
304 /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
305 acon1 |= 1 * WS1_CTRL;
306 WRITEREG(acon1, ACON1);
307 }
308}
309
310void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146 *chip,
311 int stream_number)
312{
313 unsigned int acon1 = 0;
314 acon1 = READREG(ACON1);
315 if (stream_number == 0) {
316 /* WS2_CTRL, WS2_SYNC: output TSL2, I2S */
317 acon1 &= ~(3 * WS2_CTRL);
318 WRITEREG(acon1, ACON1);
319
320 WRITEREG((TR_E_A2_OUT << 16), MC1);
321 } else if (stream_number == 1) {
322 /* WS1_CTRL, WS1_SYNC: output TSL1, I2S */
323 acon1 &= ~(3 * WS1_CTRL);
324 WRITEREG(acon1, ACON1);
325
326 WRITEREG((TR_E_A1_OUT << 16), MC1);
327 }
328}
329
330void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146 *chip,
331 int stream_number)
332{
333 /* In aw8 driver, dma transfert is always active. It is
334 started and stopped in a larger "space" */
335 if (stream_number == 0)
336 WRITEREG((TR_E_A1_IN << 16) | TR_E_A1_IN, MC1);
337}
338
339void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146 *chip,
340 int stream_number)
341{
342 if (stream_number == 0)
343 WRITEREG((TR_E_A1_IN << 16), MC1);
344}
345
346irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id)
347{
348 unsigned int isr;
349 unsigned int iicsta;
350 struct snd_aw2_saa7146 *chip = dev_id;
351
352 isr = READREG(ISR);
353 if (!isr)
354 return IRQ_NONE;
355
356 WRITEREG(isr, ISR);
357
358 if (isr & (IIC_S | IIC_E)) {
359 iicsta = READREG(IICSTA);
360 WRITEREG(0x100, IICSTA);
361 }
362
363 if (isr & A1_out) {
364 if (arr_substream_it_playback_cb[1].p_it_callback != NULL) {
365 arr_substream_it_playback_cb[1].
366 p_it_callback(arr_substream_it_playback_cb[1].
367 p_callback_param);
368 }
369 }
370 if (isr & A2_out) {
371 if (arr_substream_it_playback_cb[0].p_it_callback != NULL) {
372 arr_substream_it_playback_cb[0].
373 p_it_callback(arr_substream_it_playback_cb[0].
374 p_callback_param);
375 }
376
377 }
378 if (isr & A1_in) {
379 if (arr_substream_it_capture_cb[0].p_it_callback != NULL) {
380 arr_substream_it_capture_cb[0].
381 p_it_callback(arr_substream_it_capture_cb[0].
382 p_callback_param);
383 }
384 }
385 return IRQ_HANDLED;
386}
387
388unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146 *chip,
389 int stream_number,
390 unsigned char *start_addr,
391 unsigned int buffer_size)
392{
393 long pci_adp = 0;
394 size_t ptr = 0;
395
396 if (stream_number == 0) {
397 pci_adp = READREG(PCI_ADP3);
398 ptr = pci_adp - (long)start_addr;
399
400 if (ptr == buffer_size)
401 ptr = 0;
402 }
403 if (stream_number == 1) {
404 pci_adp = READREG(PCI_ADP1);
405 ptr = pci_adp - (size_t) start_addr;
406
407 if (ptr == buffer_size)
408 ptr = 0;
409 }
410 return ptr;
411}
412
413unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146 *chip,
414 int stream_number,
415 unsigned char *start_addr,
416 unsigned int buffer_size)
417{
418 size_t pci_adp = 0;
419 size_t ptr = 0;
420 if (stream_number == 0) {
421 pci_adp = READREG(PCI_ADP2);
422 ptr = pci_adp - (size_t) start_addr;
423
424 if (ptr == buffer_size)
425 ptr = 0;
426 }
427 return ptr;
428}
429
430void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
431 int use_digital)
432{
433 /* FIXME: switch between analog and digital input does not always work.
434 It can produce a kind of white noise. It seams that received data
435 are inverted sometime (endian inversion). Why ? I don't know, maybe
436 a problem of synchronization... However for the time being I have
437 not found the problem. Workaround: switch again (and again) between
438 digital and analog input until it works. */
439 if (use_digital)
440 WRITEREG(0x40, GPIO_CTRL);
441 else
442 WRITEREG(0x50, GPIO_CTRL);
443}
444
445int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146 *chip)
446{
447 unsigned int reg_val = READREG(GPIO_CTRL);
448 if ((reg_val & 0xFF) == 0x40)
449 return 1;
450 else
451 return 0;
452}
453
454
455static int snd_aw2_saa7146_get_limit(int size)
456{
457 int limitsize = 32;
458 int limit = 0;
459 while (limitsize < size) {
460 limitsize *= 2;
461 limit++;
462 }
463 return limit;
464}
diff --git a/sound/pci/aw2/aw2-saa7146.h b/sound/pci/aw2/aw2-saa7146.h
new file mode 100644
index 000000000000..5b35e358937f
--- /dev/null
+++ b/sound/pci/aw2/aw2-saa7146.h
@@ -0,0 +1,105 @@
1/*****************************************************************************
2 *
3 * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
4 * Jean-Christian Hassler <jhassler@free.fr>
5 *
6 * This file is part of the Audiowerk2 ALSA driver
7 *
8 * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.
11 *
12 * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
21 *
22 *****************************************************************************/
23
24#ifndef AW2_SAA7146_H
25#define AW2_SAA7146_H
26
27#define NB_STREAM_PLAYBACK 2
28#define NB_STREAM_CAPTURE 1
29
30#define NUM_STREAM_PLAYBACK_ANA 0
31#define NUM_STREAM_PLAYBACK_DIG 1
32
33#define NUM_STREAM_CAPTURE_ANA 0
34
35typedef void (*snd_aw2_saa7146_it_cb) (void *);
36
37struct snd_aw2_saa7146_cb_param {
38 snd_aw2_saa7146_it_cb p_it_callback;
39 void *p_callback_param;
40};
41
42/* definition of the chip-specific record */
43
44struct snd_aw2_saa7146 {
45 void __iomem *base_addr;
46};
47
48extern void snd_aw2_saa7146_setup(struct snd_aw2_saa7146 *chip,
49 void __iomem *pci_base_addr);
50extern int snd_aw2_saa7146_free(struct snd_aw2_saa7146 *chip);
51
52extern void snd_aw2_saa7146_pcm_init_playback(struct snd_aw2_saa7146 *chip,
53 int stream_number,
54 unsigned long dma_addr,
55 unsigned long period_size,
56 unsigned long buffer_size);
57extern void snd_aw2_saa7146_pcm_init_capture(struct snd_aw2_saa7146 *chip,
58 int stream_number,
59 unsigned long dma_addr,
60 unsigned long period_size,
61 unsigned long buffer_size);
62extern void snd_aw2_saa7146_define_it_playback_callback(unsigned int
63 stream_number,
64 snd_aw2_saa7146_it_cb
65 p_it_callback,
66 void *p_callback_param);
67extern void snd_aw2_saa7146_define_it_capture_callback(unsigned int
68 stream_number,
69 snd_aw2_saa7146_it_cb
70 p_it_callback,
71 void *p_callback_param);
72extern void snd_aw2_saa7146_pcm_trigger_start_capture(struct snd_aw2_saa7146
73 *chip, int stream_number);
74extern void snd_aw2_saa7146_pcm_trigger_stop_capture(struct snd_aw2_saa7146
75 *chip, int stream_number);
76
77extern void snd_aw2_saa7146_pcm_trigger_start_playback(struct snd_aw2_saa7146
78 *chip,
79 int stream_number);
80extern void snd_aw2_saa7146_pcm_trigger_stop_playback(struct snd_aw2_saa7146
81 *chip, int stream_number);
82
83extern irqreturn_t snd_aw2_saa7146_interrupt(int irq, void *dev_id);
84extern unsigned int snd_aw2_saa7146_get_hw_ptr_playback(struct snd_aw2_saa7146
85 *chip,
86 int stream_number,
87 unsigned char
88 *start_addr,
89 unsigned int
90 buffer_size);
91extern unsigned int snd_aw2_saa7146_get_hw_ptr_capture(struct snd_aw2_saa7146
92 *chip,
93 int stream_number,
94 unsigned char
95 *start_addr,
96 unsigned int
97 buffer_size);
98
99extern void snd_aw2_saa7146_use_digital_input(struct snd_aw2_saa7146 *chip,
100 int use_digital);
101
102extern int snd_aw2_saa7146_is_using_digital_input(struct snd_aw2_saa7146
103 *chip);
104
105#endif
diff --git a/sound/pci/aw2/aw2-tsl.h b/sound/pci/aw2/aw2-tsl.h
new file mode 100644
index 000000000000..e8afaa0a468a
--- /dev/null
+++ b/sound/pci/aw2/aw2-tsl.h
@@ -0,0 +1,116 @@
1/*****************************************************************************
2 *
3 * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
4 * Jean-Christian Hassler <jhassler@free.fr>
5 * Copyright 1998 Emagic Soft- und Hardware GmbH
6 * Copyright 2002 Martijn Sipkema
7 *
8 * This file is part of the Audiowerk2 ALSA driver
9 *
10 * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.
13 *
14 * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * USA.
23 *
24 *****************************************************************************/
25
26#define TSL_WS0 (1UL << 31)
27#define TSL_WS1 (1UL << 30)
28#define TSL_WS2 (1UL << 29)
29#define TSL_WS3 (1UL << 28)
30#define TSL_WS4 (1UL << 27)
31#define TSL_DIS_A1 (1UL << 24)
32#define TSL_SDW_A1 (1UL << 23)
33#define TSL_SIB_A1 (1UL << 22)
34#define TSL_SF_A1 (1UL << 21)
35#define TSL_LF_A1 (1UL << 20)
36#define TSL_BSEL_A1 (1UL << 17)
37#define TSL_DOD_A1 (1UL << 15)
38#define TSL_LOW_A1 (1UL << 14)
39#define TSL_DIS_A2 (1UL << 11)
40#define TSL_SDW_A2 (1UL << 10)
41#define TSL_SIB_A2 (1UL << 9)
42#define TSL_SF_A2 (1UL << 8)
43#define TSL_LF_A2 (1UL << 7)
44#define TSL_BSEL_A2 (1UL << 4)
45#define TSL_DOD_A2 (1UL << 2)
46#define TSL_LOW_A2 (1UL << 1)
47#define TSL_EOS (1UL << 0)
48
49 /* Audiowerk8 hardware setup: */
50 /* WS0, SD4, TSL1 - Analog/ digital in */
51 /* WS1, SD0, TSL1 - Analog out #1, digital out */
52 /* WS2, SD2, TSL1 - Analog out #2 */
53 /* WS3, SD1, TSL2 - Analog out #3 */
54 /* WS4, SD3, TSL2 - Analog out #4 */
55
56 /* Audiowerk8 timing: */
57 /* Timeslot: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... */
58
59 /* A1_INPUT: */
60 /* SD4: <_ADC-L_>-------<_ADC-R_>-------< */
61 /* WS0: _______________/---------------\_ */
62
63 /* A1_OUTPUT: */
64 /* SD0: <_1-L___>-------<_1-R___>-------< */
65 /* WS1: _______________/---------------\_ */
66 /* SD2: >-------<_2-L___>-------<_2-R___> */
67 /* WS2: -------\_______________/--------- */
68
69 /* A2_OUTPUT: */
70 /* SD1: <_3-L___>-------<_3-R___>-------< */
71 /* WS3: _______________/---------------\_ */
72 /* SD3: >-------<_4-L___>-------<_4-R___> */
73 /* WS4: -------\_______________/--------- */
74
75#ifdef __BIG_ENDIAN
76 /* TODO: not yet implemented */
77#else /* */
78
79static int tsl1[8] = {
80 1 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
81 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_LF_A1,
82
83 1 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
84 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
85
86 0 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
87 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
88
89 0 * TSL_SDW_A1 | 2 * TSL_BSEL_A1 |
90 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1,
91
92 1 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
93 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
94
95 1 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 |
96 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
97
98 0 * TSL_SDW_A1 | 1 * TSL_BSEL_A1 |
99 0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0,
100
101 0 * TSL_SDW_A1 | 0 * TSL_BSEL_A1 | 0 * TSL_DIS_A1 |
102 0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0 | TSL_SF_A1 | TSL_EOS,
103};
104
105static int tsl2[8] = {
106 0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_LF_A2,
107 0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
108 0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
109 0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
110 0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
111 0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
112 0 * TSL_SDW_A2 | 1 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2,
113 0 * TSL_SDW_A2 | 0 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_WS2 | TSL_EOS
114};
115
116#endif /* */
diff --git a/sound/pci/aw2/saa7146.h b/sound/pci/aw2/saa7146.h
new file mode 100644
index 000000000000..ce0ab5f9ee9c
--- /dev/null
+++ b/sound/pci/aw2/saa7146.h
@@ -0,0 +1,168 @@
1/*****************************************************************************
2 *
3 * Copyright (C) 2008 Cedric Bregardis <cedric.bregardis@free.fr> and
4 * Jean-Christian Hassler <jhassler@free.fr>
5 *
6 * This file is part of the Audiowerk2 ALSA driver
7 *
8 * The Audiowerk2 ALSA driver is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2.
11 *
12 * The Audiowerk2 ALSA driver is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with the Audiowerk2 ALSA driver; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
21 *
22 *****************************************************************************/
23
24/* SAA7146 registers */
25#define PCI_BT_A 0x4C
26#define IICTFR 0x8C
27#define IICSTA 0x90
28#define BaseA1_in 0x94
29#define ProtA1_in 0x98
30#define PageA1_in 0x9C
31#define BaseA1_out 0xA0
32#define ProtA1_out 0xA4
33#define PageA1_out 0xA8
34#define BaseA2_in 0xAC
35#define ProtA2_in 0xB0
36#define PageA2_in 0xB4
37#define BaseA2_out 0xB8
38#define ProtA2_out 0xBC
39#define PageA2_out 0xC0
40#define IER 0xDC
41#define GPIO_CTRL 0xE0
42#define ACON1 0xF4
43#define ACON2 0xF8
44#define MC1 0xFC
45#define MC2 0x100
46#define ISR 0x10C
47#define PSR 0x110
48#define SSR 0x114
49#define PCI_ADP1 0x12C
50#define PCI_ADP2 0x130
51#define PCI_ADP3 0x134
52#define PCI_ADP4 0x138
53#define LEVEL_REP 0x140
54#define FB_BUFFER1 0x144
55#define FB_BUFFER2 0x148
56#define TSL1 0x180
57#define TSL2 0x1C0
58
59#define ME (1UL << 11)
60#define LIMIT (1UL << 4)
61#define PV (1UL << 3)
62
63/* PSR/ISR/IER */
64#define PPEF (1UL << 31)
65#define PABO (1UL << 30)
66#define IIC_S (1UL << 17)
67#define IIC_E (1UL << 16)
68#define A2_in (1UL << 15)
69#define A2_out (1UL << 14)
70#define A1_in (1UL << 13)
71#define A1_out (1UL << 12)
72#define AFOU (1UL << 11)
73#define PIN3 (1UL << 6)
74#define PIN2 (1UL << 5)
75#define PIN1 (1UL << 4)
76#define PIN0 (1UL << 3)
77#define ECS (1UL << 2)
78#define EC3S (1UL << 1)
79#define EC0S (1UL << 0)
80
81/* SSR */
82#define PRQ (1UL << 31)
83#define PMA (1UL << 30)
84#define IIC_EA (1UL << 21)
85#define IIC_EW (1UL << 20)
86#define IIC_ER (1UL << 19)
87#define IIC_EL (1UL << 18)
88#define IIC_EF (1UL << 17)
89#define AF2_in (1UL << 10)
90#define AF2_out (1UL << 9)
91#define AF1_in (1UL << 8)
92#define AF1_out (1UL << 7)
93#define EC5S (1UL << 3)
94#define EC4S (1UL << 2)
95#define EC2S (1UL << 1)
96#define EC1S (1UL << 0)
97
98/* PCI_BT_A */
99#define BurstA1_in (1UL << 26)
100#define ThreshA1_in (1UL << 24)
101#define BurstA1_out (1UL << 18)
102#define ThreshA1_out (1UL << 16)
103#define BurstA2_in (1UL << 10)
104#define ThreshA2_in (1UL << 8)
105#define BurstA2_out (1UL << 2)
106#define ThreshA2_out (1UL << 0)
107
108/* MC1 */
109#define MRST_N (1UL << 15)
110#define EAP (1UL << 9)
111#define EI2C (1UL << 8)
112#define TR_E_A2_OUT (1UL << 3)
113#define TR_E_A2_IN (1UL << 2)
114#define TR_E_A1_OUT (1UL << 1)
115#define TR_E_A1_IN (1UL << 0)
116
117/* MC2 */
118#define UPLD_IIC (1UL << 0)
119
120/* ACON1 */
121#define AUDIO_MODE (1UL << 29)
122#define MAXLEVEL (1UL << 22)
123#define A1_SWAP (1UL << 21)
124#define A2_SWAP (1UL << 20)
125#define WS0_CTRL (1UL << 18)
126#define WS0_SYNC (1UL << 16)
127#define WS1_CTRL (1UL << 14)
128#define WS1_SYNC (1UL << 12)
129#define WS2_CTRL (1UL << 10)
130#define WS2_SYNC (1UL << 8)
131#define WS3_CTRL (1UL << 6)
132#define WS3_SYNC (1UL << 4)
133#define WS4_CTRL (1UL << 2)
134#define WS4_SYNC (1UL << 0)
135
136/* ACON2 */
137#define A1_CLKSRC (1UL << 27)
138#define A2_CLKSRC (1UL << 22)
139#define INVERT_BCLK1 (1UL << 21)
140#define INVERT_BCLK2 (1UL << 20)
141#define BCLK1_OEN (1UL << 19)
142#define BCLK2_OEN (1UL << 18)
143
144/* IICSTA */
145#define IICCC (1UL << 8)
146#define ABORT (1UL << 7)
147#define SPERR (1UL << 6)
148#define APERR (1UL << 5)
149#define DTERR (1UL << 4)
150#define DRERR (1UL << 3)
151#define AL (1UL << 2)
152#define ERR (1UL << 1)
153#define BUSY (1UL << 0)
154
155/* IICTFR */
156#define BYTE2 (1UL << 24)
157#define BYTE1 (1UL << 16)
158#define BYTE0 (1UL << 8)
159#define ATRR2 (1UL << 6)
160#define ATRR1 (1UL << 4)
161#define ATRR0 (1UL << 2)
162#define ERR (1UL << 1)
163#define BUSY (1UL << 0)
164
165#define START 3
166#define CONT 2
167#define STOP 1
168#define NOP 0