11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * ALSA driver for RME Digi32, Digi32/8 and Digi32 PRO audio interfaces 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (c) 2002-2004 Martin Langer <martin-langer@gmx.de>, 51da177e4SLinus Torvalds * Pilo Chambert <pilo.c@wanadoo.fr> 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Thanks to : Anders Torger <torger@ludd.luth.se>, 81da177e4SLinus Torvalds * Henk Hesselink <henk@anda.nl> 91da177e4SLinus Torvalds * for writing the digi96-driver 101da177e4SLinus Torvalds * and RME for all informations. 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 131da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 141da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 151da177e4SLinus Torvalds * (at your option) any later version. 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 181da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 191da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 201da177e4SLinus Torvalds * GNU General Public License for more details. 211da177e4SLinus Torvalds * 221da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 231da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 241da177e4SLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 251da177e4SLinus Torvalds * 261da177e4SLinus Torvalds * 271da177e4SLinus Torvalds * **************************************************************************** 281da177e4SLinus Torvalds * 291da177e4SLinus Torvalds * Note #1 "Sek'd models" ................................... martin 2002-12-07 301da177e4SLinus Torvalds * 311da177e4SLinus Torvalds * Identical soundcards by Sek'd were labeled: 321da177e4SLinus Torvalds * RME Digi 32 = Sek'd Prodif 32 331da177e4SLinus Torvalds * RME Digi 32 Pro = Sek'd Prodif 96 341da177e4SLinus Torvalds * RME Digi 32/8 = Sek'd Prodif Gold 351da177e4SLinus Torvalds * 361da177e4SLinus Torvalds * **************************************************************************** 371da177e4SLinus Torvalds * 381da177e4SLinus Torvalds * Note #2 "full duplex mode" ............................... martin 2002-12-07 391da177e4SLinus Torvalds * 401da177e4SLinus Torvalds * Full duplex doesn't work. All cards (32, 32/8, 32Pro) are working identical 411da177e4SLinus Torvalds * in this mode. Rec data and play data are using the same buffer therefore. At 421da177e4SLinus Torvalds * first you have got the playing bits in the buffer and then (after playing 431da177e4SLinus Torvalds * them) they were overwitten by the captured sound of the CS8412/14. Both 441da177e4SLinus Torvalds * modes (play/record) are running harmonically hand in hand in the same buffer 451da177e4SLinus Torvalds * and you have only one start bit plus one interrupt bit to control this 461da177e4SLinus Torvalds * paired action. 471da177e4SLinus Torvalds * This is opposite to the latter rme96 where playing and capturing is totally 481da177e4SLinus Torvalds * separated and so their full duplex mode is supported by alsa (using two 491da177e4SLinus Torvalds * start bits and two interrupts for two different buffers). 501da177e4SLinus Torvalds * But due to the wrong sequence of playing and capturing ALSA shows no solved 511da177e4SLinus Torvalds * full duplex support for the rme32 at the moment. That's bad, but I'm not 521da177e4SLinus Torvalds * able to solve it. Are you motivated enough to solve this problem now? Your 531da177e4SLinus Torvalds * patch would be welcome! 541da177e4SLinus Torvalds * 551da177e4SLinus Torvalds * **************************************************************************** 561da177e4SLinus Torvalds * 571da177e4SLinus Torvalds * "The story after the long seeking" -- tiwai 581da177e4SLinus Torvalds * 591da177e4SLinus Torvalds * Ok, the situation regarding the full duplex is now improved a bit. 601da177e4SLinus Torvalds * In the fullduplex mode (given by the module parameter), the hardware buffer 611da177e4SLinus Torvalds * is split to halves for read and write directions at the DMA pointer. 621da177e4SLinus Torvalds * That is, the half above the current DMA pointer is used for write, and 631da177e4SLinus Torvalds * the half below is used for read. To mangle this strange behavior, an 641da177e4SLinus Torvalds * software intermediate buffer is introduced. This is, of course, not good 651da177e4SLinus Torvalds * from the viewpoint of the data transfer efficiency. However, this allows 661da177e4SLinus Torvalds * you to use arbitrary buffer sizes, instead of the fixed I/O buffer size. 671da177e4SLinus Torvalds * 681da177e4SLinus Torvalds * **************************************************************************** 691da177e4SLinus Torvalds */ 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds #include <linux/delay.h> 735a0e3ad6STejun Heo #include <linux/gfp.h> 741da177e4SLinus Torvalds #include <linux/init.h> 751da177e4SLinus Torvalds #include <linux/interrupt.h> 761da177e4SLinus Torvalds #include <linux/pci.h> 7765a77217SPaul Gortmaker #include <linux/module.h> 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds #include <sound/core.h> 801da177e4SLinus Torvalds #include <sound/info.h> 811da177e4SLinus Torvalds #include <sound/control.h> 821da177e4SLinus Torvalds #include <sound/pcm.h> 831da177e4SLinus Torvalds #include <sound/pcm_params.h> 841da177e4SLinus Torvalds #include <sound/pcm-indirect.h> 851da177e4SLinus Torvalds #include <sound/asoundef.h> 861da177e4SLinus Torvalds #include <sound/initval.h> 871da177e4SLinus Torvalds 881da177e4SLinus Torvalds #include <asm/io.h> 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 911da177e4SLinus Torvalds static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 92a67ff6a5SRusty Russell static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 93a67ff6a5SRusty Russell static bool fullduplex[SNDRV_CARDS]; // = {[0 ... (SNDRV_CARDS - 1)] = 1}; 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds module_param_array(index, int, NULL, 0444); 961da177e4SLinus Torvalds MODULE_PARM_DESC(index, "Index value for RME Digi32 soundcard."); 971da177e4SLinus Torvalds module_param_array(id, charp, NULL, 0444); 981da177e4SLinus Torvalds MODULE_PARM_DESC(id, "ID string for RME Digi32 soundcard."); 991da177e4SLinus Torvalds module_param_array(enable, bool, NULL, 0444); 1001da177e4SLinus Torvalds MODULE_PARM_DESC(enable, "Enable RME Digi32 soundcard."); 1011da177e4SLinus Torvalds module_param_array(fullduplex, bool, NULL, 0444); 1021da177e4SLinus Torvalds MODULE_PARM_DESC(fullduplex, "Support full-duplex mode."); 1031da177e4SLinus Torvalds MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>, Pilo Chambert <pilo.c@wanadoo.fr>"); 1041da177e4SLinus Torvalds MODULE_DESCRIPTION("RME Digi32, Digi32/8, Digi32 PRO"); 1051da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 1061da177e4SLinus Torvalds MODULE_SUPPORTED_DEVICE("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}"); 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds /* Defines for RME Digi32 series */ 1091da177e4SLinus Torvalds #define RME32_SPDIF_NCHANNELS 2 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds /* Playback and capture buffer size */ 1121da177e4SLinus Torvalds #define RME32_BUFFER_SIZE 0x20000 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds /* IO area size */ 1151da177e4SLinus Torvalds #define RME32_IO_SIZE 0x30000 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds /* IO area offsets */ 1181da177e4SLinus Torvalds #define RME32_IO_DATA_BUFFER 0x0 1191da177e4SLinus Torvalds #define RME32_IO_CONTROL_REGISTER 0x20000 1201da177e4SLinus Torvalds #define RME32_IO_GET_POS 0x20000 1211da177e4SLinus Torvalds #define RME32_IO_CONFIRM_ACTION_IRQ 0x20004 1221da177e4SLinus Torvalds #define RME32_IO_RESET_POS 0x20100 1231da177e4SLinus Torvalds 1241da177e4SLinus Torvalds /* Write control register bits */ 1251da177e4SLinus Torvalds #define RME32_WCR_START (1 << 0) /* startbit */ 1261da177e4SLinus Torvalds #define RME32_WCR_MONO (1 << 1) /* 0=stereo, 1=mono 1271da177e4SLinus Torvalds Setting the whole card to mono 1281da177e4SLinus Torvalds doesn't seem to be very useful. 1291da177e4SLinus Torvalds A software-solution can handle 1301da177e4SLinus Torvalds full-duplex with one direction in 1311da177e4SLinus Torvalds stereo and the other way in mono. 1321da177e4SLinus Torvalds So, the hardware should work all 1331da177e4SLinus Torvalds the time in stereo! */ 1341da177e4SLinus Torvalds #define RME32_WCR_MODE24 (1 << 2) /* 0=16bit, 1=32bit */ 1351da177e4SLinus Torvalds #define RME32_WCR_SEL (1 << 3) /* 0=input on output, 1=normal playback/capture */ 1361da177e4SLinus Torvalds #define RME32_WCR_FREQ_0 (1 << 4) /* frequency (play) */ 1371da177e4SLinus Torvalds #define RME32_WCR_FREQ_1 (1 << 5) 1381da177e4SLinus Torvalds #define RME32_WCR_INP_0 (1 << 6) /* input switch */ 1391da177e4SLinus Torvalds #define RME32_WCR_INP_1 (1 << 7) 1401da177e4SLinus Torvalds #define RME32_WCR_RESET (1 << 8) /* Reset address */ 1411da177e4SLinus Torvalds #define RME32_WCR_MUTE (1 << 9) /* digital mute for output */ 1421da177e4SLinus Torvalds #define RME32_WCR_PRO (1 << 10) /* 1=professional, 0=consumer */ 1431da177e4SLinus Torvalds #define RME32_WCR_DS_BM (1 << 11) /* 1=DoubleSpeed (only PRO-Version); 1=BlockMode (only Adat-Version) */ 1441da177e4SLinus Torvalds #define RME32_WCR_ADAT (1 << 12) /* Adat Mode (only Adat-Version) */ 1451da177e4SLinus Torvalds #define RME32_WCR_AUTOSYNC (1 << 13) /* AutoSync */ 1461da177e4SLinus Torvalds #define RME32_WCR_PD (1 << 14) /* DAC Reset (only PRO-Version) */ 1471da177e4SLinus Torvalds #define RME32_WCR_EMP (1 << 15) /* 1=Emphasis on (only PRO-Version) */ 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds #define RME32_WCR_BITPOS_FREQ_0 4 1501da177e4SLinus Torvalds #define RME32_WCR_BITPOS_FREQ_1 5 1511da177e4SLinus Torvalds #define RME32_WCR_BITPOS_INP_0 6 1521da177e4SLinus Torvalds #define RME32_WCR_BITPOS_INP_1 7 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds /* Read control register bits */ 1551da177e4SLinus Torvalds #define RME32_RCR_AUDIO_ADDR_MASK 0x1ffff 1561da177e4SLinus Torvalds #define RME32_RCR_LOCK (1 << 23) /* 1=locked, 0=not locked */ 1571da177e4SLinus Torvalds #define RME32_RCR_ERF (1 << 26) /* 1=Error, 0=no Error */ 1581da177e4SLinus Torvalds #define RME32_RCR_FREQ_0 (1 << 27) /* CS841x frequency (record) */ 1591da177e4SLinus Torvalds #define RME32_RCR_FREQ_1 (1 << 28) 1601da177e4SLinus Torvalds #define RME32_RCR_FREQ_2 (1 << 29) 1611da177e4SLinus Torvalds #define RME32_RCR_KMODE (1 << 30) /* card mode: 1=PLL, 0=quartz */ 1621da177e4SLinus Torvalds #define RME32_RCR_IRQ (1 << 31) /* interrupt */ 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds #define RME32_RCR_BITPOS_F0 27 1651da177e4SLinus Torvalds #define RME32_RCR_BITPOS_F1 28 1661da177e4SLinus Torvalds #define RME32_RCR_BITPOS_F2 29 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds /* Input types */ 1691da177e4SLinus Torvalds #define RME32_INPUT_OPTICAL 0 1701da177e4SLinus Torvalds #define RME32_INPUT_COAXIAL 1 1711da177e4SLinus Torvalds #define RME32_INPUT_INTERNAL 2 1721da177e4SLinus Torvalds #define RME32_INPUT_XLR 3 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds /* Clock modes */ 1751da177e4SLinus Torvalds #define RME32_CLOCKMODE_SLAVE 0 1761da177e4SLinus Torvalds #define RME32_CLOCKMODE_MASTER_32 1 1771da177e4SLinus Torvalds #define RME32_CLOCKMODE_MASTER_44 2 1781da177e4SLinus Torvalds #define RME32_CLOCKMODE_MASTER_48 3 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds /* Block sizes in bytes */ 1811da177e4SLinus Torvalds #define RME32_BLOCK_SIZE 8192 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds /* Software intermediate buffer (max) size */ 1841da177e4SLinus Torvalds #define RME32_MID_BUFFER_SIZE (1024*1024) 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds /* Hardware revisions */ 1871da177e4SLinus Torvalds #define RME32_32_REVISION 192 1881da177e4SLinus Torvalds #define RME32_328_REVISION_OLD 100 1891da177e4SLinus Torvalds #define RME32_328_REVISION_NEW 101 1901da177e4SLinus Torvalds #define RME32_PRO_REVISION_WITH_8412 192 1911da177e4SLinus Torvalds #define RME32_PRO_REVISION_WITH_8414 150 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds 194017ce802STakashi Iwai struct rme32 { 1951da177e4SLinus Torvalds spinlock_t lock; 1961da177e4SLinus Torvalds int irq; 1971da177e4SLinus Torvalds unsigned long port; 1981da177e4SLinus Torvalds void __iomem *iobase; 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds u32 wcreg; /* cached write control register value */ 2011da177e4SLinus Torvalds u32 wcreg_spdif; /* S/PDIF setup */ 2021da177e4SLinus Torvalds u32 wcreg_spdif_stream; /* S/PDIF setup (temporary) */ 2031da177e4SLinus Torvalds u32 rcreg; /* cached read control register value */ 2041da177e4SLinus Torvalds 2051da177e4SLinus Torvalds u8 rev; /* card revision number */ 2061da177e4SLinus Torvalds 207017ce802STakashi Iwai struct snd_pcm_substream *playback_substream; 208017ce802STakashi Iwai struct snd_pcm_substream *capture_substream; 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds int playback_frlog; /* log2 of framesize */ 2111da177e4SLinus Torvalds int capture_frlog; 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds size_t playback_periodsize; /* in bytes, zero if not used */ 2141da177e4SLinus Torvalds size_t capture_periodsize; /* in bytes, zero if not used */ 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds unsigned int fullduplex_mode; 2171da177e4SLinus Torvalds int running; 2181da177e4SLinus Torvalds 219017ce802STakashi Iwai struct snd_pcm_indirect playback_pcm; 220017ce802STakashi Iwai struct snd_pcm_indirect capture_pcm; 2211da177e4SLinus Torvalds 222017ce802STakashi Iwai struct snd_card *card; 223017ce802STakashi Iwai struct snd_pcm *spdif_pcm; 224017ce802STakashi Iwai struct snd_pcm *adat_pcm; 2251da177e4SLinus Torvalds struct pci_dev *pci; 226017ce802STakashi Iwai struct snd_kcontrol *spdif_ctl; 227017ce802STakashi Iwai }; 2281da177e4SLinus Torvalds 229cebe41d4SAlexey Dobriyan static DEFINE_PCI_DEVICE_TABLE(snd_rme32_ids) = { 23028d27aaeSJoe Perches {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32), 0,}, 23128d27aaeSJoe Perches {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8), 0,}, 23228d27aaeSJoe Perches {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO), 0,}, 2331da177e4SLinus Torvalds {0,} 2341da177e4SLinus Torvalds }; 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, snd_rme32_ids); 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds #define RME32_ISWORKING(rme32) ((rme32)->wcreg & RME32_WCR_START) 2398b7fc421SRoland Dreier #define RME32_PRO_WITH_8414(rme32) ((rme32)->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO && (rme32)->rev == RME32_PRO_REVISION_WITH_8414) 2401da177e4SLinus Torvalds 241017ce802STakashi Iwai static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream); 2421da177e4SLinus Torvalds 243017ce802STakashi Iwai static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream); 2441da177e4SLinus Torvalds 245017ce802STakashi Iwai static int snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd); 2461da177e4SLinus Torvalds 247017ce802STakashi Iwai static void snd_rme32_proc_init(struct rme32 * rme32); 2481da177e4SLinus Torvalds 249017ce802STakashi Iwai static int snd_rme32_create_switches(struct snd_card *card, struct rme32 * rme32); 2501da177e4SLinus Torvalds 251017ce802STakashi Iwai static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32) 2521da177e4SLinus Torvalds { 2531da177e4SLinus Torvalds return (readl(rme32->iobase + RME32_IO_GET_POS) 2541da177e4SLinus Torvalds & RME32_RCR_AUDIO_ADDR_MASK); 2551da177e4SLinus Torvalds } 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds /* silence callback for halfduplex mode */ 258017ce802STakashi Iwai static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ 2591da177e4SLinus Torvalds snd_pcm_uframes_t pos, 2601da177e4SLinus Torvalds snd_pcm_uframes_t count) 2611da177e4SLinus Torvalds { 262017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 2631da177e4SLinus Torvalds count <<= rme32->playback_frlog; 2641da177e4SLinus Torvalds pos <<= rme32->playback_frlog; 2651da177e4SLinus Torvalds memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count); 2661da177e4SLinus Torvalds return 0; 2671da177e4SLinus Torvalds } 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds /* copy callback for halfduplex mode */ 270017ce802STakashi Iwai static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ 2711da177e4SLinus Torvalds snd_pcm_uframes_t pos, 2721da177e4SLinus Torvalds void __user *src, snd_pcm_uframes_t count) 2731da177e4SLinus Torvalds { 274017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 2751da177e4SLinus Torvalds count <<= rme32->playback_frlog; 2761da177e4SLinus Torvalds pos <<= rme32->playback_frlog; 2771da177e4SLinus Torvalds if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 2781da177e4SLinus Torvalds src, count)) 2791da177e4SLinus Torvalds return -EFAULT; 2801da177e4SLinus Torvalds return 0; 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds /* copy callback for halfduplex mode */ 284017ce802STakashi Iwai static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ 2851da177e4SLinus Torvalds snd_pcm_uframes_t pos, 2861da177e4SLinus Torvalds void __user *dst, snd_pcm_uframes_t count) 2871da177e4SLinus Torvalds { 288017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 2891da177e4SLinus Torvalds count <<= rme32->capture_frlog; 2901da177e4SLinus Torvalds pos <<= rme32->capture_frlog; 2911da177e4SLinus Torvalds if (copy_to_user_fromio(dst, 2921da177e4SLinus Torvalds rme32->iobase + RME32_IO_DATA_BUFFER + pos, 2931da177e4SLinus Torvalds count)) 2941da177e4SLinus Torvalds return -EFAULT; 2951da177e4SLinus Torvalds return 0; 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds /* 2997f927fccSAlexey Dobriyan * SPDIF I/O capabilities (half-duplex mode) 3001da177e4SLinus Torvalds */ 301017ce802STakashi Iwai static struct snd_pcm_hardware snd_rme32_spdif_info = { 3021da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP_IOMEM | 3031da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 3041da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 3051da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE | 3061da177e4SLinus Torvalds SNDRV_PCM_INFO_SYNC_START), 3071da177e4SLinus Torvalds .formats = (SNDRV_PCM_FMTBIT_S16_LE | 3081da177e4SLinus Torvalds SNDRV_PCM_FMTBIT_S32_LE), 3091da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_32000 | 3101da177e4SLinus Torvalds SNDRV_PCM_RATE_44100 | 3111da177e4SLinus Torvalds SNDRV_PCM_RATE_48000), 3121da177e4SLinus Torvalds .rate_min = 32000, 3131da177e4SLinus Torvalds .rate_max = 48000, 3141da177e4SLinus Torvalds .channels_min = 2, 3151da177e4SLinus Torvalds .channels_max = 2, 3161da177e4SLinus Torvalds .buffer_bytes_max = RME32_BUFFER_SIZE, 3171da177e4SLinus Torvalds .period_bytes_min = RME32_BLOCK_SIZE, 3181da177e4SLinus Torvalds .period_bytes_max = RME32_BLOCK_SIZE, 3191da177e4SLinus Torvalds .periods_min = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE, 3201da177e4SLinus Torvalds .periods_max = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE, 3211da177e4SLinus Torvalds .fifo_size = 0, 3221da177e4SLinus Torvalds }; 3231da177e4SLinus Torvalds 3241da177e4SLinus Torvalds /* 3257f927fccSAlexey Dobriyan * ADAT I/O capabilities (half-duplex mode) 3261da177e4SLinus Torvalds */ 327017ce802STakashi Iwai static struct snd_pcm_hardware snd_rme32_adat_info = 3281da177e4SLinus Torvalds { 3291da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP_IOMEM | 3301da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 3311da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 3321da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE | 3331da177e4SLinus Torvalds SNDRV_PCM_INFO_SYNC_START), 3341da177e4SLinus Torvalds .formats= SNDRV_PCM_FMTBIT_S16_LE, 3351da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_44100 | 3361da177e4SLinus Torvalds SNDRV_PCM_RATE_48000), 3371da177e4SLinus Torvalds .rate_min = 44100, 3381da177e4SLinus Torvalds .rate_max = 48000, 3391da177e4SLinus Torvalds .channels_min = 8, 3401da177e4SLinus Torvalds .channels_max = 8, 3411da177e4SLinus Torvalds .buffer_bytes_max = RME32_BUFFER_SIZE, 3421da177e4SLinus Torvalds .period_bytes_min = RME32_BLOCK_SIZE, 3431da177e4SLinus Torvalds .period_bytes_max = RME32_BLOCK_SIZE, 3441da177e4SLinus Torvalds .periods_min = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE, 3451da177e4SLinus Torvalds .periods_max = RME32_BUFFER_SIZE / RME32_BLOCK_SIZE, 3461da177e4SLinus Torvalds .fifo_size = 0, 3471da177e4SLinus Torvalds }; 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds /* 3507f927fccSAlexey Dobriyan * SPDIF I/O capabilities (full-duplex mode) 3511da177e4SLinus Torvalds */ 352017ce802STakashi Iwai static struct snd_pcm_hardware snd_rme32_spdif_fd_info = { 3531da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP | 3541da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 3551da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 3561da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE | 3571da177e4SLinus Torvalds SNDRV_PCM_INFO_SYNC_START), 3581da177e4SLinus Torvalds .formats = (SNDRV_PCM_FMTBIT_S16_LE | 3591da177e4SLinus Torvalds SNDRV_PCM_FMTBIT_S32_LE), 3601da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_32000 | 3611da177e4SLinus Torvalds SNDRV_PCM_RATE_44100 | 3621da177e4SLinus Torvalds SNDRV_PCM_RATE_48000), 3631da177e4SLinus Torvalds .rate_min = 32000, 3641da177e4SLinus Torvalds .rate_max = 48000, 3651da177e4SLinus Torvalds .channels_min = 2, 3661da177e4SLinus Torvalds .channels_max = 2, 3671da177e4SLinus Torvalds .buffer_bytes_max = RME32_MID_BUFFER_SIZE, 3681da177e4SLinus Torvalds .period_bytes_min = RME32_BLOCK_SIZE, 3691da177e4SLinus Torvalds .period_bytes_max = RME32_BLOCK_SIZE, 3701da177e4SLinus Torvalds .periods_min = 2, 3711da177e4SLinus Torvalds .periods_max = RME32_MID_BUFFER_SIZE / RME32_BLOCK_SIZE, 3721da177e4SLinus Torvalds .fifo_size = 0, 3731da177e4SLinus Torvalds }; 3741da177e4SLinus Torvalds 3751da177e4SLinus Torvalds /* 3767f927fccSAlexey Dobriyan * ADAT I/O capabilities (full-duplex mode) 3771da177e4SLinus Torvalds */ 378017ce802STakashi Iwai static struct snd_pcm_hardware snd_rme32_adat_fd_info = 3791da177e4SLinus Torvalds { 3801da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP | 3811da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 3821da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 3831da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE | 3841da177e4SLinus Torvalds SNDRV_PCM_INFO_SYNC_START), 3851da177e4SLinus Torvalds .formats= SNDRV_PCM_FMTBIT_S16_LE, 3861da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_44100 | 3871da177e4SLinus Torvalds SNDRV_PCM_RATE_48000), 3881da177e4SLinus Torvalds .rate_min = 44100, 3891da177e4SLinus Torvalds .rate_max = 48000, 3901da177e4SLinus Torvalds .channels_min = 8, 3911da177e4SLinus Torvalds .channels_max = 8, 3921da177e4SLinus Torvalds .buffer_bytes_max = RME32_MID_BUFFER_SIZE, 3931da177e4SLinus Torvalds .period_bytes_min = RME32_BLOCK_SIZE, 3941da177e4SLinus Torvalds .period_bytes_max = RME32_BLOCK_SIZE, 3951da177e4SLinus Torvalds .periods_min = 2, 3961da177e4SLinus Torvalds .periods_max = RME32_MID_BUFFER_SIZE / RME32_BLOCK_SIZE, 3971da177e4SLinus Torvalds .fifo_size = 0, 3981da177e4SLinus Torvalds }; 3991da177e4SLinus Torvalds 400017ce802STakashi Iwai static void snd_rme32_reset_dac(struct rme32 *rme32) 4011da177e4SLinus Torvalds { 4021da177e4SLinus Torvalds writel(rme32->wcreg | RME32_WCR_PD, 4031da177e4SLinus Torvalds rme32->iobase + RME32_IO_CONTROL_REGISTER); 4041da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 4051da177e4SLinus Torvalds } 4061da177e4SLinus Torvalds 407017ce802STakashi Iwai static int snd_rme32_playback_getrate(struct rme32 * rme32) 4081da177e4SLinus Torvalds { 4091da177e4SLinus Torvalds int rate; 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds rate = ((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_0) & 1) + 4121da177e4SLinus Torvalds (((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_1) & 1) << 1); 4131da177e4SLinus Torvalds switch (rate) { 4141da177e4SLinus Torvalds case 1: 4151da177e4SLinus Torvalds rate = 32000; 4161da177e4SLinus Torvalds break; 4171da177e4SLinus Torvalds case 2: 4181da177e4SLinus Torvalds rate = 44100; 4191da177e4SLinus Torvalds break; 4201da177e4SLinus Torvalds case 3: 4211da177e4SLinus Torvalds rate = 48000; 4221da177e4SLinus Torvalds break; 4231da177e4SLinus Torvalds default: 4241da177e4SLinus Torvalds return -1; 4251da177e4SLinus Torvalds } 4261da177e4SLinus Torvalds return (rme32->wcreg & RME32_WCR_DS_BM) ? rate << 1 : rate; 4271da177e4SLinus Torvalds } 4281da177e4SLinus Torvalds 429017ce802STakashi Iwai static int snd_rme32_capture_getrate(struct rme32 * rme32, int *is_adat) 4301da177e4SLinus Torvalds { 4311da177e4SLinus Torvalds int n; 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds *is_adat = 0; 4341da177e4SLinus Torvalds if (rme32->rcreg & RME32_RCR_LOCK) { 4351da177e4SLinus Torvalds /* ADAT rate */ 4361da177e4SLinus Torvalds *is_adat = 1; 4371da177e4SLinus Torvalds } 4381da177e4SLinus Torvalds if (rme32->rcreg & RME32_RCR_ERF) { 4391da177e4SLinus Torvalds return -1; 4401da177e4SLinus Torvalds } 4411da177e4SLinus Torvalds 4421da177e4SLinus Torvalds /* S/PDIF rate */ 4431da177e4SLinus Torvalds n = ((rme32->rcreg >> RME32_RCR_BITPOS_F0) & 1) + 4441da177e4SLinus Torvalds (((rme32->rcreg >> RME32_RCR_BITPOS_F1) & 1) << 1) + 4451da177e4SLinus Torvalds (((rme32->rcreg >> RME32_RCR_BITPOS_F2) & 1) << 2); 4461da177e4SLinus Torvalds 4471da177e4SLinus Torvalds if (RME32_PRO_WITH_8414(rme32)) 4481da177e4SLinus Torvalds switch (n) { /* supporting the CS8414 */ 4491da177e4SLinus Torvalds case 0: 4501da177e4SLinus Torvalds case 1: 4511da177e4SLinus Torvalds case 2: 4521da177e4SLinus Torvalds return -1; 4531da177e4SLinus Torvalds case 3: 4541da177e4SLinus Torvalds return 96000; 4551da177e4SLinus Torvalds case 4: 4561da177e4SLinus Torvalds return 88200; 4571da177e4SLinus Torvalds case 5: 4581da177e4SLinus Torvalds return 48000; 4591da177e4SLinus Torvalds case 6: 4601da177e4SLinus Torvalds return 44100; 4611da177e4SLinus Torvalds case 7: 4621da177e4SLinus Torvalds return 32000; 4631da177e4SLinus Torvalds default: 4641da177e4SLinus Torvalds return -1; 4651da177e4SLinus Torvalds break; 4661da177e4SLinus Torvalds } 4671da177e4SLinus Torvalds else 4681da177e4SLinus Torvalds switch (n) { /* supporting the CS8412 */ 4691da177e4SLinus Torvalds case 0: 4701da177e4SLinus Torvalds return -1; 4711da177e4SLinus Torvalds case 1: 4721da177e4SLinus Torvalds return 48000; 4731da177e4SLinus Torvalds case 2: 4741da177e4SLinus Torvalds return 44100; 4751da177e4SLinus Torvalds case 3: 4761da177e4SLinus Torvalds return 32000; 4771da177e4SLinus Torvalds case 4: 4781da177e4SLinus Torvalds return 48000; 4791da177e4SLinus Torvalds case 5: 4801da177e4SLinus Torvalds return 44100; 4811da177e4SLinus Torvalds case 6: 4821da177e4SLinus Torvalds return 44056; 4831da177e4SLinus Torvalds case 7: 4841da177e4SLinus Torvalds return 32000; 4851da177e4SLinus Torvalds default: 4861da177e4SLinus Torvalds break; 4871da177e4SLinus Torvalds } 4881da177e4SLinus Torvalds return -1; 4891da177e4SLinus Torvalds } 4901da177e4SLinus Torvalds 491017ce802STakashi Iwai static int snd_rme32_playback_setrate(struct rme32 * rme32, int rate) 4921da177e4SLinus Torvalds { 4931da177e4SLinus Torvalds int ds; 4941da177e4SLinus Torvalds 4951da177e4SLinus Torvalds ds = rme32->wcreg & RME32_WCR_DS_BM; 4961da177e4SLinus Torvalds switch (rate) { 4971da177e4SLinus Torvalds case 32000: 4981da177e4SLinus Torvalds rme32->wcreg &= ~RME32_WCR_DS_BM; 4991da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & 5001da177e4SLinus Torvalds ~RME32_WCR_FREQ_1; 5011da177e4SLinus Torvalds break; 5021da177e4SLinus Torvalds case 44100: 5031da177e4SLinus Torvalds rme32->wcreg &= ~RME32_WCR_DS_BM; 5041da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_1) & 5051da177e4SLinus Torvalds ~RME32_WCR_FREQ_0; 5061da177e4SLinus Torvalds break; 5071da177e4SLinus Torvalds case 48000: 5081da177e4SLinus Torvalds rme32->wcreg &= ~RME32_WCR_DS_BM; 5091da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | 5101da177e4SLinus Torvalds RME32_WCR_FREQ_1; 5111da177e4SLinus Torvalds break; 5121da177e4SLinus Torvalds case 64000: 5138b7fc421SRoland Dreier if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO) 5141da177e4SLinus Torvalds return -EINVAL; 5151da177e4SLinus Torvalds rme32->wcreg |= RME32_WCR_DS_BM; 5161da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & 5171da177e4SLinus Torvalds ~RME32_WCR_FREQ_1; 5181da177e4SLinus Torvalds break; 5191da177e4SLinus Torvalds case 88200: 5208b7fc421SRoland Dreier if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO) 5211da177e4SLinus Torvalds return -EINVAL; 5221da177e4SLinus Torvalds rme32->wcreg |= RME32_WCR_DS_BM; 5231da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_1) & 5241da177e4SLinus Torvalds ~RME32_WCR_FREQ_0; 5251da177e4SLinus Torvalds break; 5261da177e4SLinus Torvalds case 96000: 5278b7fc421SRoland Dreier if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO) 5281da177e4SLinus Torvalds return -EINVAL; 5291da177e4SLinus Torvalds rme32->wcreg |= RME32_WCR_DS_BM; 5301da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | 5311da177e4SLinus Torvalds RME32_WCR_FREQ_1; 5321da177e4SLinus Torvalds break; 5331da177e4SLinus Torvalds default: 5341da177e4SLinus Torvalds return -EINVAL; 5351da177e4SLinus Torvalds } 5361da177e4SLinus Torvalds if ((!ds && rme32->wcreg & RME32_WCR_DS_BM) || 5371da177e4SLinus Torvalds (ds && !(rme32->wcreg & RME32_WCR_DS_BM))) 5381da177e4SLinus Torvalds { 5391da177e4SLinus Torvalds /* change to/from double-speed: reset the DAC (if available) */ 5401da177e4SLinus Torvalds snd_rme32_reset_dac(rme32); 5411da177e4SLinus Torvalds } else { 5421da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 5431da177e4SLinus Torvalds } 5441da177e4SLinus Torvalds return 0; 5451da177e4SLinus Torvalds } 5461da177e4SLinus Torvalds 547017ce802STakashi Iwai static int snd_rme32_setclockmode(struct rme32 * rme32, int mode) 5481da177e4SLinus Torvalds { 5491da177e4SLinus Torvalds switch (mode) { 5501da177e4SLinus Torvalds case RME32_CLOCKMODE_SLAVE: 5511da177e4SLinus Torvalds /* AutoSync */ 5521da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg & ~RME32_WCR_FREQ_0) & 5531da177e4SLinus Torvalds ~RME32_WCR_FREQ_1; 5541da177e4SLinus Torvalds break; 5551da177e4SLinus Torvalds case RME32_CLOCKMODE_MASTER_32: 5561da177e4SLinus Torvalds /* Internal 32.0kHz */ 5571da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & 5581da177e4SLinus Torvalds ~RME32_WCR_FREQ_1; 5591da177e4SLinus Torvalds break; 5601da177e4SLinus Torvalds case RME32_CLOCKMODE_MASTER_44: 5611da177e4SLinus Torvalds /* Internal 44.1kHz */ 5621da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg & ~RME32_WCR_FREQ_0) | 5631da177e4SLinus Torvalds RME32_WCR_FREQ_1; 5641da177e4SLinus Torvalds break; 5651da177e4SLinus Torvalds case RME32_CLOCKMODE_MASTER_48: 5661da177e4SLinus Torvalds /* Internal 48.0kHz */ 5671da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | 5681da177e4SLinus Torvalds RME32_WCR_FREQ_1; 5691da177e4SLinus Torvalds break; 5701da177e4SLinus Torvalds default: 5711da177e4SLinus Torvalds return -EINVAL; 5721da177e4SLinus Torvalds } 5731da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 5741da177e4SLinus Torvalds return 0; 5751da177e4SLinus Torvalds } 5761da177e4SLinus Torvalds 577017ce802STakashi Iwai static int snd_rme32_getclockmode(struct rme32 * rme32) 5781da177e4SLinus Torvalds { 5791da177e4SLinus Torvalds return ((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_0) & 1) + 5801da177e4SLinus Torvalds (((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_1) & 1) << 1); 5811da177e4SLinus Torvalds } 5821da177e4SLinus Torvalds 583017ce802STakashi Iwai static int snd_rme32_setinputtype(struct rme32 * rme32, int type) 5841da177e4SLinus Torvalds { 5851da177e4SLinus Torvalds switch (type) { 5861da177e4SLinus Torvalds case RME32_INPUT_OPTICAL: 5871da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg & ~RME32_WCR_INP_0) & 5881da177e4SLinus Torvalds ~RME32_WCR_INP_1; 5891da177e4SLinus Torvalds break; 5901da177e4SLinus Torvalds case RME32_INPUT_COAXIAL: 5911da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg | RME32_WCR_INP_0) & 5921da177e4SLinus Torvalds ~RME32_WCR_INP_1; 5931da177e4SLinus Torvalds break; 5941da177e4SLinus Torvalds case RME32_INPUT_INTERNAL: 5951da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg & ~RME32_WCR_INP_0) | 5961da177e4SLinus Torvalds RME32_WCR_INP_1; 5971da177e4SLinus Torvalds break; 5981da177e4SLinus Torvalds case RME32_INPUT_XLR: 5991da177e4SLinus Torvalds rme32->wcreg = (rme32->wcreg | RME32_WCR_INP_0) | 6001da177e4SLinus Torvalds RME32_WCR_INP_1; 6011da177e4SLinus Torvalds break; 6021da177e4SLinus Torvalds default: 6031da177e4SLinus Torvalds return -EINVAL; 6041da177e4SLinus Torvalds } 6051da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 6061da177e4SLinus Torvalds return 0; 6071da177e4SLinus Torvalds } 6081da177e4SLinus Torvalds 609017ce802STakashi Iwai static int snd_rme32_getinputtype(struct rme32 * rme32) 6101da177e4SLinus Torvalds { 6111da177e4SLinus Torvalds return ((rme32->wcreg >> RME32_WCR_BITPOS_INP_0) & 1) + 6121da177e4SLinus Torvalds (((rme32->wcreg >> RME32_WCR_BITPOS_INP_1) & 1) << 1); 6131da177e4SLinus Torvalds } 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds static void 616017ce802STakashi Iwai snd_rme32_setframelog(struct rme32 * rme32, int n_channels, int is_playback) 6171da177e4SLinus Torvalds { 6181da177e4SLinus Torvalds int frlog; 6191da177e4SLinus Torvalds 6201da177e4SLinus Torvalds if (n_channels == 2) { 6211da177e4SLinus Torvalds frlog = 1; 6221da177e4SLinus Torvalds } else { 6231da177e4SLinus Torvalds /* assume 8 channels */ 6241da177e4SLinus Torvalds frlog = 3; 6251da177e4SLinus Torvalds } 6261da177e4SLinus Torvalds if (is_playback) { 6271da177e4SLinus Torvalds frlog += (rme32->wcreg & RME32_WCR_MODE24) ? 2 : 1; 6281da177e4SLinus Torvalds rme32->playback_frlog = frlog; 6291da177e4SLinus Torvalds } else { 6301da177e4SLinus Torvalds frlog += (rme32->wcreg & RME32_WCR_MODE24) ? 2 : 1; 6311da177e4SLinus Torvalds rme32->capture_frlog = frlog; 6321da177e4SLinus Torvalds } 6331da177e4SLinus Torvalds } 6341da177e4SLinus Torvalds 635017ce802STakashi Iwai static int snd_rme32_setformat(struct rme32 * rme32, int format) 6361da177e4SLinus Torvalds { 6371da177e4SLinus Torvalds switch (format) { 6381da177e4SLinus Torvalds case SNDRV_PCM_FORMAT_S16_LE: 6391da177e4SLinus Torvalds rme32->wcreg &= ~RME32_WCR_MODE24; 6401da177e4SLinus Torvalds break; 6411da177e4SLinus Torvalds case SNDRV_PCM_FORMAT_S32_LE: 6421da177e4SLinus Torvalds rme32->wcreg |= RME32_WCR_MODE24; 6431da177e4SLinus Torvalds break; 6441da177e4SLinus Torvalds default: 6451da177e4SLinus Torvalds return -EINVAL; 6461da177e4SLinus Torvalds } 6471da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 6481da177e4SLinus Torvalds return 0; 6491da177e4SLinus Torvalds } 6501da177e4SLinus Torvalds 6511da177e4SLinus Torvalds static int 652017ce802STakashi Iwai snd_rme32_playback_hw_params(struct snd_pcm_substream *substream, 653017ce802STakashi Iwai struct snd_pcm_hw_params *params) 6541da177e4SLinus Torvalds { 6551da177e4SLinus Torvalds int err, rate, dummy; 656017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 657017ce802STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 6581da177e4SLinus Torvalds 6591da177e4SLinus Torvalds if (rme32->fullduplex_mode) { 6601da177e4SLinus Torvalds err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 6611da177e4SLinus Torvalds if (err < 0) 6621da177e4SLinus Torvalds return err; 6631da177e4SLinus Torvalds } else { 6644d23359bSClemens Ladisch runtime->dma_area = (void __force *)(rme32->iobase + 6654d23359bSClemens Ladisch RME32_IO_DATA_BUFFER); 6661da177e4SLinus Torvalds runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER; 6671da177e4SLinus Torvalds runtime->dma_bytes = RME32_BUFFER_SIZE; 6681da177e4SLinus Torvalds } 6691da177e4SLinus Torvalds 6701da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 6711da177e4SLinus Torvalds if ((rme32->rcreg & RME32_RCR_KMODE) && 6721da177e4SLinus Torvalds (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { 6731da177e4SLinus Torvalds /* AutoSync */ 6741da177e4SLinus Torvalds if ((int)params_rate(params) != rate) { 6751da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 6761da177e4SLinus Torvalds return -EIO; 6771da177e4SLinus Torvalds } 6781da177e4SLinus Torvalds } else if ((err = snd_rme32_playback_setrate(rme32, params_rate(params))) < 0) { 6791da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 6801da177e4SLinus Torvalds return err; 6811da177e4SLinus Torvalds } 6821da177e4SLinus Torvalds if ((err = snd_rme32_setformat(rme32, params_format(params))) < 0) { 6831da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 6841da177e4SLinus Torvalds return err; 6851da177e4SLinus Torvalds } 6861da177e4SLinus Torvalds 6871da177e4SLinus Torvalds snd_rme32_setframelog(rme32, params_channels(params), 1); 6881da177e4SLinus Torvalds if (rme32->capture_periodsize != 0) { 6891da177e4SLinus Torvalds if (params_period_size(params) << rme32->playback_frlog != rme32->capture_periodsize) { 6901da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 6911da177e4SLinus Torvalds return -EBUSY; 6921da177e4SLinus Torvalds } 6931da177e4SLinus Torvalds } 6941da177e4SLinus Torvalds rme32->playback_periodsize = params_period_size(params) << rme32->playback_frlog; 6951da177e4SLinus Torvalds /* S/PDIF setup */ 6961da177e4SLinus Torvalds if ((rme32->wcreg & RME32_WCR_ADAT) == 0) { 6971da177e4SLinus Torvalds rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP); 6981da177e4SLinus Torvalds rme32->wcreg |= rme32->wcreg_spdif_stream; 6991da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 7001da177e4SLinus Torvalds } 7011da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 7021da177e4SLinus Torvalds 7031da177e4SLinus Torvalds return 0; 7041da177e4SLinus Torvalds } 7051da177e4SLinus Torvalds 7061da177e4SLinus Torvalds static int 707017ce802STakashi Iwai snd_rme32_capture_hw_params(struct snd_pcm_substream *substream, 708017ce802STakashi Iwai struct snd_pcm_hw_params *params) 7091da177e4SLinus Torvalds { 7101da177e4SLinus Torvalds int err, isadat, rate; 711017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 712017ce802STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 7131da177e4SLinus Torvalds 7141da177e4SLinus Torvalds if (rme32->fullduplex_mode) { 7151da177e4SLinus Torvalds err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 7161da177e4SLinus Torvalds if (err < 0) 7171da177e4SLinus Torvalds return err; 7181da177e4SLinus Torvalds } else { 7194d23359bSClemens Ladisch runtime->dma_area = (void __force *)rme32->iobase + 7204d23359bSClemens Ladisch RME32_IO_DATA_BUFFER; 7211da177e4SLinus Torvalds runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER; 7221da177e4SLinus Torvalds runtime->dma_bytes = RME32_BUFFER_SIZE; 7231da177e4SLinus Torvalds } 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 7261da177e4SLinus Torvalds /* enable AutoSync for record-preparing */ 7271da177e4SLinus Torvalds rme32->wcreg |= RME32_WCR_AUTOSYNC; 7281da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 7291da177e4SLinus Torvalds 7301da177e4SLinus Torvalds if ((err = snd_rme32_setformat(rme32, params_format(params))) < 0) { 7311da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 7321da177e4SLinus Torvalds return err; 7331da177e4SLinus Torvalds } 7341da177e4SLinus Torvalds if ((err = snd_rme32_playback_setrate(rme32, params_rate(params))) < 0) { 7351da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 7361da177e4SLinus Torvalds return err; 7371da177e4SLinus Torvalds } 7381da177e4SLinus Torvalds if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) { 7391da177e4SLinus Torvalds if ((int)params_rate(params) != rate) { 7401da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 7411da177e4SLinus Torvalds return -EIO; 7421da177e4SLinus Torvalds } 7431da177e4SLinus Torvalds if ((isadat && runtime->hw.channels_min == 2) || 7441da177e4SLinus Torvalds (!isadat && runtime->hw.channels_min == 8)) { 7451da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 7461da177e4SLinus Torvalds return -EIO; 7471da177e4SLinus Torvalds } 7481da177e4SLinus Torvalds } 7491da177e4SLinus Torvalds /* AutoSync off for recording */ 7501da177e4SLinus Torvalds rme32->wcreg &= ~RME32_WCR_AUTOSYNC; 7511da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 7521da177e4SLinus Torvalds 7531da177e4SLinus Torvalds snd_rme32_setframelog(rme32, params_channels(params), 0); 7541da177e4SLinus Torvalds if (rme32->playback_periodsize != 0) { 7551da177e4SLinus Torvalds if (params_period_size(params) << rme32->capture_frlog != 7561da177e4SLinus Torvalds rme32->playback_periodsize) { 7571da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 7581da177e4SLinus Torvalds return -EBUSY; 7591da177e4SLinus Torvalds } 7601da177e4SLinus Torvalds } 7611da177e4SLinus Torvalds rme32->capture_periodsize = 7621da177e4SLinus Torvalds params_period_size(params) << rme32->capture_frlog; 7631da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 7641da177e4SLinus Torvalds 7651da177e4SLinus Torvalds return 0; 7661da177e4SLinus Torvalds } 7671da177e4SLinus Torvalds 768017ce802STakashi Iwai static int snd_rme32_pcm_hw_free(struct snd_pcm_substream *substream) 7691da177e4SLinus Torvalds { 770017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 7711da177e4SLinus Torvalds if (! rme32->fullduplex_mode) 7721da177e4SLinus Torvalds return 0; 7731da177e4SLinus Torvalds return snd_pcm_lib_free_pages(substream); 7741da177e4SLinus Torvalds } 7751da177e4SLinus Torvalds 776017ce802STakashi Iwai static void snd_rme32_pcm_start(struct rme32 * rme32, int from_pause) 7771da177e4SLinus Torvalds { 7781da177e4SLinus Torvalds if (!from_pause) { 7791da177e4SLinus Torvalds writel(0, rme32->iobase + RME32_IO_RESET_POS); 7801da177e4SLinus Torvalds } 7811da177e4SLinus Torvalds 7821da177e4SLinus Torvalds rme32->wcreg |= RME32_WCR_START; 7831da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 7841da177e4SLinus Torvalds } 7851da177e4SLinus Torvalds 786017ce802STakashi Iwai static void snd_rme32_pcm_stop(struct rme32 * rme32, int to_pause) 7871da177e4SLinus Torvalds { 7881da177e4SLinus Torvalds /* 7891da177e4SLinus Torvalds * Check if there is an unconfirmed IRQ, if so confirm it, or else 7901da177e4SLinus Torvalds * the hardware will not stop generating interrupts 7911da177e4SLinus Torvalds */ 7921da177e4SLinus Torvalds rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER); 7931da177e4SLinus Torvalds if (rme32->rcreg & RME32_RCR_IRQ) { 7941da177e4SLinus Torvalds writel(0, rme32->iobase + RME32_IO_CONFIRM_ACTION_IRQ); 7951da177e4SLinus Torvalds } 7961da177e4SLinus Torvalds rme32->wcreg &= ~RME32_WCR_START; 7971da177e4SLinus Torvalds if (rme32->wcreg & RME32_WCR_SEL) 7981da177e4SLinus Torvalds rme32->wcreg |= RME32_WCR_MUTE; 7991da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 8001da177e4SLinus Torvalds if (! to_pause) 8011da177e4SLinus Torvalds writel(0, rme32->iobase + RME32_IO_RESET_POS); 8021da177e4SLinus Torvalds } 8031da177e4SLinus Torvalds 8047d12e780SDavid Howells static irqreturn_t snd_rme32_interrupt(int irq, void *dev_id) 8051da177e4SLinus Torvalds { 806017ce802STakashi Iwai struct rme32 *rme32 = (struct rme32 *) dev_id; 8071da177e4SLinus Torvalds 8081da177e4SLinus Torvalds rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER); 8091da177e4SLinus Torvalds if (!(rme32->rcreg & RME32_RCR_IRQ)) { 8101da177e4SLinus Torvalds return IRQ_NONE; 8111da177e4SLinus Torvalds } else { 8121da177e4SLinus Torvalds if (rme32->capture_substream) { 8131da177e4SLinus Torvalds snd_pcm_period_elapsed(rme32->capture_substream); 8141da177e4SLinus Torvalds } 8151da177e4SLinus Torvalds if (rme32->playback_substream) { 8161da177e4SLinus Torvalds snd_pcm_period_elapsed(rme32->playback_substream); 8171da177e4SLinus Torvalds } 8181da177e4SLinus Torvalds writel(0, rme32->iobase + RME32_IO_CONFIRM_ACTION_IRQ); 8191da177e4SLinus Torvalds } 8201da177e4SLinus Torvalds return IRQ_HANDLED; 8211da177e4SLinus Torvalds } 8221da177e4SLinus Torvalds 8231da177e4SLinus Torvalds static unsigned int period_bytes[] = { RME32_BLOCK_SIZE }; 8241da177e4SLinus Torvalds 8251da177e4SLinus Torvalds 826017ce802STakashi Iwai static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { 8271da177e4SLinus Torvalds .count = ARRAY_SIZE(period_bytes), 8281da177e4SLinus Torvalds .list = period_bytes, 8291da177e4SLinus Torvalds .mask = 0 8301da177e4SLinus Torvalds }; 8311da177e4SLinus Torvalds 832017ce802STakashi Iwai static void snd_rme32_set_buffer_constraint(struct rme32 *rme32, struct snd_pcm_runtime *runtime) 8331da177e4SLinus Torvalds { 8341da177e4SLinus Torvalds if (! rme32->fullduplex_mode) { 8351da177e4SLinus Torvalds snd_pcm_hw_constraint_minmax(runtime, 8361da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 8371da177e4SLinus Torvalds RME32_BUFFER_SIZE, RME32_BUFFER_SIZE); 8381da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, 8391da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 8401da177e4SLinus Torvalds &hw_constraints_period_bytes); 8411da177e4SLinus Torvalds } 8421da177e4SLinus Torvalds } 8431da177e4SLinus Torvalds 844017ce802STakashi Iwai static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream) 8451da177e4SLinus Torvalds { 8461da177e4SLinus Torvalds int rate, dummy; 847017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 848017ce802STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 8491da177e4SLinus Torvalds 8501da177e4SLinus Torvalds snd_pcm_set_sync(substream); 8511da177e4SLinus Torvalds 8521da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 8531da177e4SLinus Torvalds if (rme32->playback_substream != NULL) { 8541da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 8551da177e4SLinus Torvalds return -EBUSY; 8561da177e4SLinus Torvalds } 8571da177e4SLinus Torvalds rme32->wcreg &= ~RME32_WCR_ADAT; 8581da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 8591da177e4SLinus Torvalds rme32->playback_substream = substream; 8601da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 8611da177e4SLinus Torvalds 8621da177e4SLinus Torvalds if (rme32->fullduplex_mode) 8631da177e4SLinus Torvalds runtime->hw = snd_rme32_spdif_fd_info; 8641da177e4SLinus Torvalds else 8651da177e4SLinus Torvalds runtime->hw = snd_rme32_spdif_info; 8668b7fc421SRoland Dreier if (rme32->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO) { 8671da177e4SLinus Torvalds runtime->hw.rates |= SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000; 8681da177e4SLinus Torvalds runtime->hw.rate_max = 96000; 8691da177e4SLinus Torvalds } 8701da177e4SLinus Torvalds if ((rme32->rcreg & RME32_RCR_KMODE) && 8711da177e4SLinus Torvalds (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { 8721da177e4SLinus Torvalds /* AutoSync */ 873918f3a0eSClemens Ladisch runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); 8741da177e4SLinus Torvalds runtime->hw.rate_min = rate; 8751da177e4SLinus Torvalds runtime->hw.rate_max = rate; 8761da177e4SLinus Torvalds } 8771da177e4SLinus Torvalds 8781da177e4SLinus Torvalds snd_rme32_set_buffer_constraint(rme32, runtime); 8791da177e4SLinus Torvalds 8801da177e4SLinus Torvalds rme32->wcreg_spdif_stream = rme32->wcreg_spdif; 8811da177e4SLinus Torvalds rme32->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; 8821da177e4SLinus Torvalds snd_ctl_notify(rme32->card, SNDRV_CTL_EVENT_MASK_VALUE | 8831da177e4SLinus Torvalds SNDRV_CTL_EVENT_MASK_INFO, &rme32->spdif_ctl->id); 8841da177e4SLinus Torvalds return 0; 8851da177e4SLinus Torvalds } 8861da177e4SLinus Torvalds 887017ce802STakashi Iwai static int snd_rme32_capture_spdif_open(struct snd_pcm_substream *substream) 8881da177e4SLinus Torvalds { 8891da177e4SLinus Torvalds int isadat, rate; 890017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 891017ce802STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 8921da177e4SLinus Torvalds 8931da177e4SLinus Torvalds snd_pcm_set_sync(substream); 8941da177e4SLinus Torvalds 8951da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 8961da177e4SLinus Torvalds if (rme32->capture_substream != NULL) { 8971da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 8981da177e4SLinus Torvalds return -EBUSY; 8991da177e4SLinus Torvalds } 9001da177e4SLinus Torvalds rme32->capture_substream = substream; 9011da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 9021da177e4SLinus Torvalds 9031da177e4SLinus Torvalds if (rme32->fullduplex_mode) 9041da177e4SLinus Torvalds runtime->hw = snd_rme32_spdif_fd_info; 9051da177e4SLinus Torvalds else 9061da177e4SLinus Torvalds runtime->hw = snd_rme32_spdif_info; 9071da177e4SLinus Torvalds if (RME32_PRO_WITH_8414(rme32)) { 9081da177e4SLinus Torvalds runtime->hw.rates |= SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000; 9091da177e4SLinus Torvalds runtime->hw.rate_max = 96000; 9101da177e4SLinus Torvalds } 9111da177e4SLinus Torvalds if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) { 9121da177e4SLinus Torvalds if (isadat) { 9131da177e4SLinus Torvalds return -EIO; 9141da177e4SLinus Torvalds } 915918f3a0eSClemens Ladisch runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); 9161da177e4SLinus Torvalds runtime->hw.rate_min = rate; 9171da177e4SLinus Torvalds runtime->hw.rate_max = rate; 9181da177e4SLinus Torvalds } 9191da177e4SLinus Torvalds 9201da177e4SLinus Torvalds snd_rme32_set_buffer_constraint(rme32, runtime); 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds return 0; 9231da177e4SLinus Torvalds } 9241da177e4SLinus Torvalds 9251da177e4SLinus Torvalds static int 926017ce802STakashi Iwai snd_rme32_playback_adat_open(struct snd_pcm_substream *substream) 9271da177e4SLinus Torvalds { 9281da177e4SLinus Torvalds int rate, dummy; 929017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 930017ce802STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 9311da177e4SLinus Torvalds 9321da177e4SLinus Torvalds snd_pcm_set_sync(substream); 9331da177e4SLinus Torvalds 9341da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 9351da177e4SLinus Torvalds if (rme32->playback_substream != NULL) { 9361da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 9371da177e4SLinus Torvalds return -EBUSY; 9381da177e4SLinus Torvalds } 9391da177e4SLinus Torvalds rme32->wcreg |= RME32_WCR_ADAT; 9401da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 9411da177e4SLinus Torvalds rme32->playback_substream = substream; 9421da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 9431da177e4SLinus Torvalds 9441da177e4SLinus Torvalds if (rme32->fullduplex_mode) 9451da177e4SLinus Torvalds runtime->hw = snd_rme32_adat_fd_info; 9461da177e4SLinus Torvalds else 9471da177e4SLinus Torvalds runtime->hw = snd_rme32_adat_info; 9481da177e4SLinus Torvalds if ((rme32->rcreg & RME32_RCR_KMODE) && 9491da177e4SLinus Torvalds (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) { 9501da177e4SLinus Torvalds /* AutoSync */ 951918f3a0eSClemens Ladisch runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); 9521da177e4SLinus Torvalds runtime->hw.rate_min = rate; 9531da177e4SLinus Torvalds runtime->hw.rate_max = rate; 9541da177e4SLinus Torvalds } 9551da177e4SLinus Torvalds 9561da177e4SLinus Torvalds snd_rme32_set_buffer_constraint(rme32, runtime); 9571da177e4SLinus Torvalds return 0; 9581da177e4SLinus Torvalds } 9591da177e4SLinus Torvalds 9601da177e4SLinus Torvalds static int 961017ce802STakashi Iwai snd_rme32_capture_adat_open(struct snd_pcm_substream *substream) 9621da177e4SLinus Torvalds { 9631da177e4SLinus Torvalds int isadat, rate; 964017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 965017ce802STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 9661da177e4SLinus Torvalds 9671da177e4SLinus Torvalds if (rme32->fullduplex_mode) 9681da177e4SLinus Torvalds runtime->hw = snd_rme32_adat_fd_info; 9691da177e4SLinus Torvalds else 9701da177e4SLinus Torvalds runtime->hw = snd_rme32_adat_info; 9711da177e4SLinus Torvalds if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) { 9721da177e4SLinus Torvalds if (!isadat) { 9731da177e4SLinus Torvalds return -EIO; 9741da177e4SLinus Torvalds } 975918f3a0eSClemens Ladisch runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); 9761da177e4SLinus Torvalds runtime->hw.rate_min = rate; 9771da177e4SLinus Torvalds runtime->hw.rate_max = rate; 9781da177e4SLinus Torvalds } 9791da177e4SLinus Torvalds 9801da177e4SLinus Torvalds snd_pcm_set_sync(substream); 9811da177e4SLinus Torvalds 9821da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 9831da177e4SLinus Torvalds if (rme32->capture_substream != NULL) { 9841da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 9851da177e4SLinus Torvalds return -EBUSY; 9861da177e4SLinus Torvalds } 9871da177e4SLinus Torvalds rme32->capture_substream = substream; 9881da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 9891da177e4SLinus Torvalds 9901da177e4SLinus Torvalds snd_rme32_set_buffer_constraint(rme32, runtime); 9911da177e4SLinus Torvalds return 0; 9921da177e4SLinus Torvalds } 9931da177e4SLinus Torvalds 994017ce802STakashi Iwai static int snd_rme32_playback_close(struct snd_pcm_substream *substream) 9951da177e4SLinus Torvalds { 996017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 9971da177e4SLinus Torvalds int spdif = 0; 9981da177e4SLinus Torvalds 9991da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 10001da177e4SLinus Torvalds rme32->playback_substream = NULL; 10011da177e4SLinus Torvalds rme32->playback_periodsize = 0; 10021da177e4SLinus Torvalds spdif = (rme32->wcreg & RME32_WCR_ADAT) == 0; 10031da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 10041da177e4SLinus Torvalds if (spdif) { 10051da177e4SLinus Torvalds rme32->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; 10061da177e4SLinus Torvalds snd_ctl_notify(rme32->card, SNDRV_CTL_EVENT_MASK_VALUE | 10071da177e4SLinus Torvalds SNDRV_CTL_EVENT_MASK_INFO, 10081da177e4SLinus Torvalds &rme32->spdif_ctl->id); 10091da177e4SLinus Torvalds } 10101da177e4SLinus Torvalds return 0; 10111da177e4SLinus Torvalds } 10121da177e4SLinus Torvalds 1013017ce802STakashi Iwai static int snd_rme32_capture_close(struct snd_pcm_substream *substream) 10141da177e4SLinus Torvalds { 1015017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 10161da177e4SLinus Torvalds 10171da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 10181da177e4SLinus Torvalds rme32->capture_substream = NULL; 10191da177e4SLinus Torvalds rme32->capture_periodsize = 0; 10201da177e4SLinus Torvalds spin_unlock(&rme32->lock); 10211da177e4SLinus Torvalds return 0; 10221da177e4SLinus Torvalds } 10231da177e4SLinus Torvalds 1024017ce802STakashi Iwai static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream) 10251da177e4SLinus Torvalds { 1026017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 10271da177e4SLinus Torvalds 10281da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 10291da177e4SLinus Torvalds if (rme32->fullduplex_mode) { 10301da177e4SLinus Torvalds memset(&rme32->playback_pcm, 0, sizeof(rme32->playback_pcm)); 10311da177e4SLinus Torvalds rme32->playback_pcm.hw_buffer_size = RME32_BUFFER_SIZE; 10321da177e4SLinus Torvalds rme32->playback_pcm.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); 10331da177e4SLinus Torvalds } else { 10341da177e4SLinus Torvalds writel(0, rme32->iobase + RME32_IO_RESET_POS); 10351da177e4SLinus Torvalds } 10361da177e4SLinus Torvalds if (rme32->wcreg & RME32_WCR_SEL) 10371da177e4SLinus Torvalds rme32->wcreg &= ~RME32_WCR_MUTE; 10381da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 10391da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 10401da177e4SLinus Torvalds return 0; 10411da177e4SLinus Torvalds } 10421da177e4SLinus Torvalds 1043017ce802STakashi Iwai static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream) 10441da177e4SLinus Torvalds { 1045017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 10461da177e4SLinus Torvalds 10471da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 10481da177e4SLinus Torvalds if (rme32->fullduplex_mode) { 10491da177e4SLinus Torvalds memset(&rme32->capture_pcm, 0, sizeof(rme32->capture_pcm)); 10501da177e4SLinus Torvalds rme32->capture_pcm.hw_buffer_size = RME32_BUFFER_SIZE; 10511da177e4SLinus Torvalds rme32->capture_pcm.hw_queue_size = RME32_BUFFER_SIZE / 2; 10521da177e4SLinus Torvalds rme32->capture_pcm.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); 10531da177e4SLinus Torvalds } else { 10541da177e4SLinus Torvalds writel(0, rme32->iobase + RME32_IO_RESET_POS); 10551da177e4SLinus Torvalds } 10561da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 10571da177e4SLinus Torvalds return 0; 10581da177e4SLinus Torvalds } 10591da177e4SLinus Torvalds 10601da177e4SLinus Torvalds static int 1061017ce802STakashi Iwai snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 10621da177e4SLinus Torvalds { 1063017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 1064017ce802STakashi Iwai struct snd_pcm_substream *s; 10651da177e4SLinus Torvalds 10661da177e4SLinus Torvalds spin_lock(&rme32->lock); 1067ef991b95STakashi Iwai snd_pcm_group_for_each_entry(s, substream) { 10681da177e4SLinus Torvalds if (s != rme32->playback_substream && 10691da177e4SLinus Torvalds s != rme32->capture_substream) 10701da177e4SLinus Torvalds continue; 10711da177e4SLinus Torvalds switch (cmd) { 10721da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_START: 10731da177e4SLinus Torvalds rme32->running |= (1 << s->stream); 10741da177e4SLinus Torvalds if (rme32->fullduplex_mode) { 10751da177e4SLinus Torvalds /* remember the current DMA position */ 10761da177e4SLinus Torvalds if (s == rme32->playback_substream) { 10771da177e4SLinus Torvalds rme32->playback_pcm.hw_io = 10781da177e4SLinus Torvalds rme32->playback_pcm.hw_data = snd_rme32_pcm_byteptr(rme32); 10791da177e4SLinus Torvalds } else { 10801da177e4SLinus Torvalds rme32->capture_pcm.hw_io = 10811da177e4SLinus Torvalds rme32->capture_pcm.hw_data = snd_rme32_pcm_byteptr(rme32); 10821da177e4SLinus Torvalds } 10831da177e4SLinus Torvalds } 10841da177e4SLinus Torvalds break; 10851da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_STOP: 10861da177e4SLinus Torvalds rme32->running &= ~(1 << s->stream); 10871da177e4SLinus Torvalds break; 10881da177e4SLinus Torvalds } 10891da177e4SLinus Torvalds snd_pcm_trigger_done(s, substream); 10901da177e4SLinus Torvalds } 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds /* prefill playback buffer */ 10931da177e4SLinus Torvalds if (cmd == SNDRV_PCM_TRIGGER_START && rme32->fullduplex_mode) { 1094ef991b95STakashi Iwai snd_pcm_group_for_each_entry(s, substream) { 10951da177e4SLinus Torvalds if (s == rme32->playback_substream) { 10961da177e4SLinus Torvalds s->ops->ack(s); 10971da177e4SLinus Torvalds break; 10981da177e4SLinus Torvalds } 10991da177e4SLinus Torvalds } 11001da177e4SLinus Torvalds } 11011da177e4SLinus Torvalds 11021da177e4SLinus Torvalds switch (cmd) { 11031da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_START: 11041da177e4SLinus Torvalds if (rme32->running && ! RME32_ISWORKING(rme32)) 11051da177e4SLinus Torvalds snd_rme32_pcm_start(rme32, 0); 11061da177e4SLinus Torvalds break; 11071da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_STOP: 11081da177e4SLinus Torvalds if (! rme32->running && RME32_ISWORKING(rme32)) 11091da177e4SLinus Torvalds snd_rme32_pcm_stop(rme32, 0); 11101da177e4SLinus Torvalds break; 11111da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 11121da177e4SLinus Torvalds if (rme32->running && RME32_ISWORKING(rme32)) 11131da177e4SLinus Torvalds snd_rme32_pcm_stop(rme32, 1); 11141da177e4SLinus Torvalds break; 11151da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 11161da177e4SLinus Torvalds if (rme32->running && ! RME32_ISWORKING(rme32)) 11171da177e4SLinus Torvalds snd_rme32_pcm_start(rme32, 1); 11181da177e4SLinus Torvalds break; 11191da177e4SLinus Torvalds } 11201da177e4SLinus Torvalds spin_unlock(&rme32->lock); 11211da177e4SLinus Torvalds return 0; 11221da177e4SLinus Torvalds } 11231da177e4SLinus Torvalds 11241da177e4SLinus Torvalds /* pointer callback for halfduplex mode */ 11251da177e4SLinus Torvalds static snd_pcm_uframes_t 1126017ce802STakashi Iwai snd_rme32_playback_pointer(struct snd_pcm_substream *substream) 11271da177e4SLinus Torvalds { 1128017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 11291da177e4SLinus Torvalds return snd_rme32_pcm_byteptr(rme32) >> rme32->playback_frlog; 11301da177e4SLinus Torvalds } 11311da177e4SLinus Torvalds 11321da177e4SLinus Torvalds static snd_pcm_uframes_t 1133017ce802STakashi Iwai snd_rme32_capture_pointer(struct snd_pcm_substream *substream) 11341da177e4SLinus Torvalds { 1135017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 11361da177e4SLinus Torvalds return snd_rme32_pcm_byteptr(rme32) >> rme32->capture_frlog; 11371da177e4SLinus Torvalds } 11381da177e4SLinus Torvalds 11391da177e4SLinus Torvalds 11401da177e4SLinus Torvalds /* ack and pointer callbacks for fullduplex mode */ 1141017ce802STakashi Iwai static void snd_rme32_pb_trans_copy(struct snd_pcm_substream *substream, 1142017ce802STakashi Iwai struct snd_pcm_indirect *rec, size_t bytes) 11431da177e4SLinus Torvalds { 1144017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 11451da177e4SLinus Torvalds memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data, 11461da177e4SLinus Torvalds substream->runtime->dma_area + rec->sw_data, bytes); 11471da177e4SLinus Torvalds } 11481da177e4SLinus Torvalds 1149017ce802STakashi Iwai static int snd_rme32_playback_fd_ack(struct snd_pcm_substream *substream) 11501da177e4SLinus Torvalds { 1151017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 1152017ce802STakashi Iwai struct snd_pcm_indirect *rec, *cprec; 11531da177e4SLinus Torvalds 11541da177e4SLinus Torvalds rec = &rme32->playback_pcm; 11551da177e4SLinus Torvalds cprec = &rme32->capture_pcm; 11561da177e4SLinus Torvalds spin_lock(&rme32->lock); 11571da177e4SLinus Torvalds rec->hw_queue_size = RME32_BUFFER_SIZE; 11581da177e4SLinus Torvalds if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) 11591da177e4SLinus Torvalds rec->hw_queue_size -= cprec->hw_ready; 11601da177e4SLinus Torvalds spin_unlock(&rme32->lock); 11611da177e4SLinus Torvalds snd_pcm_indirect_playback_transfer(substream, rec, 11621da177e4SLinus Torvalds snd_rme32_pb_trans_copy); 11631da177e4SLinus Torvalds return 0; 11641da177e4SLinus Torvalds } 11651da177e4SLinus Torvalds 1166017ce802STakashi Iwai static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream, 1167017ce802STakashi Iwai struct snd_pcm_indirect *rec, size_t bytes) 11681da177e4SLinus Torvalds { 1169017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 11701da177e4SLinus Torvalds memcpy_fromio(substream->runtime->dma_area + rec->sw_data, 11711da177e4SLinus Torvalds rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data, 11721da177e4SLinus Torvalds bytes); 11731da177e4SLinus Torvalds } 11741da177e4SLinus Torvalds 1175017ce802STakashi Iwai static int snd_rme32_capture_fd_ack(struct snd_pcm_substream *substream) 11761da177e4SLinus Torvalds { 1177017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 11781da177e4SLinus Torvalds snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm, 11791da177e4SLinus Torvalds snd_rme32_cp_trans_copy); 11801da177e4SLinus Torvalds return 0; 11811da177e4SLinus Torvalds } 11821da177e4SLinus Torvalds 11831da177e4SLinus Torvalds static snd_pcm_uframes_t 1184017ce802STakashi Iwai snd_rme32_playback_fd_pointer(struct snd_pcm_substream *substream) 11851da177e4SLinus Torvalds { 1186017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 11871da177e4SLinus Torvalds return snd_pcm_indirect_playback_pointer(substream, &rme32->playback_pcm, 11881da177e4SLinus Torvalds snd_rme32_pcm_byteptr(rme32)); 11891da177e4SLinus Torvalds } 11901da177e4SLinus Torvalds 11911da177e4SLinus Torvalds static snd_pcm_uframes_t 1192017ce802STakashi Iwai snd_rme32_capture_fd_pointer(struct snd_pcm_substream *substream) 11931da177e4SLinus Torvalds { 1194017ce802STakashi Iwai struct rme32 *rme32 = snd_pcm_substream_chip(substream); 11951da177e4SLinus Torvalds return snd_pcm_indirect_capture_pointer(substream, &rme32->capture_pcm, 11961da177e4SLinus Torvalds snd_rme32_pcm_byteptr(rme32)); 11971da177e4SLinus Torvalds } 11981da177e4SLinus Torvalds 11991da177e4SLinus Torvalds /* for halfduplex mode */ 1200017ce802STakashi Iwai static struct snd_pcm_ops snd_rme32_playback_spdif_ops = { 12011da177e4SLinus Torvalds .open = snd_rme32_playback_spdif_open, 12021da177e4SLinus Torvalds .close = snd_rme32_playback_close, 12031da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 12041da177e4SLinus Torvalds .hw_params = snd_rme32_playback_hw_params, 12051da177e4SLinus Torvalds .hw_free = snd_rme32_pcm_hw_free, 12061da177e4SLinus Torvalds .prepare = snd_rme32_playback_prepare, 12071da177e4SLinus Torvalds .trigger = snd_rme32_pcm_trigger, 12081da177e4SLinus Torvalds .pointer = snd_rme32_playback_pointer, 12091da177e4SLinus Torvalds .copy = snd_rme32_playback_copy, 12101da177e4SLinus Torvalds .silence = snd_rme32_playback_silence, 12111da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 12121da177e4SLinus Torvalds }; 12131da177e4SLinus Torvalds 1214017ce802STakashi Iwai static struct snd_pcm_ops snd_rme32_capture_spdif_ops = { 12151da177e4SLinus Torvalds .open = snd_rme32_capture_spdif_open, 12161da177e4SLinus Torvalds .close = snd_rme32_capture_close, 12171da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 12181da177e4SLinus Torvalds .hw_params = snd_rme32_capture_hw_params, 12191da177e4SLinus Torvalds .hw_free = snd_rme32_pcm_hw_free, 12201da177e4SLinus Torvalds .prepare = snd_rme32_capture_prepare, 12211da177e4SLinus Torvalds .trigger = snd_rme32_pcm_trigger, 12221da177e4SLinus Torvalds .pointer = snd_rme32_capture_pointer, 12231da177e4SLinus Torvalds .copy = snd_rme32_capture_copy, 12241da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 12251da177e4SLinus Torvalds }; 12261da177e4SLinus Torvalds 1227017ce802STakashi Iwai static struct snd_pcm_ops snd_rme32_playback_adat_ops = { 12281da177e4SLinus Torvalds .open = snd_rme32_playback_adat_open, 12291da177e4SLinus Torvalds .close = snd_rme32_playback_close, 12301da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 12311da177e4SLinus Torvalds .hw_params = snd_rme32_playback_hw_params, 12321da177e4SLinus Torvalds .prepare = snd_rme32_playback_prepare, 12331da177e4SLinus Torvalds .trigger = snd_rme32_pcm_trigger, 12341da177e4SLinus Torvalds .pointer = snd_rme32_playback_pointer, 12351da177e4SLinus Torvalds .copy = snd_rme32_playback_copy, 12361da177e4SLinus Torvalds .silence = snd_rme32_playback_silence, 12371da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 12381da177e4SLinus Torvalds }; 12391da177e4SLinus Torvalds 1240017ce802STakashi Iwai static struct snd_pcm_ops snd_rme32_capture_adat_ops = { 12411da177e4SLinus Torvalds .open = snd_rme32_capture_adat_open, 12421da177e4SLinus Torvalds .close = snd_rme32_capture_close, 12431da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 12441da177e4SLinus Torvalds .hw_params = snd_rme32_capture_hw_params, 12451da177e4SLinus Torvalds .prepare = snd_rme32_capture_prepare, 12461da177e4SLinus Torvalds .trigger = snd_rme32_pcm_trigger, 12471da177e4SLinus Torvalds .pointer = snd_rme32_capture_pointer, 12481da177e4SLinus Torvalds .copy = snd_rme32_capture_copy, 12491da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 12501da177e4SLinus Torvalds }; 12511da177e4SLinus Torvalds 12521da177e4SLinus Torvalds /* for fullduplex mode */ 1253017ce802STakashi Iwai static struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = { 12541da177e4SLinus Torvalds .open = snd_rme32_playback_spdif_open, 12551da177e4SLinus Torvalds .close = snd_rme32_playback_close, 12561da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 12571da177e4SLinus Torvalds .hw_params = snd_rme32_playback_hw_params, 12581da177e4SLinus Torvalds .hw_free = snd_rme32_pcm_hw_free, 12591da177e4SLinus Torvalds .prepare = snd_rme32_playback_prepare, 12601da177e4SLinus Torvalds .trigger = snd_rme32_pcm_trigger, 12611da177e4SLinus Torvalds .pointer = snd_rme32_playback_fd_pointer, 12621da177e4SLinus Torvalds .ack = snd_rme32_playback_fd_ack, 12631da177e4SLinus Torvalds }; 12641da177e4SLinus Torvalds 1265017ce802STakashi Iwai static struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = { 12661da177e4SLinus Torvalds .open = snd_rme32_capture_spdif_open, 12671da177e4SLinus Torvalds .close = snd_rme32_capture_close, 12681da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 12691da177e4SLinus Torvalds .hw_params = snd_rme32_capture_hw_params, 12701da177e4SLinus Torvalds .hw_free = snd_rme32_pcm_hw_free, 12711da177e4SLinus Torvalds .prepare = snd_rme32_capture_prepare, 12721da177e4SLinus Torvalds .trigger = snd_rme32_pcm_trigger, 12731da177e4SLinus Torvalds .pointer = snd_rme32_capture_fd_pointer, 12741da177e4SLinus Torvalds .ack = snd_rme32_capture_fd_ack, 12751da177e4SLinus Torvalds }; 12761da177e4SLinus Torvalds 1277017ce802STakashi Iwai static struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = { 12781da177e4SLinus Torvalds .open = snd_rme32_playback_adat_open, 12791da177e4SLinus Torvalds .close = snd_rme32_playback_close, 12801da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 12811da177e4SLinus Torvalds .hw_params = snd_rme32_playback_hw_params, 12821da177e4SLinus Torvalds .prepare = snd_rme32_playback_prepare, 12831da177e4SLinus Torvalds .trigger = snd_rme32_pcm_trigger, 12841da177e4SLinus Torvalds .pointer = snd_rme32_playback_fd_pointer, 12851da177e4SLinus Torvalds .ack = snd_rme32_playback_fd_ack, 12861da177e4SLinus Torvalds }; 12871da177e4SLinus Torvalds 1288017ce802STakashi Iwai static struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = { 12891da177e4SLinus Torvalds .open = snd_rme32_capture_adat_open, 12901da177e4SLinus Torvalds .close = snd_rme32_capture_close, 12911da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 12921da177e4SLinus Torvalds .hw_params = snd_rme32_capture_hw_params, 12931da177e4SLinus Torvalds .prepare = snd_rme32_capture_prepare, 12941da177e4SLinus Torvalds .trigger = snd_rme32_pcm_trigger, 12951da177e4SLinus Torvalds .pointer = snd_rme32_capture_fd_pointer, 12961da177e4SLinus Torvalds .ack = snd_rme32_capture_fd_ack, 12971da177e4SLinus Torvalds }; 12981da177e4SLinus Torvalds 12991da177e4SLinus Torvalds static void snd_rme32_free(void *private_data) 13001da177e4SLinus Torvalds { 1301017ce802STakashi Iwai struct rme32 *rme32 = (struct rme32 *) private_data; 13021da177e4SLinus Torvalds 13031da177e4SLinus Torvalds if (rme32 == NULL) { 13041da177e4SLinus Torvalds return; 13051da177e4SLinus Torvalds } 13061da177e4SLinus Torvalds if (rme32->irq >= 0) { 13071da177e4SLinus Torvalds snd_rme32_pcm_stop(rme32, 0); 13081da177e4SLinus Torvalds free_irq(rme32->irq, (void *) rme32); 13091da177e4SLinus Torvalds rme32->irq = -1; 13101da177e4SLinus Torvalds } 13111da177e4SLinus Torvalds if (rme32->iobase) { 13121da177e4SLinus Torvalds iounmap(rme32->iobase); 13131da177e4SLinus Torvalds rme32->iobase = NULL; 13141da177e4SLinus Torvalds } 13151da177e4SLinus Torvalds if (rme32->port) { 13161da177e4SLinus Torvalds pci_release_regions(rme32->pci); 13171da177e4SLinus Torvalds rme32->port = 0; 13181da177e4SLinus Torvalds } 13191da177e4SLinus Torvalds pci_disable_device(rme32->pci); 13201da177e4SLinus Torvalds } 13211da177e4SLinus Torvalds 1322017ce802STakashi Iwai static void snd_rme32_free_spdif_pcm(struct snd_pcm *pcm) 13231da177e4SLinus Torvalds { 1324017ce802STakashi Iwai struct rme32 *rme32 = (struct rme32 *) pcm->private_data; 13251da177e4SLinus Torvalds rme32->spdif_pcm = NULL; 13261da177e4SLinus Torvalds } 13271da177e4SLinus Torvalds 13281da177e4SLinus Torvalds static void 1329017ce802STakashi Iwai snd_rme32_free_adat_pcm(struct snd_pcm *pcm) 13301da177e4SLinus Torvalds { 1331017ce802STakashi Iwai struct rme32 *rme32 = (struct rme32 *) pcm->private_data; 13321da177e4SLinus Torvalds rme32->adat_pcm = NULL; 13331da177e4SLinus Torvalds } 13341da177e4SLinus Torvalds 1335017ce802STakashi Iwai static int __devinit snd_rme32_create(struct rme32 * rme32) 13361da177e4SLinus Torvalds { 13371da177e4SLinus Torvalds struct pci_dev *pci = rme32->pci; 13381da177e4SLinus Torvalds int err; 13391da177e4SLinus Torvalds 13401da177e4SLinus Torvalds rme32->irq = -1; 13411da177e4SLinus Torvalds spin_lock_init(&rme32->lock); 13421da177e4SLinus Torvalds 13431da177e4SLinus Torvalds if ((err = pci_enable_device(pci)) < 0) 13441da177e4SLinus Torvalds return err; 13451da177e4SLinus Torvalds 13461da177e4SLinus Torvalds if ((err = pci_request_regions(pci, "RME32")) < 0) 13471da177e4SLinus Torvalds return err; 13481da177e4SLinus Torvalds rme32->port = pci_resource_start(rme32->pci, 0); 13491da177e4SLinus Torvalds 13504db9e4f2SHarvey Harrison rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE); 13514db9e4f2SHarvey Harrison if (!rme32->iobase) { 135299b359baSTakashi Iwai snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", 13531da177e4SLinus Torvalds rme32->port, rme32->port + RME32_IO_SIZE - 1); 13541da177e4SLinus Torvalds return -ENOMEM; 13551da177e4SLinus Torvalds } 13561da177e4SLinus Torvalds 1357437a5a46STakashi Iwai if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_SHARED, 1358934c2b6dSTakashi Iwai KBUILD_MODNAME, rme32)) { 1359688956f2STakashi Iwai snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); 1360688956f2STakashi Iwai return -EBUSY; 1361688956f2STakashi Iwai } 1362688956f2STakashi Iwai rme32->irq = pci->irq; 1363688956f2STakashi Iwai 13641da177e4SLinus Torvalds /* read the card's revision number */ 13651da177e4SLinus Torvalds pci_read_config_byte(pci, 8, &rme32->rev); 13661da177e4SLinus Torvalds 13671da177e4SLinus Torvalds /* set up ALSA pcm device for S/PDIF */ 13681da177e4SLinus Torvalds if ((err = snd_pcm_new(rme32->card, "Digi32 IEC958", 0, 1, 1, &rme32->spdif_pcm)) < 0) { 13691da177e4SLinus Torvalds return err; 13701da177e4SLinus Torvalds } 13711da177e4SLinus Torvalds rme32->spdif_pcm->private_data = rme32; 13721da177e4SLinus Torvalds rme32->spdif_pcm->private_free = snd_rme32_free_spdif_pcm; 13731da177e4SLinus Torvalds strcpy(rme32->spdif_pcm->name, "Digi32 IEC958"); 13741da177e4SLinus Torvalds if (rme32->fullduplex_mode) { 13751da177e4SLinus Torvalds snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK, 13761da177e4SLinus Torvalds &snd_rme32_playback_spdif_fd_ops); 13771da177e4SLinus Torvalds snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE, 13781da177e4SLinus Torvalds &snd_rme32_capture_spdif_fd_ops); 13791da177e4SLinus Torvalds snd_pcm_lib_preallocate_pages_for_all(rme32->spdif_pcm, SNDRV_DMA_TYPE_CONTINUOUS, 13801da177e4SLinus Torvalds snd_dma_continuous_data(GFP_KERNEL), 13811da177e4SLinus Torvalds 0, RME32_MID_BUFFER_SIZE); 13821da177e4SLinus Torvalds rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; 13831da177e4SLinus Torvalds } else { 13841da177e4SLinus Torvalds snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK, 13851da177e4SLinus Torvalds &snd_rme32_playback_spdif_ops); 13861da177e4SLinus Torvalds snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE, 13871da177e4SLinus Torvalds &snd_rme32_capture_spdif_ops); 13881da177e4SLinus Torvalds rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; 13891da177e4SLinus Torvalds } 13901da177e4SLinus Torvalds 13911da177e4SLinus Torvalds /* set up ALSA pcm device for ADAT */ 13928b7fc421SRoland Dreier if ((pci->device == PCI_DEVICE_ID_RME_DIGI32) || 13938b7fc421SRoland Dreier (pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO)) { 13941da177e4SLinus Torvalds /* ADAT is not available on DIGI32 and DIGI32 Pro */ 13951da177e4SLinus Torvalds rme32->adat_pcm = NULL; 13961da177e4SLinus Torvalds } 13971da177e4SLinus Torvalds else { 13981da177e4SLinus Torvalds if ((err = snd_pcm_new(rme32->card, "Digi32 ADAT", 1, 13991da177e4SLinus Torvalds 1, 1, &rme32->adat_pcm)) < 0) 14001da177e4SLinus Torvalds { 14011da177e4SLinus Torvalds return err; 14021da177e4SLinus Torvalds } 14031da177e4SLinus Torvalds rme32->adat_pcm->private_data = rme32; 14041da177e4SLinus Torvalds rme32->adat_pcm->private_free = snd_rme32_free_adat_pcm; 14051da177e4SLinus Torvalds strcpy(rme32->adat_pcm->name, "Digi32 ADAT"); 14061da177e4SLinus Torvalds if (rme32->fullduplex_mode) { 14071da177e4SLinus Torvalds snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 14081da177e4SLinus Torvalds &snd_rme32_playback_adat_fd_ops); 14091da177e4SLinus Torvalds snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 14101da177e4SLinus Torvalds &snd_rme32_capture_adat_fd_ops); 14111da177e4SLinus Torvalds snd_pcm_lib_preallocate_pages_for_all(rme32->adat_pcm, SNDRV_DMA_TYPE_CONTINUOUS, 14121da177e4SLinus Torvalds snd_dma_continuous_data(GFP_KERNEL), 14131da177e4SLinus Torvalds 0, RME32_MID_BUFFER_SIZE); 14141da177e4SLinus Torvalds rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; 14151da177e4SLinus Torvalds } else { 14161da177e4SLinus Torvalds snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 14171da177e4SLinus Torvalds &snd_rme32_playback_adat_ops); 14181da177e4SLinus Torvalds snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 14191da177e4SLinus Torvalds &snd_rme32_capture_adat_ops); 14201da177e4SLinus Torvalds rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX; 14211da177e4SLinus Torvalds } 14221da177e4SLinus Torvalds } 14231da177e4SLinus Torvalds 14241da177e4SLinus Torvalds 14251da177e4SLinus Torvalds rme32->playback_periodsize = 0; 14261da177e4SLinus Torvalds rme32->capture_periodsize = 0; 14271da177e4SLinus Torvalds 14281da177e4SLinus Torvalds /* make sure playback/capture is stopped, if by some reason active */ 14291da177e4SLinus Torvalds snd_rme32_pcm_stop(rme32, 0); 14301da177e4SLinus Torvalds 14311da177e4SLinus Torvalds /* reset DAC */ 14321da177e4SLinus Torvalds snd_rme32_reset_dac(rme32); 14331da177e4SLinus Torvalds 14341da177e4SLinus Torvalds /* reset buffer pointer */ 14351da177e4SLinus Torvalds writel(0, rme32->iobase + RME32_IO_RESET_POS); 14361da177e4SLinus Torvalds 14371da177e4SLinus Torvalds /* set default values in registers */ 14381da177e4SLinus Torvalds rme32->wcreg = RME32_WCR_SEL | /* normal playback */ 14391da177e4SLinus Torvalds RME32_WCR_INP_0 | /* input select */ 14401da177e4SLinus Torvalds RME32_WCR_MUTE; /* muting on */ 14411da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 14421da177e4SLinus Torvalds 14431da177e4SLinus Torvalds 14441da177e4SLinus Torvalds /* init switch interface */ 14451da177e4SLinus Torvalds if ((err = snd_rme32_create_switches(rme32->card, rme32)) < 0) { 14461da177e4SLinus Torvalds return err; 14471da177e4SLinus Torvalds } 14481da177e4SLinus Torvalds 14491da177e4SLinus Torvalds /* init proc interface */ 14501da177e4SLinus Torvalds snd_rme32_proc_init(rme32); 14511da177e4SLinus Torvalds 14521da177e4SLinus Torvalds rme32->capture_substream = NULL; 14531da177e4SLinus Torvalds rme32->playback_substream = NULL; 14541da177e4SLinus Torvalds 14551da177e4SLinus Torvalds return 0; 14561da177e4SLinus Torvalds } 14571da177e4SLinus Torvalds 14581da177e4SLinus Torvalds /* 14591da177e4SLinus Torvalds * proc interface 14601da177e4SLinus Torvalds */ 14611da177e4SLinus Torvalds 14621da177e4SLinus Torvalds static void 1463017ce802STakashi Iwai snd_rme32_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer) 14641da177e4SLinus Torvalds { 14651da177e4SLinus Torvalds int n; 1466017ce802STakashi Iwai struct rme32 *rme32 = (struct rme32 *) entry->private_data; 14671da177e4SLinus Torvalds 14681da177e4SLinus Torvalds rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER); 14691da177e4SLinus Torvalds 14701da177e4SLinus Torvalds snd_iprintf(buffer, rme32->card->longname); 14711da177e4SLinus Torvalds snd_iprintf(buffer, " (index #%d)\n", rme32->card->number + 1); 14721da177e4SLinus Torvalds 14731da177e4SLinus Torvalds snd_iprintf(buffer, "\nGeneral settings\n"); 14741da177e4SLinus Torvalds if (rme32->fullduplex_mode) 14751da177e4SLinus Torvalds snd_iprintf(buffer, " Full-duplex mode\n"); 14761da177e4SLinus Torvalds else 14771da177e4SLinus Torvalds snd_iprintf(buffer, " Half-duplex mode\n"); 14781da177e4SLinus Torvalds if (RME32_PRO_WITH_8414(rme32)) { 14791da177e4SLinus Torvalds snd_iprintf(buffer, " receiver: CS8414\n"); 14801da177e4SLinus Torvalds } else { 14811da177e4SLinus Torvalds snd_iprintf(buffer, " receiver: CS8412\n"); 14821da177e4SLinus Torvalds } 14831da177e4SLinus Torvalds if (rme32->wcreg & RME32_WCR_MODE24) { 14841da177e4SLinus Torvalds snd_iprintf(buffer, " format: 24 bit"); 14851da177e4SLinus Torvalds } else { 14861da177e4SLinus Torvalds snd_iprintf(buffer, " format: 16 bit"); 14871da177e4SLinus Torvalds } 14881da177e4SLinus Torvalds if (rme32->wcreg & RME32_WCR_MONO) { 14891da177e4SLinus Torvalds snd_iprintf(buffer, ", Mono\n"); 14901da177e4SLinus Torvalds } else { 14911da177e4SLinus Torvalds snd_iprintf(buffer, ", Stereo\n"); 14921da177e4SLinus Torvalds } 14931da177e4SLinus Torvalds 14941da177e4SLinus Torvalds snd_iprintf(buffer, "\nInput settings\n"); 14951da177e4SLinus Torvalds switch (snd_rme32_getinputtype(rme32)) { 14961da177e4SLinus Torvalds case RME32_INPUT_OPTICAL: 14971da177e4SLinus Torvalds snd_iprintf(buffer, " input: optical"); 14981da177e4SLinus Torvalds break; 14991da177e4SLinus Torvalds case RME32_INPUT_COAXIAL: 15001da177e4SLinus Torvalds snd_iprintf(buffer, " input: coaxial"); 15011da177e4SLinus Torvalds break; 15021da177e4SLinus Torvalds case RME32_INPUT_INTERNAL: 15031da177e4SLinus Torvalds snd_iprintf(buffer, " input: internal"); 15041da177e4SLinus Torvalds break; 15051da177e4SLinus Torvalds case RME32_INPUT_XLR: 15061da177e4SLinus Torvalds snd_iprintf(buffer, " input: XLR"); 15071da177e4SLinus Torvalds break; 15081da177e4SLinus Torvalds } 15091da177e4SLinus Torvalds if (snd_rme32_capture_getrate(rme32, &n) < 0) { 15101da177e4SLinus Torvalds snd_iprintf(buffer, "\n sample rate: no valid signal\n"); 15111da177e4SLinus Torvalds } else { 15121da177e4SLinus Torvalds if (n) { 15131da177e4SLinus Torvalds snd_iprintf(buffer, " (8 channels)\n"); 15141da177e4SLinus Torvalds } else { 15151da177e4SLinus Torvalds snd_iprintf(buffer, " (2 channels)\n"); 15161da177e4SLinus Torvalds } 15171da177e4SLinus Torvalds snd_iprintf(buffer, " sample rate: %d Hz\n", 15181da177e4SLinus Torvalds snd_rme32_capture_getrate(rme32, &n)); 15191da177e4SLinus Torvalds } 15201da177e4SLinus Torvalds 15211da177e4SLinus Torvalds snd_iprintf(buffer, "\nOutput settings\n"); 15221da177e4SLinus Torvalds if (rme32->wcreg & RME32_WCR_SEL) { 15231da177e4SLinus Torvalds snd_iprintf(buffer, " output signal: normal playback"); 15241da177e4SLinus Torvalds } else { 15251da177e4SLinus Torvalds snd_iprintf(buffer, " output signal: same as input"); 15261da177e4SLinus Torvalds } 15271da177e4SLinus Torvalds if (rme32->wcreg & RME32_WCR_MUTE) { 15281da177e4SLinus Torvalds snd_iprintf(buffer, " (muted)\n"); 15291da177e4SLinus Torvalds } else { 15301da177e4SLinus Torvalds snd_iprintf(buffer, "\n"); 15311da177e4SLinus Torvalds } 15321da177e4SLinus Torvalds 15331da177e4SLinus Torvalds /* master output frequency */ 15341da177e4SLinus Torvalds if (! 15351da177e4SLinus Torvalds ((!(rme32->wcreg & RME32_WCR_FREQ_0)) 15361da177e4SLinus Torvalds && (!(rme32->wcreg & RME32_WCR_FREQ_1)))) { 15371da177e4SLinus Torvalds snd_iprintf(buffer, " sample rate: %d Hz\n", 15381da177e4SLinus Torvalds snd_rme32_playback_getrate(rme32)); 15391da177e4SLinus Torvalds } 15401da177e4SLinus Torvalds if (rme32->rcreg & RME32_RCR_KMODE) { 15411da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: AutoSync\n"); 15421da177e4SLinus Torvalds } else { 15431da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: Internal\n"); 15441da177e4SLinus Torvalds } 15451da177e4SLinus Torvalds if (rme32->wcreg & RME32_WCR_PRO) { 15461da177e4SLinus Torvalds snd_iprintf(buffer, " format: AES/EBU (professional)\n"); 15471da177e4SLinus Torvalds } else { 15481da177e4SLinus Torvalds snd_iprintf(buffer, " format: IEC958 (consumer)\n"); 15491da177e4SLinus Torvalds } 15501da177e4SLinus Torvalds if (rme32->wcreg & RME32_WCR_EMP) { 15511da177e4SLinus Torvalds snd_iprintf(buffer, " emphasis: on\n"); 15521da177e4SLinus Torvalds } else { 15531da177e4SLinus Torvalds snd_iprintf(buffer, " emphasis: off\n"); 15541da177e4SLinus Torvalds } 15551da177e4SLinus Torvalds } 15561da177e4SLinus Torvalds 1557017ce802STakashi Iwai static void __devinit snd_rme32_proc_init(struct rme32 * rme32) 15581da177e4SLinus Torvalds { 1559017ce802STakashi Iwai struct snd_info_entry *entry; 15601da177e4SLinus Torvalds 15611da177e4SLinus Torvalds if (! snd_card_proc_new(rme32->card, "rme32", &entry)) 1562bf850204STakashi Iwai snd_info_set_text_ops(entry, rme32, snd_rme32_proc_read); 15631da177e4SLinus Torvalds } 15641da177e4SLinus Torvalds 15651da177e4SLinus Torvalds /* 15661da177e4SLinus Torvalds * control interface 15671da177e4SLinus Torvalds */ 15681da177e4SLinus Torvalds 1569a5ce8890STakashi Iwai #define snd_rme32_info_loopback_control snd_ctl_boolean_mono_info 1570a5ce8890STakashi Iwai 15711da177e4SLinus Torvalds static int 1572017ce802STakashi Iwai snd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol, 1573017ce802STakashi Iwai struct snd_ctl_elem_value *ucontrol) 15741da177e4SLinus Torvalds { 1575017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 15761da177e4SLinus Torvalds 15771da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 15781da177e4SLinus Torvalds ucontrol->value.integer.value[0] = 15791da177e4SLinus Torvalds rme32->wcreg & RME32_WCR_SEL ? 0 : 1; 15801da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 15811da177e4SLinus Torvalds return 0; 15821da177e4SLinus Torvalds } 15831da177e4SLinus Torvalds static int 1584017ce802STakashi Iwai snd_rme32_put_loopback_control(struct snd_kcontrol *kcontrol, 1585017ce802STakashi Iwai struct snd_ctl_elem_value *ucontrol) 15861da177e4SLinus Torvalds { 1587017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 15881da177e4SLinus Torvalds unsigned int val; 15891da177e4SLinus Torvalds int change; 15901da177e4SLinus Torvalds 15911da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] ? 0 : RME32_WCR_SEL; 15921da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 15931da177e4SLinus Torvalds val = (rme32->wcreg & ~RME32_WCR_SEL) | val; 15941da177e4SLinus Torvalds change = val != rme32->wcreg; 15951da177e4SLinus Torvalds if (ucontrol->value.integer.value[0]) 15961da177e4SLinus Torvalds val &= ~RME32_WCR_MUTE; 15971da177e4SLinus Torvalds else 15981da177e4SLinus Torvalds val |= RME32_WCR_MUTE; 15991da177e4SLinus Torvalds rme32->wcreg = val; 16001da177e4SLinus Torvalds writel(val, rme32->iobase + RME32_IO_CONTROL_REGISTER); 16011da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 16021da177e4SLinus Torvalds return change; 16031da177e4SLinus Torvalds } 16041da177e4SLinus Torvalds 16051da177e4SLinus Torvalds static int 1606017ce802STakashi Iwai snd_rme32_info_inputtype_control(struct snd_kcontrol *kcontrol, 1607017ce802STakashi Iwai struct snd_ctl_elem_info *uinfo) 16081da177e4SLinus Torvalds { 1609017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 16101da177e4SLinus Torvalds static char *texts[4] = { "Optical", "Coaxial", "Internal", "XLR" }; 16111da177e4SLinus Torvalds 16121da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 16131da177e4SLinus Torvalds uinfo->count = 1; 16141da177e4SLinus Torvalds switch (rme32->pci->device) { 16158b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32: 16168b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32_8: 16171da177e4SLinus Torvalds uinfo->value.enumerated.items = 3; 16181da177e4SLinus Torvalds break; 16198b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32_PRO: 16201da177e4SLinus Torvalds uinfo->value.enumerated.items = 4; 16211da177e4SLinus Torvalds break; 16221da177e4SLinus Torvalds default: 16231da177e4SLinus Torvalds snd_BUG(); 16241da177e4SLinus Torvalds break; 16251da177e4SLinus Torvalds } 16261da177e4SLinus Torvalds if (uinfo->value.enumerated.item > 16271da177e4SLinus Torvalds uinfo->value.enumerated.items - 1) { 16281da177e4SLinus Torvalds uinfo->value.enumerated.item = 16291da177e4SLinus Torvalds uinfo->value.enumerated.items - 1; 16301da177e4SLinus Torvalds } 16311da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, 16321da177e4SLinus Torvalds texts[uinfo->value.enumerated.item]); 16331da177e4SLinus Torvalds return 0; 16341da177e4SLinus Torvalds } 16351da177e4SLinus Torvalds static int 1636017ce802STakashi Iwai snd_rme32_get_inputtype_control(struct snd_kcontrol *kcontrol, 1637017ce802STakashi Iwai struct snd_ctl_elem_value *ucontrol) 16381da177e4SLinus Torvalds { 1639017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 16401da177e4SLinus Torvalds unsigned int items = 3; 16411da177e4SLinus Torvalds 16421da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 16431da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = snd_rme32_getinputtype(rme32); 16441da177e4SLinus Torvalds 16451da177e4SLinus Torvalds switch (rme32->pci->device) { 16468b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32: 16478b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32_8: 16481da177e4SLinus Torvalds items = 3; 16491da177e4SLinus Torvalds break; 16508b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32_PRO: 16511da177e4SLinus Torvalds items = 4; 16521da177e4SLinus Torvalds break; 16531da177e4SLinus Torvalds default: 16541da177e4SLinus Torvalds snd_BUG(); 16551da177e4SLinus Torvalds break; 16561da177e4SLinus Torvalds } 16571da177e4SLinus Torvalds if (ucontrol->value.enumerated.item[0] >= items) { 16581da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = items - 1; 16591da177e4SLinus Torvalds } 16601da177e4SLinus Torvalds 16611da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 16621da177e4SLinus Torvalds return 0; 16631da177e4SLinus Torvalds } 16641da177e4SLinus Torvalds static int 1665017ce802STakashi Iwai snd_rme32_put_inputtype_control(struct snd_kcontrol *kcontrol, 1666017ce802STakashi Iwai struct snd_ctl_elem_value *ucontrol) 16671da177e4SLinus Torvalds { 1668017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 16691da177e4SLinus Torvalds unsigned int val; 16701da177e4SLinus Torvalds int change, items = 3; 16711da177e4SLinus Torvalds 16721da177e4SLinus Torvalds switch (rme32->pci->device) { 16738b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32: 16748b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32_8: 16751da177e4SLinus Torvalds items = 3; 16761da177e4SLinus Torvalds break; 16778b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32_PRO: 16781da177e4SLinus Torvalds items = 4; 16791da177e4SLinus Torvalds break; 16801da177e4SLinus Torvalds default: 16811da177e4SLinus Torvalds snd_BUG(); 16821da177e4SLinus Torvalds break; 16831da177e4SLinus Torvalds } 16841da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % items; 16851da177e4SLinus Torvalds 16861da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 16871da177e4SLinus Torvalds change = val != (unsigned int)snd_rme32_getinputtype(rme32); 16881da177e4SLinus Torvalds snd_rme32_setinputtype(rme32, val); 16891da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 16901da177e4SLinus Torvalds return change; 16911da177e4SLinus Torvalds } 16921da177e4SLinus Torvalds 16931da177e4SLinus Torvalds static int 1694017ce802STakashi Iwai snd_rme32_info_clockmode_control(struct snd_kcontrol *kcontrol, 1695017ce802STakashi Iwai struct snd_ctl_elem_info *uinfo) 16961da177e4SLinus Torvalds { 16971da177e4SLinus Torvalds static char *texts[4] = { "AutoSync", 16981da177e4SLinus Torvalds "Internal 32.0kHz", 16991da177e4SLinus Torvalds "Internal 44.1kHz", 17001da177e4SLinus Torvalds "Internal 48.0kHz" }; 17011da177e4SLinus Torvalds 17021da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 17031da177e4SLinus Torvalds uinfo->count = 1; 17041da177e4SLinus Torvalds uinfo->value.enumerated.items = 4; 17051da177e4SLinus Torvalds if (uinfo->value.enumerated.item > 3) { 17061da177e4SLinus Torvalds uinfo->value.enumerated.item = 3; 17071da177e4SLinus Torvalds } 17081da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, 17091da177e4SLinus Torvalds texts[uinfo->value.enumerated.item]); 17101da177e4SLinus Torvalds return 0; 17111da177e4SLinus Torvalds } 17121da177e4SLinus Torvalds static int 1713017ce802STakashi Iwai snd_rme32_get_clockmode_control(struct snd_kcontrol *kcontrol, 1714017ce802STakashi Iwai struct snd_ctl_elem_value *ucontrol) 17151da177e4SLinus Torvalds { 1716017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 17171da177e4SLinus Torvalds 17181da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 17191da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = snd_rme32_getclockmode(rme32); 17201da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 17211da177e4SLinus Torvalds return 0; 17221da177e4SLinus Torvalds } 17231da177e4SLinus Torvalds static int 1724017ce802STakashi Iwai snd_rme32_put_clockmode_control(struct snd_kcontrol *kcontrol, 1725017ce802STakashi Iwai struct snd_ctl_elem_value *ucontrol) 17261da177e4SLinus Torvalds { 1727017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 17281da177e4SLinus Torvalds unsigned int val; 17291da177e4SLinus Torvalds int change; 17301da177e4SLinus Torvalds 17311da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % 3; 17321da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 17331da177e4SLinus Torvalds change = val != (unsigned int)snd_rme32_getclockmode(rme32); 17341da177e4SLinus Torvalds snd_rme32_setclockmode(rme32, val); 17351da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 17361da177e4SLinus Torvalds return change; 17371da177e4SLinus Torvalds } 17381da177e4SLinus Torvalds 1739017ce802STakashi Iwai static u32 snd_rme32_convert_from_aes(struct snd_aes_iec958 * aes) 17401da177e4SLinus Torvalds { 17411da177e4SLinus Torvalds u32 val = 0; 17421da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME32_WCR_PRO : 0; 17431da177e4SLinus Torvalds if (val & RME32_WCR_PRO) 17441da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? RME32_WCR_EMP : 0; 17451da177e4SLinus Torvalds else 17461da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? RME32_WCR_EMP : 0; 17471da177e4SLinus Torvalds return val; 17481da177e4SLinus Torvalds } 17491da177e4SLinus Torvalds 1750017ce802STakashi Iwai static void snd_rme32_convert_to_aes(struct snd_aes_iec958 * aes, u32 val) 17511da177e4SLinus Torvalds { 17521da177e4SLinus Torvalds aes->status[0] = ((val & RME32_WCR_PRO) ? IEC958_AES0_PROFESSIONAL : 0); 17531da177e4SLinus Torvalds if (val & RME32_WCR_PRO) 17541da177e4SLinus Torvalds aes->status[0] |= (val & RME32_WCR_EMP) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; 17551da177e4SLinus Torvalds else 17561da177e4SLinus Torvalds aes->status[0] |= (val & RME32_WCR_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0; 17571da177e4SLinus Torvalds } 17581da177e4SLinus Torvalds 1759017ce802STakashi Iwai static int snd_rme32_control_spdif_info(struct snd_kcontrol *kcontrol, 1760017ce802STakashi Iwai struct snd_ctl_elem_info *uinfo) 17611da177e4SLinus Torvalds { 17621da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 17631da177e4SLinus Torvalds uinfo->count = 1; 17641da177e4SLinus Torvalds return 0; 17651da177e4SLinus Torvalds } 17661da177e4SLinus Torvalds 1767017ce802STakashi Iwai static int snd_rme32_control_spdif_get(struct snd_kcontrol *kcontrol, 1768017ce802STakashi Iwai struct snd_ctl_elem_value *ucontrol) 17691da177e4SLinus Torvalds { 1770017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 17711da177e4SLinus Torvalds 17721da177e4SLinus Torvalds snd_rme32_convert_to_aes(&ucontrol->value.iec958, 17731da177e4SLinus Torvalds rme32->wcreg_spdif); 17741da177e4SLinus Torvalds return 0; 17751da177e4SLinus Torvalds } 17761da177e4SLinus Torvalds 1777017ce802STakashi Iwai static int snd_rme32_control_spdif_put(struct snd_kcontrol *kcontrol, 1778017ce802STakashi Iwai struct snd_ctl_elem_value *ucontrol) 17791da177e4SLinus Torvalds { 1780017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 17811da177e4SLinus Torvalds int change; 17821da177e4SLinus Torvalds u32 val; 17831da177e4SLinus Torvalds 17841da177e4SLinus Torvalds val = snd_rme32_convert_from_aes(&ucontrol->value.iec958); 17851da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 17861da177e4SLinus Torvalds change = val != rme32->wcreg_spdif; 17871da177e4SLinus Torvalds rme32->wcreg_spdif = val; 17881da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 17891da177e4SLinus Torvalds return change; 17901da177e4SLinus Torvalds } 17911da177e4SLinus Torvalds 1792017ce802STakashi Iwai static int snd_rme32_control_spdif_stream_info(struct snd_kcontrol *kcontrol, 1793017ce802STakashi Iwai struct snd_ctl_elem_info *uinfo) 17941da177e4SLinus Torvalds { 17951da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 17961da177e4SLinus Torvalds uinfo->count = 1; 17971da177e4SLinus Torvalds return 0; 17981da177e4SLinus Torvalds } 17991da177e4SLinus Torvalds 1800017ce802STakashi Iwai static int snd_rme32_control_spdif_stream_get(struct snd_kcontrol *kcontrol, 1801017ce802STakashi Iwai struct snd_ctl_elem_value * 18021da177e4SLinus Torvalds ucontrol) 18031da177e4SLinus Torvalds { 1804017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 18051da177e4SLinus Torvalds 18061da177e4SLinus Torvalds snd_rme32_convert_to_aes(&ucontrol->value.iec958, 18071da177e4SLinus Torvalds rme32->wcreg_spdif_stream); 18081da177e4SLinus Torvalds return 0; 18091da177e4SLinus Torvalds } 18101da177e4SLinus Torvalds 1811017ce802STakashi Iwai static int snd_rme32_control_spdif_stream_put(struct snd_kcontrol *kcontrol, 1812017ce802STakashi Iwai struct snd_ctl_elem_value * 18131da177e4SLinus Torvalds ucontrol) 18141da177e4SLinus Torvalds { 1815017ce802STakashi Iwai struct rme32 *rme32 = snd_kcontrol_chip(kcontrol); 18161da177e4SLinus Torvalds int change; 18171da177e4SLinus Torvalds u32 val; 18181da177e4SLinus Torvalds 18191da177e4SLinus Torvalds val = snd_rme32_convert_from_aes(&ucontrol->value.iec958); 18201da177e4SLinus Torvalds spin_lock_irq(&rme32->lock); 18211da177e4SLinus Torvalds change = val != rme32->wcreg_spdif_stream; 18221da177e4SLinus Torvalds rme32->wcreg_spdif_stream = val; 18231da177e4SLinus Torvalds rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP); 18241da177e4SLinus Torvalds rme32->wcreg |= val; 18251da177e4SLinus Torvalds writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER); 18261da177e4SLinus Torvalds spin_unlock_irq(&rme32->lock); 18271da177e4SLinus Torvalds return change; 18281da177e4SLinus Torvalds } 18291da177e4SLinus Torvalds 1830017ce802STakashi Iwai static int snd_rme32_control_spdif_mask_info(struct snd_kcontrol *kcontrol, 1831017ce802STakashi Iwai struct snd_ctl_elem_info *uinfo) 18321da177e4SLinus Torvalds { 18331da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 18341da177e4SLinus Torvalds uinfo->count = 1; 18351da177e4SLinus Torvalds return 0; 18361da177e4SLinus Torvalds } 18371da177e4SLinus Torvalds 1838017ce802STakashi Iwai static int snd_rme32_control_spdif_mask_get(struct snd_kcontrol *kcontrol, 1839017ce802STakashi Iwai struct snd_ctl_elem_value * 18401da177e4SLinus Torvalds ucontrol) 18411da177e4SLinus Torvalds { 18421da177e4SLinus Torvalds ucontrol->value.iec958.status[0] = kcontrol->private_value; 18431da177e4SLinus Torvalds return 0; 18441da177e4SLinus Torvalds } 18451da177e4SLinus Torvalds 1846017ce802STakashi Iwai static struct snd_kcontrol_new snd_rme32_controls[] = { 18471da177e4SLinus Torvalds { 18481da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 18491da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), 18501da177e4SLinus Torvalds .info = snd_rme32_control_spdif_info, 18511da177e4SLinus Torvalds .get = snd_rme32_control_spdif_get, 18521da177e4SLinus Torvalds .put = snd_rme32_control_spdif_put 18531da177e4SLinus Torvalds }, 18541da177e4SLinus Torvalds { 18551da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 18561da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 18571da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), 18581da177e4SLinus Torvalds .info = snd_rme32_control_spdif_stream_info, 18591da177e4SLinus Torvalds .get = snd_rme32_control_spdif_stream_get, 18601da177e4SLinus Torvalds .put = snd_rme32_control_spdif_stream_put 18611da177e4SLinus Torvalds }, 18621da177e4SLinus Torvalds { 18631da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, 186467ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 18651da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), 18661da177e4SLinus Torvalds .info = snd_rme32_control_spdif_mask_info, 18671da177e4SLinus Torvalds .get = snd_rme32_control_spdif_mask_get, 18681da177e4SLinus Torvalds .private_value = IEC958_AES0_PROFESSIONAL | IEC958_AES0_CON_EMPHASIS 18691da177e4SLinus Torvalds }, 18701da177e4SLinus Torvalds { 18711da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, 187267ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 18731da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), 18741da177e4SLinus Torvalds .info = snd_rme32_control_spdif_mask_info, 18751da177e4SLinus Torvalds .get = snd_rme32_control_spdif_mask_get, 18761da177e4SLinus Torvalds .private_value = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_EMPHASIS 18771da177e4SLinus Torvalds }, 18781da177e4SLinus Torvalds { 18791da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 18801da177e4SLinus Torvalds .name = "Input Connector", 18811da177e4SLinus Torvalds .info = snd_rme32_info_inputtype_control, 18821da177e4SLinus Torvalds .get = snd_rme32_get_inputtype_control, 18831da177e4SLinus Torvalds .put = snd_rme32_put_inputtype_control 18841da177e4SLinus Torvalds }, 18851da177e4SLinus Torvalds { 18861da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 18871da177e4SLinus Torvalds .name = "Loopback Input", 18881da177e4SLinus Torvalds .info = snd_rme32_info_loopback_control, 18891da177e4SLinus Torvalds .get = snd_rme32_get_loopback_control, 18901da177e4SLinus Torvalds .put = snd_rme32_put_loopback_control 18911da177e4SLinus Torvalds }, 18921da177e4SLinus Torvalds { 18931da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 18941da177e4SLinus Torvalds .name = "Sample Clock Source", 18951da177e4SLinus Torvalds .info = snd_rme32_info_clockmode_control, 18961da177e4SLinus Torvalds .get = snd_rme32_get_clockmode_control, 18971da177e4SLinus Torvalds .put = snd_rme32_put_clockmode_control 18981da177e4SLinus Torvalds } 18991da177e4SLinus Torvalds }; 19001da177e4SLinus Torvalds 1901017ce802STakashi Iwai static int snd_rme32_create_switches(struct snd_card *card, struct rme32 * rme32) 19021da177e4SLinus Torvalds { 19031da177e4SLinus Torvalds int idx, err; 1904017ce802STakashi Iwai struct snd_kcontrol *kctl; 19051da177e4SLinus Torvalds 19061da177e4SLinus Torvalds for (idx = 0; idx < (int)ARRAY_SIZE(snd_rme32_controls); idx++) { 19071da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme32_controls[idx], rme32))) < 0) 19081da177e4SLinus Torvalds return err; 19091da177e4SLinus Torvalds if (idx == 1) /* IEC958 (S/PDIF) Stream */ 19101da177e4SLinus Torvalds rme32->spdif_ctl = kctl; 19111da177e4SLinus Torvalds } 19121da177e4SLinus Torvalds 19131da177e4SLinus Torvalds return 0; 19141da177e4SLinus Torvalds } 19151da177e4SLinus Torvalds 19161da177e4SLinus Torvalds /* 19171da177e4SLinus Torvalds * Card initialisation 19181da177e4SLinus Torvalds */ 19191da177e4SLinus Torvalds 1920017ce802STakashi Iwai static void snd_rme32_card_free(struct snd_card *card) 19211da177e4SLinus Torvalds { 19221da177e4SLinus Torvalds snd_rme32_free(card->private_data); 19231da177e4SLinus Torvalds } 19241da177e4SLinus Torvalds 19251da177e4SLinus Torvalds static int __devinit 19261da177e4SLinus Torvalds snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) 19271da177e4SLinus Torvalds { 19281da177e4SLinus Torvalds static int dev; 1929017ce802STakashi Iwai struct rme32 *rme32; 1930017ce802STakashi Iwai struct snd_card *card; 19311da177e4SLinus Torvalds int err; 19321da177e4SLinus Torvalds 19331da177e4SLinus Torvalds if (dev >= SNDRV_CARDS) { 19341da177e4SLinus Torvalds return -ENODEV; 19351da177e4SLinus Torvalds } 19361da177e4SLinus Torvalds if (!enable[dev]) { 19371da177e4SLinus Torvalds dev++; 19381da177e4SLinus Torvalds return -ENOENT; 19391da177e4SLinus Torvalds } 19401da177e4SLinus Torvalds 1941e58de7baSTakashi Iwai err = snd_card_create(index[dev], id[dev], THIS_MODULE, 1942e58de7baSTakashi Iwai sizeof(struct rme32), &card); 1943e58de7baSTakashi Iwai if (err < 0) 1944e58de7baSTakashi Iwai return err; 19451da177e4SLinus Torvalds card->private_free = snd_rme32_card_free; 1946017ce802STakashi Iwai rme32 = (struct rme32 *) card->private_data; 19471da177e4SLinus Torvalds rme32->card = card; 19481da177e4SLinus Torvalds rme32->pci = pci; 19491da177e4SLinus Torvalds snd_card_set_dev(card, &pci->dev); 19501da177e4SLinus Torvalds if (fullduplex[dev]) 19511da177e4SLinus Torvalds rme32->fullduplex_mode = 1; 19521da177e4SLinus Torvalds if ((err = snd_rme32_create(rme32)) < 0) { 19531da177e4SLinus Torvalds snd_card_free(card); 19541da177e4SLinus Torvalds return err; 19551da177e4SLinus Torvalds } 19561da177e4SLinus Torvalds 19571da177e4SLinus Torvalds strcpy(card->driver, "Digi32"); 19581da177e4SLinus Torvalds switch (rme32->pci->device) { 19598b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32: 19601da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi32"); 19611da177e4SLinus Torvalds break; 19628b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32_8: 19631da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi32/8"); 19641da177e4SLinus Torvalds break; 19658b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI32_PRO: 19661da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi32 PRO"); 19671da177e4SLinus Torvalds break; 19681da177e4SLinus Torvalds } 19691da177e4SLinus Torvalds sprintf(card->longname, "%s (Rev. %d) at 0x%lx, irq %d", 19701da177e4SLinus Torvalds card->shortname, rme32->rev, rme32->port, rme32->irq); 19711da177e4SLinus Torvalds 19721da177e4SLinus Torvalds if ((err = snd_card_register(card)) < 0) { 19731da177e4SLinus Torvalds snd_card_free(card); 19741da177e4SLinus Torvalds return err; 19751da177e4SLinus Torvalds } 19761da177e4SLinus Torvalds pci_set_drvdata(pci, card); 19771da177e4SLinus Torvalds dev++; 19781da177e4SLinus Torvalds return 0; 19791da177e4SLinus Torvalds } 19801da177e4SLinus Torvalds 19811da177e4SLinus Torvalds static void __devexit snd_rme32_remove(struct pci_dev *pci) 19821da177e4SLinus Torvalds { 19831da177e4SLinus Torvalds snd_card_free(pci_get_drvdata(pci)); 19841da177e4SLinus Torvalds pci_set_drvdata(pci, NULL); 19851da177e4SLinus Torvalds } 19861da177e4SLinus Torvalds 1987*e9f66d9bSTakashi Iwai static struct pci_driver rme32_driver = { 19883733e424STakashi Iwai .name = KBUILD_MODNAME, 19891da177e4SLinus Torvalds .id_table = snd_rme32_ids, 19901da177e4SLinus Torvalds .probe = snd_rme32_probe, 19911da177e4SLinus Torvalds .remove = __devexit_p(snd_rme32_remove), 19921da177e4SLinus Torvalds }; 19931da177e4SLinus Torvalds 1994*e9f66d9bSTakashi Iwai module_pci_driver(rme32_driver); 1995