11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * ALSA driver for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST audio 31da177e4SLinus Torvalds * interfaces 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (c) 2000, 2001 Anders Torger <torger@ludd.luth.se> 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * Thanks to Henk Hesselink <henk@anda.nl> for the analog volume control 81da177e4SLinus Torvalds * code. 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 111da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 121da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 131da177e4SLinus Torvalds * (at your option) any later version. 141da177e4SLinus Torvalds * 151da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 161da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 171da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 181da177e4SLinus Torvalds * GNU General Public License for more details. 191da177e4SLinus Torvalds * 201da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 211da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 221da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 231da177e4SLinus Torvalds * 241da177e4SLinus Torvalds */ 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds #include <sound/driver.h> 271da177e4SLinus Torvalds #include <linux/delay.h> 281da177e4SLinus Torvalds #include <linux/init.h> 291da177e4SLinus Torvalds #include <linux/interrupt.h> 301da177e4SLinus Torvalds #include <linux/pci.h> 311da177e4SLinus Torvalds #include <linux/slab.h> 321da177e4SLinus Torvalds #include <linux/moduleparam.h> 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds #include <sound/core.h> 351da177e4SLinus Torvalds #include <sound/info.h> 361da177e4SLinus Torvalds #include <sound/control.h> 371da177e4SLinus Torvalds #include <sound/pcm.h> 381da177e4SLinus Torvalds #include <sound/pcm_params.h> 391da177e4SLinus Torvalds #include <sound/asoundef.h> 401da177e4SLinus Torvalds #include <sound/initval.h> 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds #include <asm/io.h> 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds /* note, two last pcis should be equal, it is not a bug */ 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds MODULE_AUTHOR("Anders Torger <torger@ludd.luth.se>"); 471da177e4SLinus Torvalds MODULE_DESCRIPTION("RME Digi96, Digi96/8, Digi96/8 PRO, Digi96/8 PST, " 481da177e4SLinus Torvalds "Digi96/8 PAD"); 491da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 501da177e4SLinus Torvalds MODULE_SUPPORTED_DEVICE("{{RME,Digi96}," 511da177e4SLinus Torvalds "{RME,Digi96/8}," 521da177e4SLinus Torvalds "{RME,Digi96/8 PRO}," 531da177e4SLinus Torvalds "{RME,Digi96/8 PST}," 541da177e4SLinus Torvalds "{RME,Digi96/8 PAD}}"); 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 571da177e4SLinus Torvalds static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 581da177e4SLinus Torvalds static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds module_param_array(index, int, NULL, 0444); 611da177e4SLinus Torvalds MODULE_PARM_DESC(index, "Index value for RME Digi96 soundcard."); 621da177e4SLinus Torvalds module_param_array(id, charp, NULL, 0444); 631da177e4SLinus Torvalds MODULE_PARM_DESC(id, "ID string for RME Digi96 soundcard."); 641da177e4SLinus Torvalds module_param_array(enable, bool, NULL, 0444); 651da177e4SLinus Torvalds MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard."); 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds /* 681da177e4SLinus Torvalds * Defines for RME Digi96 series, from internal RME reference documents 691da177e4SLinus Torvalds * dated 12.01.00 701da177e4SLinus Torvalds */ 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds #define RME96_SPDIF_NCHANNELS 2 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds /* Playback and capture buffer size */ 751da177e4SLinus Torvalds #define RME96_BUFFER_SIZE 0x10000 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds /* IO area size */ 781da177e4SLinus Torvalds #define RME96_IO_SIZE 0x60000 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds /* IO area offsets */ 811da177e4SLinus Torvalds #define RME96_IO_PLAY_BUFFER 0x0 821da177e4SLinus Torvalds #define RME96_IO_REC_BUFFER 0x10000 831da177e4SLinus Torvalds #define RME96_IO_CONTROL_REGISTER 0x20000 841da177e4SLinus Torvalds #define RME96_IO_ADDITIONAL_REG 0x20004 851da177e4SLinus Torvalds #define RME96_IO_CONFIRM_PLAY_IRQ 0x20008 861da177e4SLinus Torvalds #define RME96_IO_CONFIRM_REC_IRQ 0x2000C 871da177e4SLinus Torvalds #define RME96_IO_SET_PLAY_POS 0x40000 881da177e4SLinus Torvalds #define RME96_IO_RESET_PLAY_POS 0x4FFFC 891da177e4SLinus Torvalds #define RME96_IO_SET_REC_POS 0x50000 901da177e4SLinus Torvalds #define RME96_IO_RESET_REC_POS 0x5FFFC 911da177e4SLinus Torvalds #define RME96_IO_GET_PLAY_POS 0x20000 921da177e4SLinus Torvalds #define RME96_IO_GET_REC_POS 0x30000 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds /* Write control register bits */ 951da177e4SLinus Torvalds #define RME96_WCR_START (1 << 0) 961da177e4SLinus Torvalds #define RME96_WCR_START_2 (1 << 1) 971da177e4SLinus Torvalds #define RME96_WCR_GAIN_0 (1 << 2) 981da177e4SLinus Torvalds #define RME96_WCR_GAIN_1 (1 << 3) 991da177e4SLinus Torvalds #define RME96_WCR_MODE24 (1 << 4) 1001da177e4SLinus Torvalds #define RME96_WCR_MODE24_2 (1 << 5) 1011da177e4SLinus Torvalds #define RME96_WCR_BM (1 << 6) 1021da177e4SLinus Torvalds #define RME96_WCR_BM_2 (1 << 7) 1031da177e4SLinus Torvalds #define RME96_WCR_ADAT (1 << 8) 1041da177e4SLinus Torvalds #define RME96_WCR_FREQ_0 (1 << 9) 1051da177e4SLinus Torvalds #define RME96_WCR_FREQ_1 (1 << 10) 1061da177e4SLinus Torvalds #define RME96_WCR_DS (1 << 11) 1071da177e4SLinus Torvalds #define RME96_WCR_PRO (1 << 12) 1081da177e4SLinus Torvalds #define RME96_WCR_EMP (1 << 13) 1091da177e4SLinus Torvalds #define RME96_WCR_SEL (1 << 14) 1101da177e4SLinus Torvalds #define RME96_WCR_MASTER (1 << 15) 1111da177e4SLinus Torvalds #define RME96_WCR_PD (1 << 16) 1121da177e4SLinus Torvalds #define RME96_WCR_INP_0 (1 << 17) 1131da177e4SLinus Torvalds #define RME96_WCR_INP_1 (1 << 18) 1141da177e4SLinus Torvalds #define RME96_WCR_THRU_0 (1 << 19) 1151da177e4SLinus Torvalds #define RME96_WCR_THRU_1 (1 << 20) 1161da177e4SLinus Torvalds #define RME96_WCR_THRU_2 (1 << 21) 1171da177e4SLinus Torvalds #define RME96_WCR_THRU_3 (1 << 22) 1181da177e4SLinus Torvalds #define RME96_WCR_THRU_4 (1 << 23) 1191da177e4SLinus Torvalds #define RME96_WCR_THRU_5 (1 << 24) 1201da177e4SLinus Torvalds #define RME96_WCR_THRU_6 (1 << 25) 1211da177e4SLinus Torvalds #define RME96_WCR_THRU_7 (1 << 26) 1221da177e4SLinus Torvalds #define RME96_WCR_DOLBY (1 << 27) 1231da177e4SLinus Torvalds #define RME96_WCR_MONITOR_0 (1 << 28) 1241da177e4SLinus Torvalds #define RME96_WCR_MONITOR_1 (1 << 29) 1251da177e4SLinus Torvalds #define RME96_WCR_ISEL (1 << 30) 1261da177e4SLinus Torvalds #define RME96_WCR_IDIS (1 << 31) 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds #define RME96_WCR_BITPOS_GAIN_0 2 1291da177e4SLinus Torvalds #define RME96_WCR_BITPOS_GAIN_1 3 1301da177e4SLinus Torvalds #define RME96_WCR_BITPOS_FREQ_0 9 1311da177e4SLinus Torvalds #define RME96_WCR_BITPOS_FREQ_1 10 1321da177e4SLinus Torvalds #define RME96_WCR_BITPOS_INP_0 17 1331da177e4SLinus Torvalds #define RME96_WCR_BITPOS_INP_1 18 1341da177e4SLinus Torvalds #define RME96_WCR_BITPOS_MONITOR_0 28 1351da177e4SLinus Torvalds #define RME96_WCR_BITPOS_MONITOR_1 29 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds /* Read control register bits */ 1381da177e4SLinus Torvalds #define RME96_RCR_AUDIO_ADDR_MASK 0xFFFF 1391da177e4SLinus Torvalds #define RME96_RCR_IRQ_2 (1 << 16) 1401da177e4SLinus Torvalds #define RME96_RCR_T_OUT (1 << 17) 1411da177e4SLinus Torvalds #define RME96_RCR_DEV_ID_0 (1 << 21) 1421da177e4SLinus Torvalds #define RME96_RCR_DEV_ID_1 (1 << 22) 1431da177e4SLinus Torvalds #define RME96_RCR_LOCK (1 << 23) 1441da177e4SLinus Torvalds #define RME96_RCR_VERF (1 << 26) 1451da177e4SLinus Torvalds #define RME96_RCR_F0 (1 << 27) 1461da177e4SLinus Torvalds #define RME96_RCR_F1 (1 << 28) 1471da177e4SLinus Torvalds #define RME96_RCR_F2 (1 << 29) 1481da177e4SLinus Torvalds #define RME96_RCR_AUTOSYNC (1 << 30) 1491da177e4SLinus Torvalds #define RME96_RCR_IRQ (1 << 31) 1501da177e4SLinus Torvalds 1511da177e4SLinus Torvalds #define RME96_RCR_BITPOS_F0 27 1521da177e4SLinus Torvalds #define RME96_RCR_BITPOS_F1 28 1531da177e4SLinus Torvalds #define RME96_RCR_BITPOS_F2 29 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds /* Additonal register bits */ 1561da177e4SLinus Torvalds #define RME96_AR_WSEL (1 << 0) 1571da177e4SLinus Torvalds #define RME96_AR_ANALOG (1 << 1) 1581da177e4SLinus Torvalds #define RME96_AR_FREQPAD_0 (1 << 2) 1591da177e4SLinus Torvalds #define RME96_AR_FREQPAD_1 (1 << 3) 1601da177e4SLinus Torvalds #define RME96_AR_FREQPAD_2 (1 << 4) 1611da177e4SLinus Torvalds #define RME96_AR_PD2 (1 << 5) 1621da177e4SLinus Torvalds #define RME96_AR_DAC_EN (1 << 6) 1631da177e4SLinus Torvalds #define RME96_AR_CLATCH (1 << 7) 1641da177e4SLinus Torvalds #define RME96_AR_CCLK (1 << 8) 1651da177e4SLinus Torvalds #define RME96_AR_CDATA (1 << 9) 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds #define RME96_AR_BITPOS_F0 2 1681da177e4SLinus Torvalds #define RME96_AR_BITPOS_F1 3 1691da177e4SLinus Torvalds #define RME96_AR_BITPOS_F2 4 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds /* Monitor tracks */ 1721da177e4SLinus Torvalds #define RME96_MONITOR_TRACKS_1_2 0 1731da177e4SLinus Torvalds #define RME96_MONITOR_TRACKS_3_4 1 1741da177e4SLinus Torvalds #define RME96_MONITOR_TRACKS_5_6 2 1751da177e4SLinus Torvalds #define RME96_MONITOR_TRACKS_7_8 3 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds /* Attenuation */ 1781da177e4SLinus Torvalds #define RME96_ATTENUATION_0 0 1791da177e4SLinus Torvalds #define RME96_ATTENUATION_6 1 1801da177e4SLinus Torvalds #define RME96_ATTENUATION_12 2 1811da177e4SLinus Torvalds #define RME96_ATTENUATION_18 3 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds /* Input types */ 1841da177e4SLinus Torvalds #define RME96_INPUT_OPTICAL 0 1851da177e4SLinus Torvalds #define RME96_INPUT_COAXIAL 1 1861da177e4SLinus Torvalds #define RME96_INPUT_INTERNAL 2 1871da177e4SLinus Torvalds #define RME96_INPUT_XLR 3 1881da177e4SLinus Torvalds #define RME96_INPUT_ANALOG 4 1891da177e4SLinus Torvalds 1901da177e4SLinus Torvalds /* Clock modes */ 1911da177e4SLinus Torvalds #define RME96_CLOCKMODE_SLAVE 0 1921da177e4SLinus Torvalds #define RME96_CLOCKMODE_MASTER 1 1931da177e4SLinus Torvalds #define RME96_CLOCKMODE_WORDCLOCK 2 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds /* Block sizes in bytes */ 1961da177e4SLinus Torvalds #define RME96_SMALL_BLOCK_SIZE 2048 1971da177e4SLinus Torvalds #define RME96_LARGE_BLOCK_SIZE 8192 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds /* Volume control */ 2001da177e4SLinus Torvalds #define RME96_AD1852_VOL_BITS 14 2011da177e4SLinus Torvalds #define RME96_AD1855_VOL_BITS 10 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds 204a3aefd88STakashi Iwai struct rme96 { 2051da177e4SLinus Torvalds spinlock_t lock; 2061da177e4SLinus Torvalds int irq; 2071da177e4SLinus Torvalds unsigned long port; 2081da177e4SLinus Torvalds void __iomem *iobase; 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds u32 wcreg; /* cached write control register value */ 2111da177e4SLinus Torvalds u32 wcreg_spdif; /* S/PDIF setup */ 2121da177e4SLinus Torvalds u32 wcreg_spdif_stream; /* S/PDIF setup (temporary) */ 2131da177e4SLinus Torvalds u32 rcreg; /* cached read control register value */ 2141da177e4SLinus Torvalds u32 areg; /* cached additional register value */ 2151da177e4SLinus Torvalds u16 vol[2]; /* cached volume of analog output */ 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds u8 rev; /* card revision number */ 2181da177e4SLinus Torvalds 219a3aefd88STakashi Iwai struct snd_pcm_substream *playback_substream; 220a3aefd88STakashi Iwai struct snd_pcm_substream *capture_substream; 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds int playback_frlog; /* log2 of framesize */ 2231da177e4SLinus Torvalds int capture_frlog; 2241da177e4SLinus Torvalds 2251da177e4SLinus Torvalds size_t playback_periodsize; /* in bytes, zero if not used */ 2261da177e4SLinus Torvalds size_t capture_periodsize; /* in bytes, zero if not used */ 2271da177e4SLinus Torvalds 228a3aefd88STakashi Iwai struct snd_card *card; 229a3aefd88STakashi Iwai struct snd_pcm *spdif_pcm; 230a3aefd88STakashi Iwai struct snd_pcm *adat_pcm; 2311da177e4SLinus Torvalds struct pci_dev *pci; 232a3aefd88STakashi Iwai struct snd_kcontrol *spdif_ctl; 233a3aefd88STakashi Iwai }; 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds static struct pci_device_id snd_rme96_ids[] = { 2368b7fc421SRoland Dreier { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96, 2371da177e4SLinus Torvalds PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 2388b7fc421SRoland Dreier { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8, 2391da177e4SLinus Torvalds PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 2408b7fc421SRoland Dreier { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO, 2411da177e4SLinus Torvalds PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 2428b7fc421SRoland Dreier { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST, 2431da177e4SLinus Torvalds PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 2441da177e4SLinus Torvalds { 0, } 2451da177e4SLinus Torvalds }; 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, snd_rme96_ids); 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds #define RME96_ISPLAYING(rme96) ((rme96)->wcreg & RME96_WCR_START) 2501da177e4SLinus Torvalds #define RME96_ISRECORDING(rme96) ((rme96)->wcreg & RME96_WCR_START_2) 2518b7fc421SRoland Dreier #define RME96_HAS_ANALOG_IN(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST) 2528b7fc421SRoland Dreier #define RME96_HAS_ANALOG_OUT(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO || \ 2538b7fc421SRoland Dreier (rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST) 2541da177e4SLinus Torvalds #define RME96_DAC_IS_1852(rme96) (RME96_HAS_ANALOG_OUT(rme96) && (rme96)->rev >= 4) 2558b7fc421SRoland Dreier #define RME96_DAC_IS_1855(rme96) (((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && (rme96)->rev < 4) || \ 2568b7fc421SRoland Dreier ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO && (rme96)->rev == 2)) 2571da177e4SLinus Torvalds #define RME96_185X_MAX_OUT(rme96) ((1 << (RME96_DAC_IS_1852(rme96) ? RME96_AD1852_VOL_BITS : RME96_AD1855_VOL_BITS)) - 1) 2581da177e4SLinus Torvalds 2591da177e4SLinus Torvalds static int 260a3aefd88STakashi Iwai snd_rme96_playback_prepare(struct snd_pcm_substream *substream); 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds static int 263a3aefd88STakashi Iwai snd_rme96_capture_prepare(struct snd_pcm_substream *substream); 2641da177e4SLinus Torvalds 2651da177e4SLinus Torvalds static int 266a3aefd88STakashi Iwai snd_rme96_playback_trigger(struct snd_pcm_substream *substream, 2671da177e4SLinus Torvalds int cmd); 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds static int 270a3aefd88STakashi Iwai snd_rme96_capture_trigger(struct snd_pcm_substream *substream, 2711da177e4SLinus Torvalds int cmd); 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds static snd_pcm_uframes_t 274a3aefd88STakashi Iwai snd_rme96_playback_pointer(struct snd_pcm_substream *substream); 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds static snd_pcm_uframes_t 277a3aefd88STakashi Iwai snd_rme96_capture_pointer(struct snd_pcm_substream *substream); 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds static void __devinit 280a3aefd88STakashi Iwai snd_rme96_proc_init(struct rme96 *rme96); 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds static int 283a3aefd88STakashi Iwai snd_rme96_create_switches(struct snd_card *card, 284a3aefd88STakashi Iwai struct rme96 *rme96); 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds static int 287a3aefd88STakashi Iwai snd_rme96_getinputtype(struct rme96 *rme96); 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds static inline unsigned int 290a3aefd88STakashi Iwai snd_rme96_playback_ptr(struct rme96 *rme96) 2911da177e4SLinus Torvalds { 2921da177e4SLinus Torvalds return (readl(rme96->iobase + RME96_IO_GET_PLAY_POS) 2931da177e4SLinus Torvalds & RME96_RCR_AUDIO_ADDR_MASK) >> rme96->playback_frlog; 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds static inline unsigned int 297a3aefd88STakashi Iwai snd_rme96_capture_ptr(struct rme96 *rme96) 2981da177e4SLinus Torvalds { 2991da177e4SLinus Torvalds return (readl(rme96->iobase + RME96_IO_GET_REC_POS) 3001da177e4SLinus Torvalds & RME96_RCR_AUDIO_ADDR_MASK) >> rme96->capture_frlog; 3011da177e4SLinus Torvalds } 3021da177e4SLinus Torvalds 3031da177e4SLinus Torvalds static int 3041da177e4SLinus Torvalds snd_rme96_ratecode(int rate) 3051da177e4SLinus Torvalds { 3061da177e4SLinus Torvalds switch (rate) { 3071da177e4SLinus Torvalds case 32000: return SNDRV_PCM_RATE_32000; 3081da177e4SLinus Torvalds case 44100: return SNDRV_PCM_RATE_44100; 3091da177e4SLinus Torvalds case 48000: return SNDRV_PCM_RATE_48000; 3101da177e4SLinus Torvalds case 64000: return SNDRV_PCM_RATE_64000; 3111da177e4SLinus Torvalds case 88200: return SNDRV_PCM_RATE_88200; 3121da177e4SLinus Torvalds case 96000: return SNDRV_PCM_RATE_96000; 3131da177e4SLinus Torvalds } 3141da177e4SLinus Torvalds return 0; 3151da177e4SLinus Torvalds } 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds static int 318a3aefd88STakashi Iwai snd_rme96_playback_silence(struct snd_pcm_substream *substream, 3191da177e4SLinus Torvalds int channel, /* not used (interleaved data) */ 3201da177e4SLinus Torvalds snd_pcm_uframes_t pos, 3211da177e4SLinus Torvalds snd_pcm_uframes_t count) 3221da177e4SLinus Torvalds { 323a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 3241da177e4SLinus Torvalds count <<= rme96->playback_frlog; 3251da177e4SLinus Torvalds pos <<= rme96->playback_frlog; 3261da177e4SLinus Torvalds memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, 3271da177e4SLinus Torvalds 0, count); 3281da177e4SLinus Torvalds return 0; 3291da177e4SLinus Torvalds } 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds static int 332a3aefd88STakashi Iwai snd_rme96_playback_copy(struct snd_pcm_substream *substream, 3331da177e4SLinus Torvalds int channel, /* not used (interleaved data) */ 3341da177e4SLinus Torvalds snd_pcm_uframes_t pos, 3351da177e4SLinus Torvalds void __user *src, 3361da177e4SLinus Torvalds snd_pcm_uframes_t count) 3371da177e4SLinus Torvalds { 338a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 3391da177e4SLinus Torvalds count <<= rme96->playback_frlog; 3401da177e4SLinus Torvalds pos <<= rme96->playback_frlog; 3411da177e4SLinus Torvalds copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, 3421da177e4SLinus Torvalds count); 3431da177e4SLinus Torvalds return 0; 3441da177e4SLinus Torvalds } 3451da177e4SLinus Torvalds 3461da177e4SLinus Torvalds static int 347a3aefd88STakashi Iwai snd_rme96_capture_copy(struct snd_pcm_substream *substream, 3481da177e4SLinus Torvalds int channel, /* not used (interleaved data) */ 3491da177e4SLinus Torvalds snd_pcm_uframes_t pos, 3501da177e4SLinus Torvalds void __user *dst, 3511da177e4SLinus Torvalds snd_pcm_uframes_t count) 3521da177e4SLinus Torvalds { 353a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 3541da177e4SLinus Torvalds count <<= rme96->capture_frlog; 3551da177e4SLinus Torvalds pos <<= rme96->capture_frlog; 3561da177e4SLinus Torvalds copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, 3571da177e4SLinus Torvalds count); 3581da177e4SLinus Torvalds return 0; 3591da177e4SLinus Torvalds } 3601da177e4SLinus Torvalds 3611da177e4SLinus Torvalds /* 362*7f927fccSAlexey Dobriyan * Digital output capabilities (S/PDIF) 3631da177e4SLinus Torvalds */ 364a3aefd88STakashi Iwai static struct snd_pcm_hardware snd_rme96_playback_spdif_info = 3651da177e4SLinus Torvalds { 3661da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP_IOMEM | 3671da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 3681da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 3691da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE), 3701da177e4SLinus Torvalds .formats = (SNDRV_PCM_FMTBIT_S16_LE | 3711da177e4SLinus Torvalds SNDRV_PCM_FMTBIT_S32_LE), 3721da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_32000 | 3731da177e4SLinus Torvalds SNDRV_PCM_RATE_44100 | 3741da177e4SLinus Torvalds SNDRV_PCM_RATE_48000 | 3751da177e4SLinus Torvalds SNDRV_PCM_RATE_64000 | 3761da177e4SLinus Torvalds SNDRV_PCM_RATE_88200 | 3771da177e4SLinus Torvalds SNDRV_PCM_RATE_96000), 3781da177e4SLinus Torvalds .rate_min = 32000, 3791da177e4SLinus Torvalds .rate_max = 96000, 3801da177e4SLinus Torvalds .channels_min = 2, 3811da177e4SLinus Torvalds .channels_max = 2, 3821da177e4SLinus Torvalds .buffer_bytes_max = RME96_BUFFER_SIZE, 3831da177e4SLinus Torvalds .period_bytes_min = RME96_SMALL_BLOCK_SIZE, 3841da177e4SLinus Torvalds .period_bytes_max = RME96_LARGE_BLOCK_SIZE, 3851da177e4SLinus Torvalds .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, 3861da177e4SLinus Torvalds .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, 3871da177e4SLinus Torvalds .fifo_size = 0, 3881da177e4SLinus Torvalds }; 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds /* 391*7f927fccSAlexey Dobriyan * Digital input capabilities (S/PDIF) 3921da177e4SLinus Torvalds */ 393a3aefd88STakashi Iwai static struct snd_pcm_hardware snd_rme96_capture_spdif_info = 3941da177e4SLinus Torvalds { 3951da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP_IOMEM | 3961da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 3971da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 3981da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE), 3991da177e4SLinus Torvalds .formats = (SNDRV_PCM_FMTBIT_S16_LE | 4001da177e4SLinus Torvalds SNDRV_PCM_FMTBIT_S32_LE), 4011da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_32000 | 4021da177e4SLinus Torvalds SNDRV_PCM_RATE_44100 | 4031da177e4SLinus Torvalds SNDRV_PCM_RATE_48000 | 4041da177e4SLinus Torvalds SNDRV_PCM_RATE_64000 | 4051da177e4SLinus Torvalds SNDRV_PCM_RATE_88200 | 4061da177e4SLinus Torvalds SNDRV_PCM_RATE_96000), 4071da177e4SLinus Torvalds .rate_min = 32000, 4081da177e4SLinus Torvalds .rate_max = 96000, 4091da177e4SLinus Torvalds .channels_min = 2, 4101da177e4SLinus Torvalds .channels_max = 2, 4111da177e4SLinus Torvalds .buffer_bytes_max = RME96_BUFFER_SIZE, 4121da177e4SLinus Torvalds .period_bytes_min = RME96_SMALL_BLOCK_SIZE, 4131da177e4SLinus Torvalds .period_bytes_max = RME96_LARGE_BLOCK_SIZE, 4141da177e4SLinus Torvalds .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, 4151da177e4SLinus Torvalds .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, 4161da177e4SLinus Torvalds .fifo_size = 0, 4171da177e4SLinus Torvalds }; 4181da177e4SLinus Torvalds 4191da177e4SLinus Torvalds /* 420*7f927fccSAlexey Dobriyan * Digital output capabilities (ADAT) 4211da177e4SLinus Torvalds */ 422a3aefd88STakashi Iwai static struct snd_pcm_hardware snd_rme96_playback_adat_info = 4231da177e4SLinus Torvalds { 4241da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP_IOMEM | 4251da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 4261da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 4271da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE), 4281da177e4SLinus Torvalds .formats = (SNDRV_PCM_FMTBIT_S16_LE | 4291da177e4SLinus Torvalds SNDRV_PCM_FMTBIT_S32_LE), 4301da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_44100 | 4311da177e4SLinus Torvalds SNDRV_PCM_RATE_48000), 4321da177e4SLinus Torvalds .rate_min = 44100, 4331da177e4SLinus Torvalds .rate_max = 48000, 4341da177e4SLinus Torvalds .channels_min = 8, 4351da177e4SLinus Torvalds .channels_max = 8, 4361da177e4SLinus Torvalds .buffer_bytes_max = RME96_BUFFER_SIZE, 4371da177e4SLinus Torvalds .period_bytes_min = RME96_SMALL_BLOCK_SIZE, 4381da177e4SLinus Torvalds .period_bytes_max = RME96_LARGE_BLOCK_SIZE, 4391da177e4SLinus Torvalds .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, 4401da177e4SLinus Torvalds .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, 4411da177e4SLinus Torvalds .fifo_size = 0, 4421da177e4SLinus Torvalds }; 4431da177e4SLinus Torvalds 4441da177e4SLinus Torvalds /* 445*7f927fccSAlexey Dobriyan * Digital input capabilities (ADAT) 4461da177e4SLinus Torvalds */ 447a3aefd88STakashi Iwai static struct snd_pcm_hardware snd_rme96_capture_adat_info = 4481da177e4SLinus Torvalds { 4491da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP_IOMEM | 4501da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 4511da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 4521da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE), 4531da177e4SLinus Torvalds .formats = (SNDRV_PCM_FMTBIT_S16_LE | 4541da177e4SLinus Torvalds SNDRV_PCM_FMTBIT_S32_LE), 4551da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_44100 | 4561da177e4SLinus Torvalds SNDRV_PCM_RATE_48000), 4571da177e4SLinus Torvalds .rate_min = 44100, 4581da177e4SLinus Torvalds .rate_max = 48000, 4591da177e4SLinus Torvalds .channels_min = 8, 4601da177e4SLinus Torvalds .channels_max = 8, 4611da177e4SLinus Torvalds .buffer_bytes_max = RME96_BUFFER_SIZE, 4621da177e4SLinus Torvalds .period_bytes_min = RME96_SMALL_BLOCK_SIZE, 4631da177e4SLinus Torvalds .period_bytes_max = RME96_LARGE_BLOCK_SIZE, 4641da177e4SLinus Torvalds .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, 4651da177e4SLinus Torvalds .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, 4661da177e4SLinus Torvalds .fifo_size = 0, 4671da177e4SLinus Torvalds }; 4681da177e4SLinus Torvalds 4691da177e4SLinus Torvalds /* 4701da177e4SLinus Torvalds * The CDATA, CCLK and CLATCH bits can be used to write to the SPI interface 4711da177e4SLinus Torvalds * of the AD1852 or AD1852 D/A converter on the board. CDATA must be set up 4721da177e4SLinus Torvalds * on the falling edge of CCLK and be stable on the rising edge. The rising 4731da177e4SLinus Torvalds * edge of CLATCH after the last data bit clocks in the whole data word. 4741da177e4SLinus Torvalds * A fast processor could probably drive the SPI interface faster than the 4751da177e4SLinus Torvalds * DAC can handle (3MHz for the 1855, unknown for the 1852). The udelay(1) 4761da177e4SLinus Torvalds * limits the data rate to 500KHz and only causes a delay of 33 microsecs. 4771da177e4SLinus Torvalds * 4781da177e4SLinus Torvalds * NOTE: increased delay from 1 to 10, since there where problems setting 4791da177e4SLinus Torvalds * the volume. 4801da177e4SLinus Torvalds */ 4811da177e4SLinus Torvalds static void 482a3aefd88STakashi Iwai snd_rme96_write_SPI(struct rme96 *rme96, u16 val) 4831da177e4SLinus Torvalds { 4841da177e4SLinus Torvalds int i; 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds for (i = 0; i < 16; i++) { 4871da177e4SLinus Torvalds if (val & 0x8000) { 4881da177e4SLinus Torvalds rme96->areg |= RME96_AR_CDATA; 4891da177e4SLinus Torvalds } else { 4901da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_CDATA; 4911da177e4SLinus Torvalds } 4921da177e4SLinus Torvalds rme96->areg &= ~(RME96_AR_CCLK | RME96_AR_CLATCH); 4931da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 4941da177e4SLinus Torvalds udelay(10); 4951da177e4SLinus Torvalds rme96->areg |= RME96_AR_CCLK; 4961da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 4971da177e4SLinus Torvalds udelay(10); 4981da177e4SLinus Torvalds val <<= 1; 4991da177e4SLinus Torvalds } 5001da177e4SLinus Torvalds rme96->areg &= ~(RME96_AR_CCLK | RME96_AR_CDATA); 5011da177e4SLinus Torvalds rme96->areg |= RME96_AR_CLATCH; 5021da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 5031da177e4SLinus Torvalds udelay(10); 5041da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_CLATCH; 5051da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 5061da177e4SLinus Torvalds } 5071da177e4SLinus Torvalds 5081da177e4SLinus Torvalds static void 509a3aefd88STakashi Iwai snd_rme96_apply_dac_volume(struct rme96 *rme96) 5101da177e4SLinus Torvalds { 5111da177e4SLinus Torvalds if (RME96_DAC_IS_1852(rme96)) { 5121da177e4SLinus Torvalds snd_rme96_write_SPI(rme96, (rme96->vol[0] << 2) | 0x0); 5131da177e4SLinus Torvalds snd_rme96_write_SPI(rme96, (rme96->vol[1] << 2) | 0x2); 5141da177e4SLinus Torvalds } else if (RME96_DAC_IS_1855(rme96)) { 5151da177e4SLinus Torvalds snd_rme96_write_SPI(rme96, (rme96->vol[0] & 0x3FF) | 0x000); 5161da177e4SLinus Torvalds snd_rme96_write_SPI(rme96, (rme96->vol[1] & 0x3FF) | 0x400); 5171da177e4SLinus Torvalds } 5181da177e4SLinus Torvalds } 5191da177e4SLinus Torvalds 5201da177e4SLinus Torvalds static void 521a3aefd88STakashi Iwai snd_rme96_reset_dac(struct rme96 *rme96) 5221da177e4SLinus Torvalds { 5231da177e4SLinus Torvalds writel(rme96->wcreg | RME96_WCR_PD, 5241da177e4SLinus Torvalds rme96->iobase + RME96_IO_CONTROL_REGISTER); 5251da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 5261da177e4SLinus Torvalds } 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds static int 529a3aefd88STakashi Iwai snd_rme96_getmontracks(struct rme96 *rme96) 5301da177e4SLinus Torvalds { 5311da177e4SLinus Torvalds return ((rme96->wcreg >> RME96_WCR_BITPOS_MONITOR_0) & 1) + 5321da177e4SLinus Torvalds (((rme96->wcreg >> RME96_WCR_BITPOS_MONITOR_1) & 1) << 1); 5331da177e4SLinus Torvalds } 5341da177e4SLinus Torvalds 5351da177e4SLinus Torvalds static int 536a3aefd88STakashi Iwai snd_rme96_setmontracks(struct rme96 *rme96, 5371da177e4SLinus Torvalds int montracks) 5381da177e4SLinus Torvalds { 5391da177e4SLinus Torvalds if (montracks & 1) { 5401da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MONITOR_0; 5411da177e4SLinus Torvalds } else { 5421da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_MONITOR_0; 5431da177e4SLinus Torvalds } 5441da177e4SLinus Torvalds if (montracks & 2) { 5451da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MONITOR_1; 5461da177e4SLinus Torvalds } else { 5471da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_MONITOR_1; 5481da177e4SLinus Torvalds } 5491da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 5501da177e4SLinus Torvalds return 0; 5511da177e4SLinus Torvalds } 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds static int 554a3aefd88STakashi Iwai snd_rme96_getattenuation(struct rme96 *rme96) 5551da177e4SLinus Torvalds { 5561da177e4SLinus Torvalds return ((rme96->wcreg >> RME96_WCR_BITPOS_GAIN_0) & 1) + 5571da177e4SLinus Torvalds (((rme96->wcreg >> RME96_WCR_BITPOS_GAIN_1) & 1) << 1); 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds 5601da177e4SLinus Torvalds static int 561a3aefd88STakashi Iwai snd_rme96_setattenuation(struct rme96 *rme96, 5621da177e4SLinus Torvalds int attenuation) 5631da177e4SLinus Torvalds { 5641da177e4SLinus Torvalds switch (attenuation) { 5651da177e4SLinus Torvalds case 0: 5661da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg & ~RME96_WCR_GAIN_0) & 5671da177e4SLinus Torvalds ~RME96_WCR_GAIN_1; 5681da177e4SLinus Torvalds break; 5691da177e4SLinus Torvalds case 1: 5701da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_GAIN_0) & 5711da177e4SLinus Torvalds ~RME96_WCR_GAIN_1; 5721da177e4SLinus Torvalds break; 5731da177e4SLinus Torvalds case 2: 5741da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg & ~RME96_WCR_GAIN_0) | 5751da177e4SLinus Torvalds RME96_WCR_GAIN_1; 5761da177e4SLinus Torvalds break; 5771da177e4SLinus Torvalds case 3: 5781da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_GAIN_0) | 5791da177e4SLinus Torvalds RME96_WCR_GAIN_1; 5801da177e4SLinus Torvalds break; 5811da177e4SLinus Torvalds default: 5821da177e4SLinus Torvalds return -EINVAL; 5831da177e4SLinus Torvalds } 5841da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 5851da177e4SLinus Torvalds return 0; 5861da177e4SLinus Torvalds } 5871da177e4SLinus Torvalds 5881da177e4SLinus Torvalds static int 589a3aefd88STakashi Iwai snd_rme96_capture_getrate(struct rme96 *rme96, 5901da177e4SLinus Torvalds int *is_adat) 5911da177e4SLinus Torvalds { 5921da177e4SLinus Torvalds int n, rate; 5931da177e4SLinus Torvalds 5941da177e4SLinus Torvalds *is_adat = 0; 5951da177e4SLinus Torvalds if (rme96->areg & RME96_AR_ANALOG) { 5961da177e4SLinus Torvalds /* Analog input, overrides S/PDIF setting */ 5971da177e4SLinus Torvalds n = ((rme96->areg >> RME96_AR_BITPOS_F0) & 1) + 5981da177e4SLinus Torvalds (((rme96->areg >> RME96_AR_BITPOS_F1) & 1) << 1); 5991da177e4SLinus Torvalds switch (n) { 6001da177e4SLinus Torvalds case 1: 6011da177e4SLinus Torvalds rate = 32000; 6021da177e4SLinus Torvalds break; 6031da177e4SLinus Torvalds case 2: 6041da177e4SLinus Torvalds rate = 44100; 6051da177e4SLinus Torvalds break; 6061da177e4SLinus Torvalds case 3: 6071da177e4SLinus Torvalds rate = 48000; 6081da177e4SLinus Torvalds break; 6091da177e4SLinus Torvalds default: 6101da177e4SLinus Torvalds return -1; 6111da177e4SLinus Torvalds } 6121da177e4SLinus Torvalds return (rme96->areg & RME96_AR_BITPOS_F2) ? rate << 1 : rate; 6131da177e4SLinus Torvalds } 6141da177e4SLinus Torvalds 6151da177e4SLinus Torvalds rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 6161da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_LOCK) { 6171da177e4SLinus Torvalds /* ADAT rate */ 6181da177e4SLinus Torvalds *is_adat = 1; 6191da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_T_OUT) { 6201da177e4SLinus Torvalds return 48000; 6211da177e4SLinus Torvalds } 6221da177e4SLinus Torvalds return 44100; 6231da177e4SLinus Torvalds } 6241da177e4SLinus Torvalds 6251da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_VERF) { 6261da177e4SLinus Torvalds return -1; 6271da177e4SLinus Torvalds } 6281da177e4SLinus Torvalds 6291da177e4SLinus Torvalds /* S/PDIF rate */ 6301da177e4SLinus Torvalds n = ((rme96->rcreg >> RME96_RCR_BITPOS_F0) & 1) + 6311da177e4SLinus Torvalds (((rme96->rcreg >> RME96_RCR_BITPOS_F1) & 1) << 1) + 6321da177e4SLinus Torvalds (((rme96->rcreg >> RME96_RCR_BITPOS_F2) & 1) << 2); 6331da177e4SLinus Torvalds 6341da177e4SLinus Torvalds switch (n) { 6351da177e4SLinus Torvalds case 0: 6361da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_T_OUT) { 6371da177e4SLinus Torvalds return 64000; 6381da177e4SLinus Torvalds } 6391da177e4SLinus Torvalds return -1; 6401da177e4SLinus Torvalds case 3: return 96000; 6411da177e4SLinus Torvalds case 4: return 88200; 6421da177e4SLinus Torvalds case 5: return 48000; 6431da177e4SLinus Torvalds case 6: return 44100; 6441da177e4SLinus Torvalds case 7: return 32000; 6451da177e4SLinus Torvalds default: 6461da177e4SLinus Torvalds break; 6471da177e4SLinus Torvalds } 6481da177e4SLinus Torvalds return -1; 6491da177e4SLinus Torvalds } 6501da177e4SLinus Torvalds 6511da177e4SLinus Torvalds static int 652a3aefd88STakashi Iwai snd_rme96_playback_getrate(struct rme96 *rme96) 6531da177e4SLinus Torvalds { 6541da177e4SLinus Torvalds int rate, dummy; 6551da177e4SLinus Torvalds 6561da177e4SLinus Torvalds if (!(rme96->wcreg & RME96_WCR_MASTER) && 6571da177e4SLinus Torvalds snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && 6581da177e4SLinus Torvalds (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) 6591da177e4SLinus Torvalds { 6601da177e4SLinus Torvalds /* slave clock */ 6611da177e4SLinus Torvalds return rate; 6621da177e4SLinus Torvalds } 6631da177e4SLinus Torvalds rate = ((rme96->wcreg >> RME96_WCR_BITPOS_FREQ_0) & 1) + 6641da177e4SLinus Torvalds (((rme96->wcreg >> RME96_WCR_BITPOS_FREQ_1) & 1) << 1); 6651da177e4SLinus Torvalds switch (rate) { 6661da177e4SLinus Torvalds case 1: 6671da177e4SLinus Torvalds rate = 32000; 6681da177e4SLinus Torvalds break; 6691da177e4SLinus Torvalds case 2: 6701da177e4SLinus Torvalds rate = 44100; 6711da177e4SLinus Torvalds break; 6721da177e4SLinus Torvalds case 3: 6731da177e4SLinus Torvalds rate = 48000; 6741da177e4SLinus Torvalds break; 6751da177e4SLinus Torvalds default: 6761da177e4SLinus Torvalds return -1; 6771da177e4SLinus Torvalds } 6781da177e4SLinus Torvalds return (rme96->wcreg & RME96_WCR_DS) ? rate << 1 : rate; 6791da177e4SLinus Torvalds } 6801da177e4SLinus Torvalds 6811da177e4SLinus Torvalds static int 682a3aefd88STakashi Iwai snd_rme96_playback_setrate(struct rme96 *rme96, 6831da177e4SLinus Torvalds int rate) 6841da177e4SLinus Torvalds { 6851da177e4SLinus Torvalds int ds; 6861da177e4SLinus Torvalds 6871da177e4SLinus Torvalds ds = rme96->wcreg & RME96_WCR_DS; 6881da177e4SLinus Torvalds switch (rate) { 6891da177e4SLinus Torvalds case 32000: 6901da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_DS; 6911da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) & 6921da177e4SLinus Torvalds ~RME96_WCR_FREQ_1; 6931da177e4SLinus Torvalds break; 6941da177e4SLinus Torvalds case 44100: 6951da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_DS; 6961da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_1) & 6971da177e4SLinus Torvalds ~RME96_WCR_FREQ_0; 6981da177e4SLinus Torvalds break; 6991da177e4SLinus Torvalds case 48000: 7001da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_DS; 7011da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) | 7021da177e4SLinus Torvalds RME96_WCR_FREQ_1; 7031da177e4SLinus Torvalds break; 7041da177e4SLinus Torvalds case 64000: 7051da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_DS; 7061da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) & 7071da177e4SLinus Torvalds ~RME96_WCR_FREQ_1; 7081da177e4SLinus Torvalds break; 7091da177e4SLinus Torvalds case 88200: 7101da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_DS; 7111da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_1) & 7121da177e4SLinus Torvalds ~RME96_WCR_FREQ_0; 7131da177e4SLinus Torvalds break; 7141da177e4SLinus Torvalds case 96000: 7151da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_DS; 7161da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) | 7171da177e4SLinus Torvalds RME96_WCR_FREQ_1; 7181da177e4SLinus Torvalds break; 7191da177e4SLinus Torvalds default: 7201da177e4SLinus Torvalds return -EINVAL; 7211da177e4SLinus Torvalds } 7221da177e4SLinus Torvalds if ((!ds && rme96->wcreg & RME96_WCR_DS) || 7231da177e4SLinus Torvalds (ds && !(rme96->wcreg & RME96_WCR_DS))) 7241da177e4SLinus Torvalds { 7251da177e4SLinus Torvalds /* change to/from double-speed: reset the DAC (if available) */ 7261da177e4SLinus Torvalds snd_rme96_reset_dac(rme96); 7271da177e4SLinus Torvalds } else { 7281da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 7291da177e4SLinus Torvalds } 7301da177e4SLinus Torvalds return 0; 7311da177e4SLinus Torvalds } 7321da177e4SLinus Torvalds 7331da177e4SLinus Torvalds static int 734a3aefd88STakashi Iwai snd_rme96_capture_analog_setrate(struct rme96 *rme96, 7351da177e4SLinus Torvalds int rate) 7361da177e4SLinus Torvalds { 7371da177e4SLinus Torvalds switch (rate) { 7381da177e4SLinus Torvalds case 32000: 7391da177e4SLinus Torvalds rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) & 7401da177e4SLinus Torvalds ~RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2; 7411da177e4SLinus Torvalds break; 7421da177e4SLinus Torvalds case 44100: 7431da177e4SLinus Torvalds rme96->areg = ((rme96->areg & ~RME96_AR_FREQPAD_0) | 7441da177e4SLinus Torvalds RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2; 7451da177e4SLinus Torvalds break; 7461da177e4SLinus Torvalds case 48000: 7471da177e4SLinus Torvalds rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) | 7481da177e4SLinus Torvalds RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2; 7491da177e4SLinus Torvalds break; 7501da177e4SLinus Torvalds case 64000: 7511da177e4SLinus Torvalds if (rme96->rev < 4) { 7521da177e4SLinus Torvalds return -EINVAL; 7531da177e4SLinus Torvalds } 7541da177e4SLinus Torvalds rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) & 7551da177e4SLinus Torvalds ~RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2; 7561da177e4SLinus Torvalds break; 7571da177e4SLinus Torvalds case 88200: 7581da177e4SLinus Torvalds if (rme96->rev < 4) { 7591da177e4SLinus Torvalds return -EINVAL; 7601da177e4SLinus Torvalds } 7611da177e4SLinus Torvalds rme96->areg = ((rme96->areg & ~RME96_AR_FREQPAD_0) | 7621da177e4SLinus Torvalds RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2; 7631da177e4SLinus Torvalds break; 7641da177e4SLinus Torvalds case 96000: 7651da177e4SLinus Torvalds rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) | 7661da177e4SLinus Torvalds RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2; 7671da177e4SLinus Torvalds break; 7681da177e4SLinus Torvalds default: 7691da177e4SLinus Torvalds return -EINVAL; 7701da177e4SLinus Torvalds } 7711da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 7721da177e4SLinus Torvalds return 0; 7731da177e4SLinus Torvalds } 7741da177e4SLinus Torvalds 7751da177e4SLinus Torvalds static int 776a3aefd88STakashi Iwai snd_rme96_setclockmode(struct rme96 *rme96, 7771da177e4SLinus Torvalds int mode) 7781da177e4SLinus Torvalds { 7791da177e4SLinus Torvalds switch (mode) { 7801da177e4SLinus Torvalds case RME96_CLOCKMODE_SLAVE: 7811da177e4SLinus Torvalds /* AutoSync */ 7821da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_MASTER; 7831da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_WSEL; 7841da177e4SLinus Torvalds break; 7851da177e4SLinus Torvalds case RME96_CLOCKMODE_MASTER: 7861da177e4SLinus Torvalds /* Internal */ 7871da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MASTER; 7881da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_WSEL; 7891da177e4SLinus Torvalds break; 7901da177e4SLinus Torvalds case RME96_CLOCKMODE_WORDCLOCK: 7911da177e4SLinus Torvalds /* Word clock is a master mode */ 7921da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MASTER; 7931da177e4SLinus Torvalds rme96->areg |= RME96_AR_WSEL; 7941da177e4SLinus Torvalds break; 7951da177e4SLinus Torvalds default: 7961da177e4SLinus Torvalds return -EINVAL; 7971da177e4SLinus Torvalds } 7981da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 7991da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 8001da177e4SLinus Torvalds return 0; 8011da177e4SLinus Torvalds } 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds static int 804a3aefd88STakashi Iwai snd_rme96_getclockmode(struct rme96 *rme96) 8051da177e4SLinus Torvalds { 8061da177e4SLinus Torvalds if (rme96->areg & RME96_AR_WSEL) { 8071da177e4SLinus Torvalds return RME96_CLOCKMODE_WORDCLOCK; 8081da177e4SLinus Torvalds } 8091da177e4SLinus Torvalds return (rme96->wcreg & RME96_WCR_MASTER) ? RME96_CLOCKMODE_MASTER : 8101da177e4SLinus Torvalds RME96_CLOCKMODE_SLAVE; 8111da177e4SLinus Torvalds } 8121da177e4SLinus Torvalds 8131da177e4SLinus Torvalds static int 814a3aefd88STakashi Iwai snd_rme96_setinputtype(struct rme96 *rme96, 8151da177e4SLinus Torvalds int type) 8161da177e4SLinus Torvalds { 8171da177e4SLinus Torvalds int n; 8181da177e4SLinus Torvalds 8191da177e4SLinus Torvalds switch (type) { 8201da177e4SLinus Torvalds case RME96_INPUT_OPTICAL: 8211da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg & ~RME96_WCR_INP_0) & 8221da177e4SLinus Torvalds ~RME96_WCR_INP_1; 8231da177e4SLinus Torvalds break; 8241da177e4SLinus Torvalds case RME96_INPUT_COAXIAL: 8251da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_INP_0) & 8261da177e4SLinus Torvalds ~RME96_WCR_INP_1; 8271da177e4SLinus Torvalds break; 8281da177e4SLinus Torvalds case RME96_INPUT_INTERNAL: 8291da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg & ~RME96_WCR_INP_0) | 8301da177e4SLinus Torvalds RME96_WCR_INP_1; 8311da177e4SLinus Torvalds break; 8321da177e4SLinus Torvalds case RME96_INPUT_XLR: 8338b7fc421SRoland Dreier if ((rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && 8348b7fc421SRoland Dreier rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PRO) || 8358b7fc421SRoland Dreier (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && 8361da177e4SLinus Torvalds rme96->rev > 4)) 8371da177e4SLinus Torvalds { 8381da177e4SLinus Torvalds /* Only Digi96/8 PRO and Digi96/8 PAD supports XLR */ 8391da177e4SLinus Torvalds return -EINVAL; 8401da177e4SLinus Torvalds } 8411da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_INP_0) | 8421da177e4SLinus Torvalds RME96_WCR_INP_1; 8431da177e4SLinus Torvalds break; 8441da177e4SLinus Torvalds case RME96_INPUT_ANALOG: 8451da177e4SLinus Torvalds if (!RME96_HAS_ANALOG_IN(rme96)) { 8461da177e4SLinus Torvalds return -EINVAL; 8471da177e4SLinus Torvalds } 8481da177e4SLinus Torvalds rme96->areg |= RME96_AR_ANALOG; 8491da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 8501da177e4SLinus Torvalds if (rme96->rev < 4) { 8511da177e4SLinus Torvalds /* 8521da177e4SLinus Torvalds * Revision less than 004 does not support 64 and 8531da177e4SLinus Torvalds * 88.2 kHz 8541da177e4SLinus Torvalds */ 8551da177e4SLinus Torvalds if (snd_rme96_capture_getrate(rme96, &n) == 88200) { 8561da177e4SLinus Torvalds snd_rme96_capture_analog_setrate(rme96, 44100); 8571da177e4SLinus Torvalds } 8581da177e4SLinus Torvalds if (snd_rme96_capture_getrate(rme96, &n) == 64000) { 8591da177e4SLinus Torvalds snd_rme96_capture_analog_setrate(rme96, 32000); 8601da177e4SLinus Torvalds } 8611da177e4SLinus Torvalds } 8621da177e4SLinus Torvalds return 0; 8631da177e4SLinus Torvalds default: 8641da177e4SLinus Torvalds return -EINVAL; 8651da177e4SLinus Torvalds } 8661da177e4SLinus Torvalds if (type != RME96_INPUT_ANALOG && RME96_HAS_ANALOG_IN(rme96)) { 8671da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_ANALOG; 8681da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 8691da177e4SLinus Torvalds } 8701da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 8711da177e4SLinus Torvalds return 0; 8721da177e4SLinus Torvalds } 8731da177e4SLinus Torvalds 8741da177e4SLinus Torvalds static int 875a3aefd88STakashi Iwai snd_rme96_getinputtype(struct rme96 *rme96) 8761da177e4SLinus Torvalds { 8771da177e4SLinus Torvalds if (rme96->areg & RME96_AR_ANALOG) { 8781da177e4SLinus Torvalds return RME96_INPUT_ANALOG; 8791da177e4SLinus Torvalds } 8801da177e4SLinus Torvalds return ((rme96->wcreg >> RME96_WCR_BITPOS_INP_0) & 1) + 8811da177e4SLinus Torvalds (((rme96->wcreg >> RME96_WCR_BITPOS_INP_1) & 1) << 1); 8821da177e4SLinus Torvalds } 8831da177e4SLinus Torvalds 8841da177e4SLinus Torvalds static void 885a3aefd88STakashi Iwai snd_rme96_setframelog(struct rme96 *rme96, 8861da177e4SLinus Torvalds int n_channels, 8871da177e4SLinus Torvalds int is_playback) 8881da177e4SLinus Torvalds { 8891da177e4SLinus Torvalds int frlog; 8901da177e4SLinus Torvalds 8911da177e4SLinus Torvalds if (n_channels == 2) { 8921da177e4SLinus Torvalds frlog = 1; 8931da177e4SLinus Torvalds } else { 8941da177e4SLinus Torvalds /* assume 8 channels */ 8951da177e4SLinus Torvalds frlog = 3; 8961da177e4SLinus Torvalds } 8971da177e4SLinus Torvalds if (is_playback) { 8981da177e4SLinus Torvalds frlog += (rme96->wcreg & RME96_WCR_MODE24) ? 2 : 1; 8991da177e4SLinus Torvalds rme96->playback_frlog = frlog; 9001da177e4SLinus Torvalds } else { 9011da177e4SLinus Torvalds frlog += (rme96->wcreg & RME96_WCR_MODE24_2) ? 2 : 1; 9021da177e4SLinus Torvalds rme96->capture_frlog = frlog; 9031da177e4SLinus Torvalds } 9041da177e4SLinus Torvalds } 9051da177e4SLinus Torvalds 9061da177e4SLinus Torvalds static int 907a3aefd88STakashi Iwai snd_rme96_playback_setformat(struct rme96 *rme96, 9081da177e4SLinus Torvalds int format) 9091da177e4SLinus Torvalds { 9101da177e4SLinus Torvalds switch (format) { 9111da177e4SLinus Torvalds case SNDRV_PCM_FORMAT_S16_LE: 9121da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_MODE24; 9131da177e4SLinus Torvalds break; 9141da177e4SLinus Torvalds case SNDRV_PCM_FORMAT_S32_LE: 9151da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MODE24; 9161da177e4SLinus Torvalds break; 9171da177e4SLinus Torvalds default: 9181da177e4SLinus Torvalds return -EINVAL; 9191da177e4SLinus Torvalds } 9201da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 9211da177e4SLinus Torvalds return 0; 9221da177e4SLinus Torvalds } 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds static int 925a3aefd88STakashi Iwai snd_rme96_capture_setformat(struct rme96 *rme96, 9261da177e4SLinus Torvalds int format) 9271da177e4SLinus Torvalds { 9281da177e4SLinus Torvalds switch (format) { 9291da177e4SLinus Torvalds case SNDRV_PCM_FORMAT_S16_LE: 9301da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_MODE24_2; 9311da177e4SLinus Torvalds break; 9321da177e4SLinus Torvalds case SNDRV_PCM_FORMAT_S32_LE: 9331da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MODE24_2; 9341da177e4SLinus Torvalds break; 9351da177e4SLinus Torvalds default: 9361da177e4SLinus Torvalds return -EINVAL; 9371da177e4SLinus Torvalds } 9381da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 9391da177e4SLinus Torvalds return 0; 9401da177e4SLinus Torvalds } 9411da177e4SLinus Torvalds 9421da177e4SLinus Torvalds static void 943a3aefd88STakashi Iwai snd_rme96_set_period_properties(struct rme96 *rme96, 9441da177e4SLinus Torvalds size_t period_bytes) 9451da177e4SLinus Torvalds { 9461da177e4SLinus Torvalds switch (period_bytes) { 9471da177e4SLinus Torvalds case RME96_LARGE_BLOCK_SIZE: 9481da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_ISEL; 9491da177e4SLinus Torvalds break; 9501da177e4SLinus Torvalds case RME96_SMALL_BLOCK_SIZE: 9511da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_ISEL; 9521da177e4SLinus Torvalds break; 9531da177e4SLinus Torvalds default: 9541da177e4SLinus Torvalds snd_BUG(); 9551da177e4SLinus Torvalds break; 9561da177e4SLinus Torvalds } 9571da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_IDIS; 9581da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 9591da177e4SLinus Torvalds } 9601da177e4SLinus Torvalds 9611da177e4SLinus Torvalds static int 962a3aefd88STakashi Iwai snd_rme96_playback_hw_params(struct snd_pcm_substream *substream, 963a3aefd88STakashi Iwai struct snd_pcm_hw_params *params) 9641da177e4SLinus Torvalds { 965a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 966a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 9671da177e4SLinus Torvalds int err, rate, dummy; 9681da177e4SLinus Torvalds 9694d23359bSClemens Ladisch runtime->dma_area = (void __force *)(rme96->iobase + 9704d23359bSClemens Ladisch RME96_IO_PLAY_BUFFER); 9711da177e4SLinus Torvalds runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER; 9721da177e4SLinus Torvalds runtime->dma_bytes = RME96_BUFFER_SIZE; 9731da177e4SLinus Torvalds 9741da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 9751da177e4SLinus Torvalds if (!(rme96->wcreg & RME96_WCR_MASTER) && 9761da177e4SLinus Torvalds snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && 9771da177e4SLinus Torvalds (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) 9781da177e4SLinus Torvalds { 9791da177e4SLinus Torvalds /* slave clock */ 9801da177e4SLinus Torvalds if ((int)params_rate(params) != rate) { 9811da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 9821da177e4SLinus Torvalds return -EIO; 9831da177e4SLinus Torvalds } 9841da177e4SLinus Torvalds } else if ((err = snd_rme96_playback_setrate(rme96, params_rate(params))) < 0) { 9851da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 9861da177e4SLinus Torvalds return err; 9871da177e4SLinus Torvalds } 9881da177e4SLinus Torvalds if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) < 0) { 9891da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 9901da177e4SLinus Torvalds return err; 9911da177e4SLinus Torvalds } 9921da177e4SLinus Torvalds snd_rme96_setframelog(rme96, params_channels(params), 1); 9931da177e4SLinus Torvalds if (rme96->capture_periodsize != 0) { 9941da177e4SLinus Torvalds if (params_period_size(params) << rme96->playback_frlog != 9951da177e4SLinus Torvalds rme96->capture_periodsize) 9961da177e4SLinus Torvalds { 9971da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 9981da177e4SLinus Torvalds return -EBUSY; 9991da177e4SLinus Torvalds } 10001da177e4SLinus Torvalds } 10011da177e4SLinus Torvalds rme96->playback_periodsize = 10021da177e4SLinus Torvalds params_period_size(params) << rme96->playback_frlog; 10031da177e4SLinus Torvalds snd_rme96_set_period_properties(rme96, rme96->playback_periodsize); 10041da177e4SLinus Torvalds /* S/PDIF setup */ 10051da177e4SLinus Torvalds if ((rme96->wcreg & RME96_WCR_ADAT) == 0) { 10061da177e4SLinus Torvalds rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); 10071da177e4SLinus Torvalds writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER); 10081da177e4SLinus Torvalds } 10091da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10101da177e4SLinus Torvalds 10111da177e4SLinus Torvalds return 0; 10121da177e4SLinus Torvalds } 10131da177e4SLinus Torvalds 10141da177e4SLinus Torvalds static int 1015a3aefd88STakashi Iwai snd_rme96_capture_hw_params(struct snd_pcm_substream *substream, 1016a3aefd88STakashi Iwai struct snd_pcm_hw_params *params) 10171da177e4SLinus Torvalds { 1018a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1019a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 10201da177e4SLinus Torvalds int err, isadat, rate; 10211da177e4SLinus Torvalds 10224d23359bSClemens Ladisch runtime->dma_area = (void __force *)(rme96->iobase + 10234d23359bSClemens Ladisch RME96_IO_REC_BUFFER); 10241da177e4SLinus Torvalds runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER; 10251da177e4SLinus Torvalds runtime->dma_bytes = RME96_BUFFER_SIZE; 10261da177e4SLinus Torvalds 10271da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 10281da177e4SLinus Torvalds if ((err = snd_rme96_capture_setformat(rme96, params_format(params))) < 0) { 10291da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10301da177e4SLinus Torvalds return err; 10311da177e4SLinus Torvalds } 10321da177e4SLinus Torvalds if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { 10331da177e4SLinus Torvalds if ((err = snd_rme96_capture_analog_setrate(rme96, 10341da177e4SLinus Torvalds params_rate(params))) < 0) 10351da177e4SLinus Torvalds { 10361da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10371da177e4SLinus Torvalds return err; 10381da177e4SLinus Torvalds } 10391da177e4SLinus Torvalds } else if ((rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) { 10401da177e4SLinus Torvalds if ((int)params_rate(params) != rate) { 10411da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10421da177e4SLinus Torvalds return -EIO; 10431da177e4SLinus Torvalds } 10441da177e4SLinus Torvalds if ((isadat && runtime->hw.channels_min == 2) || 10451da177e4SLinus Torvalds (!isadat && runtime->hw.channels_min == 8)) 10461da177e4SLinus Torvalds { 10471da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10481da177e4SLinus Torvalds return -EIO; 10491da177e4SLinus Torvalds } 10501da177e4SLinus Torvalds } 10511da177e4SLinus Torvalds snd_rme96_setframelog(rme96, params_channels(params), 0); 10521da177e4SLinus Torvalds if (rme96->playback_periodsize != 0) { 10531da177e4SLinus Torvalds if (params_period_size(params) << rme96->capture_frlog != 10541da177e4SLinus Torvalds rme96->playback_periodsize) 10551da177e4SLinus Torvalds { 10561da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10571da177e4SLinus Torvalds return -EBUSY; 10581da177e4SLinus Torvalds } 10591da177e4SLinus Torvalds } 10601da177e4SLinus Torvalds rme96->capture_periodsize = 10611da177e4SLinus Torvalds params_period_size(params) << rme96->capture_frlog; 10621da177e4SLinus Torvalds snd_rme96_set_period_properties(rme96, rme96->capture_periodsize); 10631da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10641da177e4SLinus Torvalds 10651da177e4SLinus Torvalds return 0; 10661da177e4SLinus Torvalds } 10671da177e4SLinus Torvalds 10681da177e4SLinus Torvalds static void 1069a3aefd88STakashi Iwai snd_rme96_playback_start(struct rme96 *rme96, 10701da177e4SLinus Torvalds int from_pause) 10711da177e4SLinus Torvalds { 10721da177e4SLinus Torvalds if (!from_pause) { 10731da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); 10741da177e4SLinus Torvalds } 10751da177e4SLinus Torvalds 10761da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_START; 10771da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 10781da177e4SLinus Torvalds } 10791da177e4SLinus Torvalds 10801da177e4SLinus Torvalds static void 1081a3aefd88STakashi Iwai snd_rme96_capture_start(struct rme96 *rme96, 10821da177e4SLinus Torvalds int from_pause) 10831da177e4SLinus Torvalds { 10841da177e4SLinus Torvalds if (!from_pause) { 10851da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); 10861da177e4SLinus Torvalds } 10871da177e4SLinus Torvalds 10881da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_START_2; 10891da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 10901da177e4SLinus Torvalds } 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds static void 1093a3aefd88STakashi Iwai snd_rme96_playback_stop(struct rme96 *rme96) 10941da177e4SLinus Torvalds { 10951da177e4SLinus Torvalds /* 10961da177e4SLinus Torvalds * Check if there is an unconfirmed IRQ, if so confirm it, or else 10971da177e4SLinus Torvalds * the hardware will not stop generating interrupts 10981da177e4SLinus Torvalds */ 10991da177e4SLinus Torvalds rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 11001da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_IRQ) { 11011da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ); 11021da177e4SLinus Torvalds } 11031da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_START; 11041da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 11051da177e4SLinus Torvalds } 11061da177e4SLinus Torvalds 11071da177e4SLinus Torvalds static void 1108a3aefd88STakashi Iwai snd_rme96_capture_stop(struct rme96 *rme96) 11091da177e4SLinus Torvalds { 11101da177e4SLinus Torvalds rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 11111da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_IRQ_2) { 11121da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ); 11131da177e4SLinus Torvalds } 11141da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_START_2; 11151da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 11161da177e4SLinus Torvalds } 11171da177e4SLinus Torvalds 11181da177e4SLinus Torvalds static irqreturn_t 11191da177e4SLinus Torvalds snd_rme96_interrupt(int irq, 11201da177e4SLinus Torvalds void *dev_id, 11211da177e4SLinus Torvalds struct pt_regs *regs) 11221da177e4SLinus Torvalds { 1123a3aefd88STakashi Iwai struct rme96 *rme96 = (struct rme96 *)dev_id; 11241da177e4SLinus Torvalds 11251da177e4SLinus Torvalds rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 11261da177e4SLinus Torvalds /* fastpath out, to ease interrupt sharing */ 11271da177e4SLinus Torvalds if (!((rme96->rcreg & RME96_RCR_IRQ) || 11281da177e4SLinus Torvalds (rme96->rcreg & RME96_RCR_IRQ_2))) 11291da177e4SLinus Torvalds { 11301da177e4SLinus Torvalds return IRQ_NONE; 11311da177e4SLinus Torvalds } 11321da177e4SLinus Torvalds 11331da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_IRQ) { 11341da177e4SLinus Torvalds /* playback */ 11351da177e4SLinus Torvalds snd_pcm_period_elapsed(rme96->playback_substream); 11361da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ); 11371da177e4SLinus Torvalds } 11381da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_IRQ_2) { 11391da177e4SLinus Torvalds /* capture */ 11401da177e4SLinus Torvalds snd_pcm_period_elapsed(rme96->capture_substream); 11411da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ); 11421da177e4SLinus Torvalds } 11431da177e4SLinus Torvalds return IRQ_HANDLED; 11441da177e4SLinus Torvalds } 11451da177e4SLinus Torvalds 11461da177e4SLinus Torvalds static unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE }; 11471da177e4SLinus Torvalds 1148a3aefd88STakashi Iwai static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { 11491da177e4SLinus Torvalds .count = ARRAY_SIZE(period_bytes), 11501da177e4SLinus Torvalds .list = period_bytes, 11511da177e4SLinus Torvalds .mask = 0 11521da177e4SLinus Torvalds }; 11531da177e4SLinus Torvalds 11541da177e4SLinus Torvalds static int 1155a3aefd88STakashi Iwai snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) 11561da177e4SLinus Torvalds { 11571da177e4SLinus Torvalds int rate, dummy; 1158a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1159a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 11601da177e4SLinus Torvalds 11611da177e4SLinus Torvalds snd_pcm_set_sync(substream); 11621da177e4SLinus Torvalds 11631da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 11641da177e4SLinus Torvalds if (rme96->playback_substream != NULL) { 11651da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 11661da177e4SLinus Torvalds return -EBUSY; 11671da177e4SLinus Torvalds } 11681da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_ADAT; 11691da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 11701da177e4SLinus Torvalds rme96->playback_substream = substream; 11711da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 11721da177e4SLinus Torvalds 11731da177e4SLinus Torvalds runtime->hw = snd_rme96_playback_spdif_info; 11741da177e4SLinus Torvalds if (!(rme96->wcreg & RME96_WCR_MASTER) && 11751da177e4SLinus Torvalds snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && 11761da177e4SLinus Torvalds (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) 11771da177e4SLinus Torvalds { 11781da177e4SLinus Torvalds /* slave clock */ 11791da177e4SLinus Torvalds runtime->hw.rates = snd_rme96_ratecode(rate); 11801da177e4SLinus Torvalds runtime->hw.rate_min = rate; 11811da177e4SLinus Torvalds runtime->hw.rate_max = rate; 11821da177e4SLinus Torvalds } 11831da177e4SLinus Torvalds snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); 11841da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); 11851da177e4SLinus Torvalds 11861da177e4SLinus Torvalds rme96->wcreg_spdif_stream = rme96->wcreg_spdif; 11871da177e4SLinus Torvalds rme96->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; 11881da177e4SLinus Torvalds snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE | 11891da177e4SLinus Torvalds SNDRV_CTL_EVENT_MASK_INFO, &rme96->spdif_ctl->id); 11901da177e4SLinus Torvalds return 0; 11911da177e4SLinus Torvalds } 11921da177e4SLinus Torvalds 11931da177e4SLinus Torvalds static int 1194a3aefd88STakashi Iwai snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) 11951da177e4SLinus Torvalds { 11961da177e4SLinus Torvalds int isadat, rate; 1197a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1198a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 11991da177e4SLinus Torvalds 12001da177e4SLinus Torvalds snd_pcm_set_sync(substream); 12011da177e4SLinus Torvalds 12021da177e4SLinus Torvalds runtime->hw = snd_rme96_capture_spdif_info; 12031da177e4SLinus Torvalds if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && 12041da177e4SLinus Torvalds (rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) 12051da177e4SLinus Torvalds { 12061da177e4SLinus Torvalds if (isadat) { 12071da177e4SLinus Torvalds return -EIO; 12081da177e4SLinus Torvalds } 12091da177e4SLinus Torvalds runtime->hw.rates = snd_rme96_ratecode(rate); 12101da177e4SLinus Torvalds runtime->hw.rate_min = rate; 12111da177e4SLinus Torvalds runtime->hw.rate_max = rate; 12121da177e4SLinus Torvalds } 12131da177e4SLinus Torvalds 12141da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 12151da177e4SLinus Torvalds if (rme96->capture_substream != NULL) { 12161da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 12171da177e4SLinus Torvalds return -EBUSY; 12181da177e4SLinus Torvalds } 12191da177e4SLinus Torvalds rme96->capture_substream = substream; 12201da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 12211da177e4SLinus Torvalds 12221da177e4SLinus Torvalds snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); 12231da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); 12241da177e4SLinus Torvalds 12251da177e4SLinus Torvalds return 0; 12261da177e4SLinus Torvalds } 12271da177e4SLinus Torvalds 12281da177e4SLinus Torvalds static int 1229a3aefd88STakashi Iwai snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) 12301da177e4SLinus Torvalds { 12311da177e4SLinus Torvalds int rate, dummy; 1232a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1233a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 12341da177e4SLinus Torvalds 12351da177e4SLinus Torvalds snd_pcm_set_sync(substream); 12361da177e4SLinus Torvalds 12371da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 12381da177e4SLinus Torvalds if (rme96->playback_substream != NULL) { 12391da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 12401da177e4SLinus Torvalds return -EBUSY; 12411da177e4SLinus Torvalds } 12421da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_ADAT; 12431da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 12441da177e4SLinus Torvalds rme96->playback_substream = substream; 12451da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 12461da177e4SLinus Torvalds 12471da177e4SLinus Torvalds runtime->hw = snd_rme96_playback_adat_info; 12481da177e4SLinus Torvalds if (!(rme96->wcreg & RME96_WCR_MASTER) && 12491da177e4SLinus Torvalds snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG && 12501da177e4SLinus Torvalds (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0) 12511da177e4SLinus Torvalds { 12521da177e4SLinus Torvalds /* slave clock */ 12531da177e4SLinus Torvalds runtime->hw.rates = snd_rme96_ratecode(rate); 12541da177e4SLinus Torvalds runtime->hw.rate_min = rate; 12551da177e4SLinus Torvalds runtime->hw.rate_max = rate; 12561da177e4SLinus Torvalds } 12571da177e4SLinus Torvalds snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); 12581da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); 12591da177e4SLinus Torvalds return 0; 12601da177e4SLinus Torvalds } 12611da177e4SLinus Torvalds 12621da177e4SLinus Torvalds static int 1263a3aefd88STakashi Iwai snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) 12641da177e4SLinus Torvalds { 12651da177e4SLinus Torvalds int isadat, rate; 1266a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1267a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 12681da177e4SLinus Torvalds 12691da177e4SLinus Torvalds snd_pcm_set_sync(substream); 12701da177e4SLinus Torvalds 12711da177e4SLinus Torvalds runtime->hw = snd_rme96_capture_adat_info; 12721da177e4SLinus Torvalds if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { 12731da177e4SLinus Torvalds /* makes no sense to use analog input. Note that analog 12741da177e4SLinus Torvalds expension cards AEB4/8-I are RME96_INPUT_INTERNAL */ 12751da177e4SLinus Torvalds return -EIO; 12761da177e4SLinus Torvalds } 12771da177e4SLinus Torvalds if ((rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) { 12781da177e4SLinus Torvalds if (!isadat) { 12791da177e4SLinus Torvalds return -EIO; 12801da177e4SLinus Torvalds } 12811da177e4SLinus Torvalds runtime->hw.rates = snd_rme96_ratecode(rate); 12821da177e4SLinus Torvalds runtime->hw.rate_min = rate; 12831da177e4SLinus Torvalds runtime->hw.rate_max = rate; 12841da177e4SLinus Torvalds } 12851da177e4SLinus Torvalds 12861da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 12871da177e4SLinus Torvalds if (rme96->capture_substream != NULL) { 12881da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 12891da177e4SLinus Torvalds return -EBUSY; 12901da177e4SLinus Torvalds } 12911da177e4SLinus Torvalds rme96->capture_substream = substream; 12921da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 12931da177e4SLinus Torvalds 12941da177e4SLinus Torvalds snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); 12951da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); 12961da177e4SLinus Torvalds return 0; 12971da177e4SLinus Torvalds } 12981da177e4SLinus Torvalds 12991da177e4SLinus Torvalds static int 1300a3aefd88STakashi Iwai snd_rme96_playback_close(struct snd_pcm_substream *substream) 13011da177e4SLinus Torvalds { 1302a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 13031da177e4SLinus Torvalds int spdif = 0; 13041da177e4SLinus Torvalds 13051da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 13061da177e4SLinus Torvalds if (RME96_ISPLAYING(rme96)) { 13071da177e4SLinus Torvalds snd_rme96_playback_stop(rme96); 13081da177e4SLinus Torvalds } 13091da177e4SLinus Torvalds rme96->playback_substream = NULL; 13101da177e4SLinus Torvalds rme96->playback_periodsize = 0; 13111da177e4SLinus Torvalds spdif = (rme96->wcreg & RME96_WCR_ADAT) == 0; 13121da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 13131da177e4SLinus Torvalds if (spdif) { 13141da177e4SLinus Torvalds rme96->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; 13151da177e4SLinus Torvalds snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE | 13161da177e4SLinus Torvalds SNDRV_CTL_EVENT_MASK_INFO, &rme96->spdif_ctl->id); 13171da177e4SLinus Torvalds } 13181da177e4SLinus Torvalds return 0; 13191da177e4SLinus Torvalds } 13201da177e4SLinus Torvalds 13211da177e4SLinus Torvalds static int 1322a3aefd88STakashi Iwai snd_rme96_capture_close(struct snd_pcm_substream *substream) 13231da177e4SLinus Torvalds { 1324a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 13251da177e4SLinus Torvalds 13261da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 13271da177e4SLinus Torvalds if (RME96_ISRECORDING(rme96)) { 13281da177e4SLinus Torvalds snd_rme96_capture_stop(rme96); 13291da177e4SLinus Torvalds } 13301da177e4SLinus Torvalds rme96->capture_substream = NULL; 13311da177e4SLinus Torvalds rme96->capture_periodsize = 0; 13321da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 13331da177e4SLinus Torvalds return 0; 13341da177e4SLinus Torvalds } 13351da177e4SLinus Torvalds 13361da177e4SLinus Torvalds static int 1337a3aefd88STakashi Iwai snd_rme96_playback_prepare(struct snd_pcm_substream *substream) 13381da177e4SLinus Torvalds { 1339a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 13401da177e4SLinus Torvalds 13411da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 13421da177e4SLinus Torvalds if (RME96_ISPLAYING(rme96)) { 13431da177e4SLinus Torvalds snd_rme96_playback_stop(rme96); 13441da177e4SLinus Torvalds } 13451da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); 13461da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 13471da177e4SLinus Torvalds return 0; 13481da177e4SLinus Torvalds } 13491da177e4SLinus Torvalds 13501da177e4SLinus Torvalds static int 1351a3aefd88STakashi Iwai snd_rme96_capture_prepare(struct snd_pcm_substream *substream) 13521da177e4SLinus Torvalds { 1353a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 13541da177e4SLinus Torvalds 13551da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 13561da177e4SLinus Torvalds if (RME96_ISRECORDING(rme96)) { 13571da177e4SLinus Torvalds snd_rme96_capture_stop(rme96); 13581da177e4SLinus Torvalds } 13591da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); 13601da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 13611da177e4SLinus Torvalds return 0; 13621da177e4SLinus Torvalds } 13631da177e4SLinus Torvalds 13641da177e4SLinus Torvalds static int 1365a3aefd88STakashi Iwai snd_rme96_playback_trigger(struct snd_pcm_substream *substream, 13661da177e4SLinus Torvalds int cmd) 13671da177e4SLinus Torvalds { 1368a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 13691da177e4SLinus Torvalds 13701da177e4SLinus Torvalds switch (cmd) { 13711da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_START: 13721da177e4SLinus Torvalds if (!RME96_ISPLAYING(rme96)) { 13731da177e4SLinus Torvalds if (substream != rme96->playback_substream) { 13741da177e4SLinus Torvalds return -EBUSY; 13751da177e4SLinus Torvalds } 13761da177e4SLinus Torvalds snd_rme96_playback_start(rme96, 0); 13771da177e4SLinus Torvalds } 13781da177e4SLinus Torvalds break; 13791da177e4SLinus Torvalds 13801da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_STOP: 13811da177e4SLinus Torvalds if (RME96_ISPLAYING(rme96)) { 13821da177e4SLinus Torvalds if (substream != rme96->playback_substream) { 13831da177e4SLinus Torvalds return -EBUSY; 13841da177e4SLinus Torvalds } 13851da177e4SLinus Torvalds snd_rme96_playback_stop(rme96); 13861da177e4SLinus Torvalds } 13871da177e4SLinus Torvalds break; 13881da177e4SLinus Torvalds 13891da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 13901da177e4SLinus Torvalds if (RME96_ISPLAYING(rme96)) { 13911da177e4SLinus Torvalds snd_rme96_playback_stop(rme96); 13921da177e4SLinus Torvalds } 13931da177e4SLinus Torvalds break; 13941da177e4SLinus Torvalds 13951da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 13961da177e4SLinus Torvalds if (!RME96_ISPLAYING(rme96)) { 13971da177e4SLinus Torvalds snd_rme96_playback_start(rme96, 1); 13981da177e4SLinus Torvalds } 13991da177e4SLinus Torvalds break; 14001da177e4SLinus Torvalds 14011da177e4SLinus Torvalds default: 14021da177e4SLinus Torvalds return -EINVAL; 14031da177e4SLinus Torvalds } 14041da177e4SLinus Torvalds return 0; 14051da177e4SLinus Torvalds } 14061da177e4SLinus Torvalds 14071da177e4SLinus Torvalds static int 1408a3aefd88STakashi Iwai snd_rme96_capture_trigger(struct snd_pcm_substream *substream, 14091da177e4SLinus Torvalds int cmd) 14101da177e4SLinus Torvalds { 1411a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 14121da177e4SLinus Torvalds 14131da177e4SLinus Torvalds switch (cmd) { 14141da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_START: 14151da177e4SLinus Torvalds if (!RME96_ISRECORDING(rme96)) { 14161da177e4SLinus Torvalds if (substream != rme96->capture_substream) { 14171da177e4SLinus Torvalds return -EBUSY; 14181da177e4SLinus Torvalds } 14191da177e4SLinus Torvalds snd_rme96_capture_start(rme96, 0); 14201da177e4SLinus Torvalds } 14211da177e4SLinus Torvalds break; 14221da177e4SLinus Torvalds 14231da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_STOP: 14241da177e4SLinus Torvalds if (RME96_ISRECORDING(rme96)) { 14251da177e4SLinus Torvalds if (substream != rme96->capture_substream) { 14261da177e4SLinus Torvalds return -EBUSY; 14271da177e4SLinus Torvalds } 14281da177e4SLinus Torvalds snd_rme96_capture_stop(rme96); 14291da177e4SLinus Torvalds } 14301da177e4SLinus Torvalds break; 14311da177e4SLinus Torvalds 14321da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 14331da177e4SLinus Torvalds if (RME96_ISRECORDING(rme96)) { 14341da177e4SLinus Torvalds snd_rme96_capture_stop(rme96); 14351da177e4SLinus Torvalds } 14361da177e4SLinus Torvalds break; 14371da177e4SLinus Torvalds 14381da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 14391da177e4SLinus Torvalds if (!RME96_ISRECORDING(rme96)) { 14401da177e4SLinus Torvalds snd_rme96_capture_start(rme96, 1); 14411da177e4SLinus Torvalds } 14421da177e4SLinus Torvalds break; 14431da177e4SLinus Torvalds 14441da177e4SLinus Torvalds default: 14451da177e4SLinus Torvalds return -EINVAL; 14461da177e4SLinus Torvalds } 14471da177e4SLinus Torvalds 14481da177e4SLinus Torvalds return 0; 14491da177e4SLinus Torvalds } 14501da177e4SLinus Torvalds 14511da177e4SLinus Torvalds static snd_pcm_uframes_t 1452a3aefd88STakashi Iwai snd_rme96_playback_pointer(struct snd_pcm_substream *substream) 14531da177e4SLinus Torvalds { 1454a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 14551da177e4SLinus Torvalds return snd_rme96_playback_ptr(rme96); 14561da177e4SLinus Torvalds } 14571da177e4SLinus Torvalds 14581da177e4SLinus Torvalds static snd_pcm_uframes_t 1459a3aefd88STakashi Iwai snd_rme96_capture_pointer(struct snd_pcm_substream *substream) 14601da177e4SLinus Torvalds { 1461a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 14621da177e4SLinus Torvalds return snd_rme96_capture_ptr(rme96); 14631da177e4SLinus Torvalds } 14641da177e4SLinus Torvalds 1465a3aefd88STakashi Iwai static struct snd_pcm_ops snd_rme96_playback_spdif_ops = { 14661da177e4SLinus Torvalds .open = snd_rme96_playback_spdif_open, 14671da177e4SLinus Torvalds .close = snd_rme96_playback_close, 14681da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 14691da177e4SLinus Torvalds .hw_params = snd_rme96_playback_hw_params, 14701da177e4SLinus Torvalds .prepare = snd_rme96_playback_prepare, 14711da177e4SLinus Torvalds .trigger = snd_rme96_playback_trigger, 14721da177e4SLinus Torvalds .pointer = snd_rme96_playback_pointer, 14731da177e4SLinus Torvalds .copy = snd_rme96_playback_copy, 14741da177e4SLinus Torvalds .silence = snd_rme96_playback_silence, 14751da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 14761da177e4SLinus Torvalds }; 14771da177e4SLinus Torvalds 1478a3aefd88STakashi Iwai static struct snd_pcm_ops snd_rme96_capture_spdif_ops = { 14791da177e4SLinus Torvalds .open = snd_rme96_capture_spdif_open, 14801da177e4SLinus Torvalds .close = snd_rme96_capture_close, 14811da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 14821da177e4SLinus Torvalds .hw_params = snd_rme96_capture_hw_params, 14831da177e4SLinus Torvalds .prepare = snd_rme96_capture_prepare, 14841da177e4SLinus Torvalds .trigger = snd_rme96_capture_trigger, 14851da177e4SLinus Torvalds .pointer = snd_rme96_capture_pointer, 14861da177e4SLinus Torvalds .copy = snd_rme96_capture_copy, 14871da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 14881da177e4SLinus Torvalds }; 14891da177e4SLinus Torvalds 1490a3aefd88STakashi Iwai static struct snd_pcm_ops snd_rme96_playback_adat_ops = { 14911da177e4SLinus Torvalds .open = snd_rme96_playback_adat_open, 14921da177e4SLinus Torvalds .close = snd_rme96_playback_close, 14931da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 14941da177e4SLinus Torvalds .hw_params = snd_rme96_playback_hw_params, 14951da177e4SLinus Torvalds .prepare = snd_rme96_playback_prepare, 14961da177e4SLinus Torvalds .trigger = snd_rme96_playback_trigger, 14971da177e4SLinus Torvalds .pointer = snd_rme96_playback_pointer, 14981da177e4SLinus Torvalds .copy = snd_rme96_playback_copy, 14991da177e4SLinus Torvalds .silence = snd_rme96_playback_silence, 15001da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 15011da177e4SLinus Torvalds }; 15021da177e4SLinus Torvalds 1503a3aefd88STakashi Iwai static struct snd_pcm_ops snd_rme96_capture_adat_ops = { 15041da177e4SLinus Torvalds .open = snd_rme96_capture_adat_open, 15051da177e4SLinus Torvalds .close = snd_rme96_capture_close, 15061da177e4SLinus Torvalds .ioctl = snd_pcm_lib_ioctl, 15071da177e4SLinus Torvalds .hw_params = snd_rme96_capture_hw_params, 15081da177e4SLinus Torvalds .prepare = snd_rme96_capture_prepare, 15091da177e4SLinus Torvalds .trigger = snd_rme96_capture_trigger, 15101da177e4SLinus Torvalds .pointer = snd_rme96_capture_pointer, 15111da177e4SLinus Torvalds .copy = snd_rme96_capture_copy, 15121da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 15131da177e4SLinus Torvalds }; 15141da177e4SLinus Torvalds 15151da177e4SLinus Torvalds static void 15161da177e4SLinus Torvalds snd_rme96_free(void *private_data) 15171da177e4SLinus Torvalds { 1518a3aefd88STakashi Iwai struct rme96 *rme96 = (struct rme96 *)private_data; 15191da177e4SLinus Torvalds 15201da177e4SLinus Torvalds if (rme96 == NULL) { 15211da177e4SLinus Torvalds return; 15221da177e4SLinus Torvalds } 15231da177e4SLinus Torvalds if (rme96->irq >= 0) { 15241da177e4SLinus Torvalds snd_rme96_playback_stop(rme96); 15251da177e4SLinus Torvalds snd_rme96_capture_stop(rme96); 15261da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_DAC_EN; 15271da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 15281da177e4SLinus Torvalds free_irq(rme96->irq, (void *)rme96); 15291da177e4SLinus Torvalds rme96->irq = -1; 15301da177e4SLinus Torvalds } 15311da177e4SLinus Torvalds if (rme96->iobase) { 15321da177e4SLinus Torvalds iounmap(rme96->iobase); 15331da177e4SLinus Torvalds rme96->iobase = NULL; 15341da177e4SLinus Torvalds } 15351da177e4SLinus Torvalds if (rme96->port) { 15361da177e4SLinus Torvalds pci_release_regions(rme96->pci); 15371da177e4SLinus Torvalds rme96->port = 0; 15381da177e4SLinus Torvalds } 15391da177e4SLinus Torvalds pci_disable_device(rme96->pci); 15401da177e4SLinus Torvalds } 15411da177e4SLinus Torvalds 15421da177e4SLinus Torvalds static void 1543a3aefd88STakashi Iwai snd_rme96_free_spdif_pcm(struct snd_pcm *pcm) 15441da177e4SLinus Torvalds { 1545a3aefd88STakashi Iwai struct rme96 *rme96 = (struct rme96 *) pcm->private_data; 15461da177e4SLinus Torvalds rme96->spdif_pcm = NULL; 15471da177e4SLinus Torvalds } 15481da177e4SLinus Torvalds 15491da177e4SLinus Torvalds static void 1550a3aefd88STakashi Iwai snd_rme96_free_adat_pcm(struct snd_pcm *pcm) 15511da177e4SLinus Torvalds { 1552a3aefd88STakashi Iwai struct rme96 *rme96 = (struct rme96 *) pcm->private_data; 15531da177e4SLinus Torvalds rme96->adat_pcm = NULL; 15541da177e4SLinus Torvalds } 15551da177e4SLinus Torvalds 15561da177e4SLinus Torvalds static int __devinit 1557a3aefd88STakashi Iwai snd_rme96_create(struct rme96 *rme96) 15581da177e4SLinus Torvalds { 15591da177e4SLinus Torvalds struct pci_dev *pci = rme96->pci; 15601da177e4SLinus Torvalds int err; 15611da177e4SLinus Torvalds 15621da177e4SLinus Torvalds rme96->irq = -1; 15631da177e4SLinus Torvalds spin_lock_init(&rme96->lock); 15641da177e4SLinus Torvalds 15651da177e4SLinus Torvalds if ((err = pci_enable_device(pci)) < 0) 15661da177e4SLinus Torvalds return err; 15671da177e4SLinus Torvalds 15681da177e4SLinus Torvalds if ((err = pci_request_regions(pci, "RME96")) < 0) 15691da177e4SLinus Torvalds return err; 15701da177e4SLinus Torvalds rme96->port = pci_resource_start(rme96->pci, 0); 15711da177e4SLinus Torvalds 15721da177e4SLinus Torvalds if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) { 157399b359baSTakashi Iwai snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); 15741da177e4SLinus Torvalds return -EBUSY; 15751da177e4SLinus Torvalds } 15761da177e4SLinus Torvalds rme96->irq = pci->irq; 15771da177e4SLinus Torvalds 15781da177e4SLinus Torvalds if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) { 157999b359baSTakashi Iwai snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); 15801da177e4SLinus Torvalds return -ENOMEM; 15811da177e4SLinus Torvalds } 15821da177e4SLinus Torvalds 15831da177e4SLinus Torvalds /* read the card's revision number */ 15841da177e4SLinus Torvalds pci_read_config_byte(pci, 8, &rme96->rev); 15851da177e4SLinus Torvalds 15861da177e4SLinus Torvalds /* set up ALSA pcm device for S/PDIF */ 15871da177e4SLinus Torvalds if ((err = snd_pcm_new(rme96->card, "Digi96 IEC958", 0, 15881da177e4SLinus Torvalds 1, 1, &rme96->spdif_pcm)) < 0) 15891da177e4SLinus Torvalds { 15901da177e4SLinus Torvalds return err; 15911da177e4SLinus Torvalds } 15921da177e4SLinus Torvalds rme96->spdif_pcm->private_data = rme96; 15931da177e4SLinus Torvalds rme96->spdif_pcm->private_free = snd_rme96_free_spdif_pcm; 15941da177e4SLinus Torvalds strcpy(rme96->spdif_pcm->name, "Digi96 IEC958"); 15951da177e4SLinus Torvalds snd_pcm_set_ops(rme96->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme96_playback_spdif_ops); 15961da177e4SLinus Torvalds snd_pcm_set_ops(rme96->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_spdif_ops); 15971da177e4SLinus Torvalds 15981da177e4SLinus Torvalds rme96->spdif_pcm->info_flags = 0; 15991da177e4SLinus Torvalds 16001da177e4SLinus Torvalds /* set up ALSA pcm device for ADAT */ 16018b7fc421SRoland Dreier if (pci->device == PCI_DEVICE_ID_RME_DIGI96) { 16021da177e4SLinus Torvalds /* ADAT is not available on the base model */ 16031da177e4SLinus Torvalds rme96->adat_pcm = NULL; 16041da177e4SLinus Torvalds } else { 16051da177e4SLinus Torvalds if ((err = snd_pcm_new(rme96->card, "Digi96 ADAT", 1, 16061da177e4SLinus Torvalds 1, 1, &rme96->adat_pcm)) < 0) 16071da177e4SLinus Torvalds { 16081da177e4SLinus Torvalds return err; 16091da177e4SLinus Torvalds } 16101da177e4SLinus Torvalds rme96->adat_pcm->private_data = rme96; 16111da177e4SLinus Torvalds rme96->adat_pcm->private_free = snd_rme96_free_adat_pcm; 16121da177e4SLinus Torvalds strcpy(rme96->adat_pcm->name, "Digi96 ADAT"); 16131da177e4SLinus Torvalds snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme96_playback_adat_ops); 16141da177e4SLinus Torvalds snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_adat_ops); 16151da177e4SLinus Torvalds 16161da177e4SLinus Torvalds rme96->adat_pcm->info_flags = 0; 16171da177e4SLinus Torvalds } 16181da177e4SLinus Torvalds 16191da177e4SLinus Torvalds rme96->playback_periodsize = 0; 16201da177e4SLinus Torvalds rme96->capture_periodsize = 0; 16211da177e4SLinus Torvalds 16221da177e4SLinus Torvalds /* make sure playback/capture is stopped, if by some reason active */ 16231da177e4SLinus Torvalds snd_rme96_playback_stop(rme96); 16241da177e4SLinus Torvalds snd_rme96_capture_stop(rme96); 16251da177e4SLinus Torvalds 16261da177e4SLinus Torvalds /* set default values in registers */ 16271da177e4SLinus Torvalds rme96->wcreg = 16281da177e4SLinus Torvalds RME96_WCR_FREQ_1 | /* set 44.1 kHz playback */ 16291da177e4SLinus Torvalds RME96_WCR_SEL | /* normal playback */ 16301da177e4SLinus Torvalds RME96_WCR_MASTER | /* set to master clock mode */ 16311da177e4SLinus Torvalds RME96_WCR_INP_0; /* set coaxial input */ 16321da177e4SLinus Torvalds 16331da177e4SLinus Torvalds rme96->areg = RME96_AR_FREQPAD_1; /* set 44.1 kHz analog capture */ 16341da177e4SLinus Torvalds 16351da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 16361da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 16371da177e4SLinus Torvalds 16381da177e4SLinus Torvalds /* reset the ADC */ 16391da177e4SLinus Torvalds writel(rme96->areg | RME96_AR_PD2, 16401da177e4SLinus Torvalds rme96->iobase + RME96_IO_ADDITIONAL_REG); 16411da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 16421da177e4SLinus Torvalds 16431da177e4SLinus Torvalds /* reset and enable the DAC (order is important). */ 16441da177e4SLinus Torvalds snd_rme96_reset_dac(rme96); 16451da177e4SLinus Torvalds rme96->areg |= RME96_AR_DAC_EN; 16461da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 16471da177e4SLinus Torvalds 16481da177e4SLinus Torvalds /* reset playback and record buffer pointers */ 16491da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); 16501da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); 16511da177e4SLinus Torvalds 16521da177e4SLinus Torvalds /* reset volume */ 16531da177e4SLinus Torvalds rme96->vol[0] = rme96->vol[1] = 0; 16541da177e4SLinus Torvalds if (RME96_HAS_ANALOG_OUT(rme96)) { 16551da177e4SLinus Torvalds snd_rme96_apply_dac_volume(rme96); 16561da177e4SLinus Torvalds } 16571da177e4SLinus Torvalds 16581da177e4SLinus Torvalds /* init switch interface */ 16591da177e4SLinus Torvalds if ((err = snd_rme96_create_switches(rme96->card, rme96)) < 0) { 16601da177e4SLinus Torvalds return err; 16611da177e4SLinus Torvalds } 16621da177e4SLinus Torvalds 16631da177e4SLinus Torvalds /* init proc interface */ 16641da177e4SLinus Torvalds snd_rme96_proc_init(rme96); 16651da177e4SLinus Torvalds 16661da177e4SLinus Torvalds return 0; 16671da177e4SLinus Torvalds } 16681da177e4SLinus Torvalds 16691da177e4SLinus Torvalds /* 16701da177e4SLinus Torvalds * proc interface 16711da177e4SLinus Torvalds */ 16721da177e4SLinus Torvalds 16731da177e4SLinus Torvalds static void 1674a3aefd88STakashi Iwai snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 16751da177e4SLinus Torvalds { 16761da177e4SLinus Torvalds int n; 1677a3aefd88STakashi Iwai struct rme96 *rme96 = (struct rme96 *)entry->private_data; 16781da177e4SLinus Torvalds 16791da177e4SLinus Torvalds rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 16801da177e4SLinus Torvalds 16811da177e4SLinus Torvalds snd_iprintf(buffer, rme96->card->longname); 16821da177e4SLinus Torvalds snd_iprintf(buffer, " (index #%d)\n", rme96->card->number + 1); 16831da177e4SLinus Torvalds 16841da177e4SLinus Torvalds snd_iprintf(buffer, "\nGeneral settings\n"); 16851da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_IDIS) { 16861da177e4SLinus Torvalds snd_iprintf(buffer, " period size: N/A (interrupts " 16871da177e4SLinus Torvalds "disabled)\n"); 16881da177e4SLinus Torvalds } else if (rme96->wcreg & RME96_WCR_ISEL) { 16891da177e4SLinus Torvalds snd_iprintf(buffer, " period size: 2048 bytes\n"); 16901da177e4SLinus Torvalds } else { 16911da177e4SLinus Torvalds snd_iprintf(buffer, " period size: 8192 bytes\n"); 16921da177e4SLinus Torvalds } 16931da177e4SLinus Torvalds snd_iprintf(buffer, "\nInput settings\n"); 16941da177e4SLinus Torvalds switch (snd_rme96_getinputtype(rme96)) { 16951da177e4SLinus Torvalds case RME96_INPUT_OPTICAL: 16961da177e4SLinus Torvalds snd_iprintf(buffer, " input: optical"); 16971da177e4SLinus Torvalds break; 16981da177e4SLinus Torvalds case RME96_INPUT_COAXIAL: 16991da177e4SLinus Torvalds snd_iprintf(buffer, " input: coaxial"); 17001da177e4SLinus Torvalds break; 17011da177e4SLinus Torvalds case RME96_INPUT_INTERNAL: 17021da177e4SLinus Torvalds snd_iprintf(buffer, " input: internal"); 17031da177e4SLinus Torvalds break; 17041da177e4SLinus Torvalds case RME96_INPUT_XLR: 17051da177e4SLinus Torvalds snd_iprintf(buffer, " input: XLR"); 17061da177e4SLinus Torvalds break; 17071da177e4SLinus Torvalds case RME96_INPUT_ANALOG: 17081da177e4SLinus Torvalds snd_iprintf(buffer, " input: analog"); 17091da177e4SLinus Torvalds break; 17101da177e4SLinus Torvalds } 17111da177e4SLinus Torvalds if (snd_rme96_capture_getrate(rme96, &n) < 0) { 17121da177e4SLinus Torvalds snd_iprintf(buffer, "\n sample rate: no valid signal\n"); 17131da177e4SLinus Torvalds } else { 17141da177e4SLinus Torvalds if (n) { 17151da177e4SLinus Torvalds snd_iprintf(buffer, " (8 channels)\n"); 17161da177e4SLinus Torvalds } else { 17171da177e4SLinus Torvalds snd_iprintf(buffer, " (2 channels)\n"); 17181da177e4SLinus Torvalds } 17191da177e4SLinus Torvalds snd_iprintf(buffer, " sample rate: %d Hz\n", 17201da177e4SLinus Torvalds snd_rme96_capture_getrate(rme96, &n)); 17211da177e4SLinus Torvalds } 17221da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_MODE24_2) { 17231da177e4SLinus Torvalds snd_iprintf(buffer, " sample format: 24 bit\n"); 17241da177e4SLinus Torvalds } else { 17251da177e4SLinus Torvalds snd_iprintf(buffer, " sample format: 16 bit\n"); 17261da177e4SLinus Torvalds } 17271da177e4SLinus Torvalds 17281da177e4SLinus Torvalds snd_iprintf(buffer, "\nOutput settings\n"); 17291da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_SEL) { 17301da177e4SLinus Torvalds snd_iprintf(buffer, " output signal: normal playback\n"); 17311da177e4SLinus Torvalds } else { 17321da177e4SLinus Torvalds snd_iprintf(buffer, " output signal: same as input\n"); 17331da177e4SLinus Torvalds } 17341da177e4SLinus Torvalds snd_iprintf(buffer, " sample rate: %d Hz\n", 17351da177e4SLinus Torvalds snd_rme96_playback_getrate(rme96)); 17361da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_MODE24) { 17371da177e4SLinus Torvalds snd_iprintf(buffer, " sample format: 24 bit\n"); 17381da177e4SLinus Torvalds } else { 17391da177e4SLinus Torvalds snd_iprintf(buffer, " sample format: 16 bit\n"); 17401da177e4SLinus Torvalds } 17411da177e4SLinus Torvalds if (rme96->areg & RME96_AR_WSEL) { 17421da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: word clock\n"); 17431da177e4SLinus Torvalds } else if (rme96->wcreg & RME96_WCR_MASTER) { 17441da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: internal\n"); 17451da177e4SLinus Torvalds } else if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { 17461da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: autosync (internal anyway due to analog input setting)\n"); 17471da177e4SLinus Torvalds } else if (snd_rme96_capture_getrate(rme96, &n) < 0) { 17481da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: autosync (internal anyway due to no valid signal)\n"); 17491da177e4SLinus Torvalds } else { 17501da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: autosync\n"); 17511da177e4SLinus Torvalds } 17521da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_PRO) { 17531da177e4SLinus Torvalds snd_iprintf(buffer, " format: AES/EBU (professional)\n"); 17541da177e4SLinus Torvalds } else { 17551da177e4SLinus Torvalds snd_iprintf(buffer, " format: IEC958 (consumer)\n"); 17561da177e4SLinus Torvalds } 17571da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_EMP) { 17581da177e4SLinus Torvalds snd_iprintf(buffer, " emphasis: on\n"); 17591da177e4SLinus Torvalds } else { 17601da177e4SLinus Torvalds snd_iprintf(buffer, " emphasis: off\n"); 17611da177e4SLinus Torvalds } 17621da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_DOLBY) { 17631da177e4SLinus Torvalds snd_iprintf(buffer, " non-audio (dolby): on\n"); 17641da177e4SLinus Torvalds } else { 17651da177e4SLinus Torvalds snd_iprintf(buffer, " non-audio (dolby): off\n"); 17661da177e4SLinus Torvalds } 17671da177e4SLinus Torvalds if (RME96_HAS_ANALOG_IN(rme96)) { 17681da177e4SLinus Torvalds snd_iprintf(buffer, "\nAnalog output settings\n"); 17691da177e4SLinus Torvalds switch (snd_rme96_getmontracks(rme96)) { 17701da177e4SLinus Torvalds case RME96_MONITOR_TRACKS_1_2: 17711da177e4SLinus Torvalds snd_iprintf(buffer, " monitored ADAT tracks: 1+2\n"); 17721da177e4SLinus Torvalds break; 17731da177e4SLinus Torvalds case RME96_MONITOR_TRACKS_3_4: 17741da177e4SLinus Torvalds snd_iprintf(buffer, " monitored ADAT tracks: 3+4\n"); 17751da177e4SLinus Torvalds break; 17761da177e4SLinus Torvalds case RME96_MONITOR_TRACKS_5_6: 17771da177e4SLinus Torvalds snd_iprintf(buffer, " monitored ADAT tracks: 5+6\n"); 17781da177e4SLinus Torvalds break; 17791da177e4SLinus Torvalds case RME96_MONITOR_TRACKS_7_8: 17801da177e4SLinus Torvalds snd_iprintf(buffer, " monitored ADAT tracks: 7+8\n"); 17811da177e4SLinus Torvalds break; 17821da177e4SLinus Torvalds } 17831da177e4SLinus Torvalds switch (snd_rme96_getattenuation(rme96)) { 17841da177e4SLinus Torvalds case RME96_ATTENUATION_0: 17851da177e4SLinus Torvalds snd_iprintf(buffer, " attenuation: 0 dB\n"); 17861da177e4SLinus Torvalds break; 17871da177e4SLinus Torvalds case RME96_ATTENUATION_6: 17881da177e4SLinus Torvalds snd_iprintf(buffer, " attenuation: -6 dB\n"); 17891da177e4SLinus Torvalds break; 17901da177e4SLinus Torvalds case RME96_ATTENUATION_12: 17911da177e4SLinus Torvalds snd_iprintf(buffer, " attenuation: -12 dB\n"); 17921da177e4SLinus Torvalds break; 17931da177e4SLinus Torvalds case RME96_ATTENUATION_18: 17941da177e4SLinus Torvalds snd_iprintf(buffer, " attenuation: -18 dB\n"); 17951da177e4SLinus Torvalds break; 17961da177e4SLinus Torvalds } 17971da177e4SLinus Torvalds snd_iprintf(buffer, " volume left: %u\n", rme96->vol[0]); 17981da177e4SLinus Torvalds snd_iprintf(buffer, " volume right: %u\n", rme96->vol[1]); 17991da177e4SLinus Torvalds } 18001da177e4SLinus Torvalds } 18011da177e4SLinus Torvalds 18021da177e4SLinus Torvalds static void __devinit 1803a3aefd88STakashi Iwai snd_rme96_proc_init(struct rme96 *rme96) 18041da177e4SLinus Torvalds { 1805a3aefd88STakashi Iwai struct snd_info_entry *entry; 18061da177e4SLinus Torvalds 18071da177e4SLinus Torvalds if (! snd_card_proc_new(rme96->card, "rme96", &entry)) 18081da177e4SLinus Torvalds snd_info_set_text_ops(entry, rme96, 1024, snd_rme96_proc_read); 18091da177e4SLinus Torvalds } 18101da177e4SLinus Torvalds 18111da177e4SLinus Torvalds /* 18121da177e4SLinus Torvalds * control interface 18131da177e4SLinus Torvalds */ 18141da177e4SLinus Torvalds 18151da177e4SLinus Torvalds static int 1816a3aefd88STakashi Iwai snd_rme96_info_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 18171da177e4SLinus Torvalds { 18181da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 18191da177e4SLinus Torvalds uinfo->count = 1; 18201da177e4SLinus Torvalds uinfo->value.integer.min = 0; 18211da177e4SLinus Torvalds uinfo->value.integer.max = 1; 18221da177e4SLinus Torvalds return 0; 18231da177e4SLinus Torvalds } 18241da177e4SLinus Torvalds static int 1825a3aefd88STakashi Iwai snd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 18261da177e4SLinus Torvalds { 1827a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 18281da177e4SLinus Torvalds 18291da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 18301da177e4SLinus Torvalds ucontrol->value.integer.value[0] = rme96->wcreg & RME96_WCR_SEL ? 0 : 1; 18311da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 18321da177e4SLinus Torvalds return 0; 18331da177e4SLinus Torvalds } 18341da177e4SLinus Torvalds static int 1835a3aefd88STakashi Iwai snd_rme96_put_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 18361da177e4SLinus Torvalds { 1837a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 18381da177e4SLinus Torvalds unsigned int val; 18391da177e4SLinus Torvalds int change; 18401da177e4SLinus Torvalds 18411da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] ? 0 : RME96_WCR_SEL; 18421da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 18431da177e4SLinus Torvalds val = (rme96->wcreg & ~RME96_WCR_SEL) | val; 18441da177e4SLinus Torvalds change = val != rme96->wcreg; 18451da177e4SLinus Torvalds rme96->wcreg = val; 18461da177e4SLinus Torvalds writel(val, rme96->iobase + RME96_IO_CONTROL_REGISTER); 18471da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 18481da177e4SLinus Torvalds return change; 18491da177e4SLinus Torvalds } 18501da177e4SLinus Torvalds 18511da177e4SLinus Torvalds static int 1852a3aefd88STakashi Iwai snd_rme96_info_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 18531da177e4SLinus Torvalds { 18541da177e4SLinus Torvalds static char *_texts[5] = { "Optical", "Coaxial", "Internal", "XLR", "Analog" }; 1855a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 18561da177e4SLinus Torvalds char *texts[5] = { _texts[0], _texts[1], _texts[2], _texts[3], _texts[4] }; 18571da177e4SLinus Torvalds 18581da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 18591da177e4SLinus Torvalds uinfo->count = 1; 18601da177e4SLinus Torvalds switch (rme96->pci->device) { 18618b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96: 18628b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8: 18631da177e4SLinus Torvalds uinfo->value.enumerated.items = 3; 18641da177e4SLinus Torvalds break; 18658b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PRO: 18661da177e4SLinus Torvalds uinfo->value.enumerated.items = 4; 18671da177e4SLinus Torvalds break; 18688b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: 18691da177e4SLinus Torvalds if (rme96->rev > 4) { 18701da177e4SLinus Torvalds /* PST */ 18711da177e4SLinus Torvalds uinfo->value.enumerated.items = 4; 18721da177e4SLinus Torvalds texts[3] = _texts[4]; /* Analog instead of XLR */ 18731da177e4SLinus Torvalds } else { 18741da177e4SLinus Torvalds /* PAD */ 18751da177e4SLinus Torvalds uinfo->value.enumerated.items = 5; 18761da177e4SLinus Torvalds } 18771da177e4SLinus Torvalds break; 18781da177e4SLinus Torvalds default: 18791da177e4SLinus Torvalds snd_BUG(); 18801da177e4SLinus Torvalds break; 18811da177e4SLinus Torvalds } 18821da177e4SLinus Torvalds if (uinfo->value.enumerated.item > uinfo->value.enumerated.items - 1) { 18831da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 18841da177e4SLinus Torvalds } 18851da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 18861da177e4SLinus Torvalds return 0; 18871da177e4SLinus Torvalds } 18881da177e4SLinus Torvalds static int 1889a3aefd88STakashi Iwai snd_rme96_get_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 18901da177e4SLinus Torvalds { 1891a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 18921da177e4SLinus Torvalds unsigned int items = 3; 18931da177e4SLinus Torvalds 18941da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 18951da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96); 18961da177e4SLinus Torvalds 18971da177e4SLinus Torvalds switch (rme96->pci->device) { 18988b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96: 18998b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8: 19001da177e4SLinus Torvalds items = 3; 19011da177e4SLinus Torvalds break; 19028b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PRO: 19031da177e4SLinus Torvalds items = 4; 19041da177e4SLinus Torvalds break; 19058b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: 19061da177e4SLinus Torvalds if (rme96->rev > 4) { 19071da177e4SLinus Torvalds /* for handling PST case, (INPUT_ANALOG is moved to INPUT_XLR */ 19081da177e4SLinus Torvalds if (ucontrol->value.enumerated.item[0] == RME96_INPUT_ANALOG) { 19091da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = RME96_INPUT_XLR; 19101da177e4SLinus Torvalds } 19111da177e4SLinus Torvalds items = 4; 19121da177e4SLinus Torvalds } else { 19131da177e4SLinus Torvalds items = 5; 19141da177e4SLinus Torvalds } 19151da177e4SLinus Torvalds break; 19161da177e4SLinus Torvalds default: 19171da177e4SLinus Torvalds snd_BUG(); 19181da177e4SLinus Torvalds break; 19191da177e4SLinus Torvalds } 19201da177e4SLinus Torvalds if (ucontrol->value.enumerated.item[0] >= items) { 19211da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = items - 1; 19221da177e4SLinus Torvalds } 19231da177e4SLinus Torvalds 19241da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 19251da177e4SLinus Torvalds return 0; 19261da177e4SLinus Torvalds } 19271da177e4SLinus Torvalds static int 1928a3aefd88STakashi Iwai snd_rme96_put_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 19291da177e4SLinus Torvalds { 1930a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 19311da177e4SLinus Torvalds unsigned int val; 19321da177e4SLinus Torvalds int change, items = 3; 19331da177e4SLinus Torvalds 19341da177e4SLinus Torvalds switch (rme96->pci->device) { 19358b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96: 19368b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8: 19371da177e4SLinus Torvalds items = 3; 19381da177e4SLinus Torvalds break; 19398b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PRO: 19401da177e4SLinus Torvalds items = 4; 19411da177e4SLinus Torvalds break; 19428b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: 19431da177e4SLinus Torvalds if (rme96->rev > 4) { 19441da177e4SLinus Torvalds items = 4; 19451da177e4SLinus Torvalds } else { 19461da177e4SLinus Torvalds items = 5; 19471da177e4SLinus Torvalds } 19481da177e4SLinus Torvalds break; 19491da177e4SLinus Torvalds default: 19501da177e4SLinus Torvalds snd_BUG(); 19511da177e4SLinus Torvalds break; 19521da177e4SLinus Torvalds } 19531da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % items; 19541da177e4SLinus Torvalds 19551da177e4SLinus Torvalds /* special case for PST */ 19568b7fc421SRoland Dreier if (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && rme96->rev > 4) { 19571da177e4SLinus Torvalds if (val == RME96_INPUT_XLR) { 19581da177e4SLinus Torvalds val = RME96_INPUT_ANALOG; 19591da177e4SLinus Torvalds } 19601da177e4SLinus Torvalds } 19611da177e4SLinus Torvalds 19621da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 19631da177e4SLinus Torvalds change = (int)val != snd_rme96_getinputtype(rme96); 19641da177e4SLinus Torvalds snd_rme96_setinputtype(rme96, val); 19651da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 19661da177e4SLinus Torvalds return change; 19671da177e4SLinus Torvalds } 19681da177e4SLinus Torvalds 19691da177e4SLinus Torvalds static int 1970a3aefd88STakashi Iwai snd_rme96_info_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 19711da177e4SLinus Torvalds { 19721da177e4SLinus Torvalds static char *texts[3] = { "AutoSync", "Internal", "Word" }; 19731da177e4SLinus Torvalds 19741da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 19751da177e4SLinus Torvalds uinfo->count = 1; 19761da177e4SLinus Torvalds uinfo->value.enumerated.items = 3; 19771da177e4SLinus Torvalds if (uinfo->value.enumerated.item > 2) { 19781da177e4SLinus Torvalds uinfo->value.enumerated.item = 2; 19791da177e4SLinus Torvalds } 19801da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 19811da177e4SLinus Torvalds return 0; 19821da177e4SLinus Torvalds } 19831da177e4SLinus Torvalds static int 1984a3aefd88STakashi Iwai snd_rme96_get_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 19851da177e4SLinus Torvalds { 1986a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 19871da177e4SLinus Torvalds 19881da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 19891da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = snd_rme96_getclockmode(rme96); 19901da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 19911da177e4SLinus Torvalds return 0; 19921da177e4SLinus Torvalds } 19931da177e4SLinus Torvalds static int 1994a3aefd88STakashi Iwai snd_rme96_put_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 19951da177e4SLinus Torvalds { 1996a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 19971da177e4SLinus Torvalds unsigned int val; 19981da177e4SLinus Torvalds int change; 19991da177e4SLinus Torvalds 20001da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % 3; 20011da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20021da177e4SLinus Torvalds change = (int)val != snd_rme96_getclockmode(rme96); 20031da177e4SLinus Torvalds snd_rme96_setclockmode(rme96, val); 20041da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20051da177e4SLinus Torvalds return change; 20061da177e4SLinus Torvalds } 20071da177e4SLinus Torvalds 20081da177e4SLinus Torvalds static int 2009a3aefd88STakashi Iwai snd_rme96_info_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 20101da177e4SLinus Torvalds { 20111da177e4SLinus Torvalds static char *texts[4] = { "0 dB", "-6 dB", "-12 dB", "-18 dB" }; 20121da177e4SLinus Torvalds 20131da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 20141da177e4SLinus Torvalds uinfo->count = 1; 20151da177e4SLinus Torvalds uinfo->value.enumerated.items = 4; 20161da177e4SLinus Torvalds if (uinfo->value.enumerated.item > 3) { 20171da177e4SLinus Torvalds uinfo->value.enumerated.item = 3; 20181da177e4SLinus Torvalds } 20191da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 20201da177e4SLinus Torvalds return 0; 20211da177e4SLinus Torvalds } 20221da177e4SLinus Torvalds static int 2023a3aefd88STakashi Iwai snd_rme96_get_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 20241da177e4SLinus Torvalds { 2025a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 20261da177e4SLinus Torvalds 20271da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20281da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = snd_rme96_getattenuation(rme96); 20291da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20301da177e4SLinus Torvalds return 0; 20311da177e4SLinus Torvalds } 20321da177e4SLinus Torvalds static int 2033a3aefd88STakashi Iwai snd_rme96_put_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 20341da177e4SLinus Torvalds { 2035a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 20361da177e4SLinus Torvalds unsigned int val; 20371da177e4SLinus Torvalds int change; 20381da177e4SLinus Torvalds 20391da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % 4; 20401da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20411da177e4SLinus Torvalds 20421da177e4SLinus Torvalds change = (int)val != snd_rme96_getattenuation(rme96); 20431da177e4SLinus Torvalds snd_rme96_setattenuation(rme96, val); 20441da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20451da177e4SLinus Torvalds return change; 20461da177e4SLinus Torvalds } 20471da177e4SLinus Torvalds 20481da177e4SLinus Torvalds static int 2049a3aefd88STakashi Iwai snd_rme96_info_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 20501da177e4SLinus Torvalds { 20511da177e4SLinus Torvalds static char *texts[4] = { "1+2", "3+4", "5+6", "7+8" }; 20521da177e4SLinus Torvalds 20531da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 20541da177e4SLinus Torvalds uinfo->count = 1; 20551da177e4SLinus Torvalds uinfo->value.enumerated.items = 4; 20561da177e4SLinus Torvalds if (uinfo->value.enumerated.item > 3) { 20571da177e4SLinus Torvalds uinfo->value.enumerated.item = 3; 20581da177e4SLinus Torvalds } 20591da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 20601da177e4SLinus Torvalds return 0; 20611da177e4SLinus Torvalds } 20621da177e4SLinus Torvalds static int 2063a3aefd88STakashi Iwai snd_rme96_get_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 20641da177e4SLinus Torvalds { 2065a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 20661da177e4SLinus Torvalds 20671da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20681da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = snd_rme96_getmontracks(rme96); 20691da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20701da177e4SLinus Torvalds return 0; 20711da177e4SLinus Torvalds } 20721da177e4SLinus Torvalds static int 2073a3aefd88STakashi Iwai snd_rme96_put_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 20741da177e4SLinus Torvalds { 2075a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 20761da177e4SLinus Torvalds unsigned int val; 20771da177e4SLinus Torvalds int change; 20781da177e4SLinus Torvalds 20791da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % 4; 20801da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20811da177e4SLinus Torvalds change = (int)val != snd_rme96_getmontracks(rme96); 20821da177e4SLinus Torvalds snd_rme96_setmontracks(rme96, val); 20831da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20841da177e4SLinus Torvalds return change; 20851da177e4SLinus Torvalds } 20861da177e4SLinus Torvalds 2087a3aefd88STakashi Iwai static u32 snd_rme96_convert_from_aes(struct snd_aes_iec958 *aes) 20881da177e4SLinus Torvalds { 20891da177e4SLinus Torvalds u32 val = 0; 20901da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME96_WCR_PRO : 0; 20911da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? RME96_WCR_DOLBY : 0; 20921da177e4SLinus Torvalds if (val & RME96_WCR_PRO) 20931da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? RME96_WCR_EMP : 0; 20941da177e4SLinus Torvalds else 20951da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? RME96_WCR_EMP : 0; 20961da177e4SLinus Torvalds return val; 20971da177e4SLinus Torvalds } 20981da177e4SLinus Torvalds 2099a3aefd88STakashi Iwai static void snd_rme96_convert_to_aes(struct snd_aes_iec958 *aes, u32 val) 21001da177e4SLinus Torvalds { 21011da177e4SLinus Torvalds aes->status[0] = ((val & RME96_WCR_PRO) ? IEC958_AES0_PROFESSIONAL : 0) | 21021da177e4SLinus Torvalds ((val & RME96_WCR_DOLBY) ? IEC958_AES0_NONAUDIO : 0); 21031da177e4SLinus Torvalds if (val & RME96_WCR_PRO) 21041da177e4SLinus Torvalds aes->status[0] |= (val & RME96_WCR_EMP) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; 21051da177e4SLinus Torvalds else 21061da177e4SLinus Torvalds aes->status[0] |= (val & RME96_WCR_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0; 21071da177e4SLinus Torvalds } 21081da177e4SLinus Torvalds 2109a3aefd88STakashi Iwai static int snd_rme96_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 21101da177e4SLinus Torvalds { 21111da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 21121da177e4SLinus Torvalds uinfo->count = 1; 21131da177e4SLinus Torvalds return 0; 21141da177e4SLinus Torvalds } 21151da177e4SLinus Torvalds 2116a3aefd88STakashi Iwai static int snd_rme96_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 21171da177e4SLinus Torvalds { 2118a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21191da177e4SLinus Torvalds 21201da177e4SLinus Torvalds snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif); 21211da177e4SLinus Torvalds return 0; 21221da177e4SLinus Torvalds } 21231da177e4SLinus Torvalds 2124a3aefd88STakashi Iwai static int snd_rme96_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 21251da177e4SLinus Torvalds { 2126a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21271da177e4SLinus Torvalds int change; 21281da177e4SLinus Torvalds u32 val; 21291da177e4SLinus Torvalds 21301da177e4SLinus Torvalds val = snd_rme96_convert_from_aes(&ucontrol->value.iec958); 21311da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 21321da177e4SLinus Torvalds change = val != rme96->wcreg_spdif; 21331da177e4SLinus Torvalds rme96->wcreg_spdif = val; 21341da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 21351da177e4SLinus Torvalds return change; 21361da177e4SLinus Torvalds } 21371da177e4SLinus Torvalds 2138a3aefd88STakashi Iwai static int snd_rme96_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 21391da177e4SLinus Torvalds { 21401da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 21411da177e4SLinus Torvalds uinfo->count = 1; 21421da177e4SLinus Torvalds return 0; 21431da177e4SLinus Torvalds } 21441da177e4SLinus Torvalds 2145a3aefd88STakashi Iwai static int snd_rme96_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 21461da177e4SLinus Torvalds { 2147a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21481da177e4SLinus Torvalds 21491da177e4SLinus Torvalds snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif_stream); 21501da177e4SLinus Torvalds return 0; 21511da177e4SLinus Torvalds } 21521da177e4SLinus Torvalds 2153a3aefd88STakashi Iwai static int snd_rme96_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 21541da177e4SLinus Torvalds { 2155a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21561da177e4SLinus Torvalds int change; 21571da177e4SLinus Torvalds u32 val; 21581da177e4SLinus Torvalds 21591da177e4SLinus Torvalds val = snd_rme96_convert_from_aes(&ucontrol->value.iec958); 21601da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 21611da177e4SLinus Torvalds change = val != rme96->wcreg_spdif_stream; 21621da177e4SLinus Torvalds rme96->wcreg_spdif_stream = val; 21631da177e4SLinus Torvalds rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); 21641da177e4SLinus Torvalds rme96->wcreg |= val; 21651da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 21661da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 21671da177e4SLinus Torvalds return change; 21681da177e4SLinus Torvalds } 21691da177e4SLinus Torvalds 2170a3aefd88STakashi Iwai static int snd_rme96_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 21711da177e4SLinus Torvalds { 21721da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 21731da177e4SLinus Torvalds uinfo->count = 1; 21741da177e4SLinus Torvalds return 0; 21751da177e4SLinus Torvalds } 21761da177e4SLinus Torvalds 2177a3aefd88STakashi Iwai static int snd_rme96_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 21781da177e4SLinus Torvalds { 21791da177e4SLinus Torvalds ucontrol->value.iec958.status[0] = kcontrol->private_value; 21801da177e4SLinus Torvalds return 0; 21811da177e4SLinus Torvalds } 21821da177e4SLinus Torvalds 21831da177e4SLinus Torvalds static int 2184a3aefd88STakashi Iwai snd_rme96_dac_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 21851da177e4SLinus Torvalds { 2186a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21871da177e4SLinus Torvalds 21881da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 21891da177e4SLinus Torvalds uinfo->count = 2; 21901da177e4SLinus Torvalds uinfo->value.integer.min = 0; 21911da177e4SLinus Torvalds uinfo->value.integer.max = RME96_185X_MAX_OUT(rme96); 21921da177e4SLinus Torvalds return 0; 21931da177e4SLinus Torvalds } 21941da177e4SLinus Torvalds 21951da177e4SLinus Torvalds static int 2196a3aefd88STakashi Iwai snd_rme96_dac_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u) 21971da177e4SLinus Torvalds { 2198a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21991da177e4SLinus Torvalds 22001da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 22011da177e4SLinus Torvalds u->value.integer.value[0] = rme96->vol[0]; 22021da177e4SLinus Torvalds u->value.integer.value[1] = rme96->vol[1]; 22031da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 22041da177e4SLinus Torvalds 22051da177e4SLinus Torvalds return 0; 22061da177e4SLinus Torvalds } 22071da177e4SLinus Torvalds 22081da177e4SLinus Torvalds static int 2209a3aefd88STakashi Iwai snd_rme96_dac_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u) 22101da177e4SLinus Torvalds { 2211a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 22121da177e4SLinus Torvalds int change = 0; 22131da177e4SLinus Torvalds 22141da177e4SLinus Torvalds if (!RME96_HAS_ANALOG_OUT(rme96)) { 22151da177e4SLinus Torvalds return -EINVAL; 22161da177e4SLinus Torvalds } 22171da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 22181da177e4SLinus Torvalds if (u->value.integer.value[0] != rme96->vol[0]) { 22191da177e4SLinus Torvalds rme96->vol[0] = u->value.integer.value[0]; 22201da177e4SLinus Torvalds change = 1; 22211da177e4SLinus Torvalds } 22221da177e4SLinus Torvalds if (u->value.integer.value[1] != rme96->vol[1]) { 22231da177e4SLinus Torvalds rme96->vol[1] = u->value.integer.value[1]; 22241da177e4SLinus Torvalds change = 1; 22251da177e4SLinus Torvalds } 22261da177e4SLinus Torvalds if (change) { 22271da177e4SLinus Torvalds snd_rme96_apply_dac_volume(rme96); 22281da177e4SLinus Torvalds } 22291da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 22301da177e4SLinus Torvalds 22311da177e4SLinus Torvalds return change; 22321da177e4SLinus Torvalds } 22331da177e4SLinus Torvalds 2234a3aefd88STakashi Iwai static struct snd_kcontrol_new snd_rme96_controls[] = { 22351da177e4SLinus Torvalds { 22361da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 22371da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 22381da177e4SLinus Torvalds .info = snd_rme96_control_spdif_info, 22391da177e4SLinus Torvalds .get = snd_rme96_control_spdif_get, 22401da177e4SLinus Torvalds .put = snd_rme96_control_spdif_put 22411da177e4SLinus Torvalds }, 22421da177e4SLinus Torvalds { 22431da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 22441da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 22451da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), 22461da177e4SLinus Torvalds .info = snd_rme96_control_spdif_stream_info, 22471da177e4SLinus Torvalds .get = snd_rme96_control_spdif_stream_get, 22481da177e4SLinus Torvalds .put = snd_rme96_control_spdif_stream_put 22491da177e4SLinus Torvalds }, 22501da177e4SLinus Torvalds { 22511da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, 225267ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 22531da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), 22541da177e4SLinus Torvalds .info = snd_rme96_control_spdif_mask_info, 22551da177e4SLinus Torvalds .get = snd_rme96_control_spdif_mask_get, 22561da177e4SLinus Torvalds .private_value = IEC958_AES0_NONAUDIO | 22571da177e4SLinus Torvalds IEC958_AES0_PROFESSIONAL | 22581da177e4SLinus Torvalds IEC958_AES0_CON_EMPHASIS 22591da177e4SLinus Torvalds }, 22601da177e4SLinus Torvalds { 22611da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, 226267ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 22631da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), 22641da177e4SLinus Torvalds .info = snd_rme96_control_spdif_mask_info, 22651da177e4SLinus Torvalds .get = snd_rme96_control_spdif_mask_get, 22661da177e4SLinus Torvalds .private_value = IEC958_AES0_NONAUDIO | 22671da177e4SLinus Torvalds IEC958_AES0_PROFESSIONAL | 22681da177e4SLinus Torvalds IEC958_AES0_PRO_EMPHASIS 22691da177e4SLinus Torvalds }, 22701da177e4SLinus Torvalds { 22711da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 22721da177e4SLinus Torvalds .name = "Input Connector", 22731da177e4SLinus Torvalds .info = snd_rme96_info_inputtype_control, 22741da177e4SLinus Torvalds .get = snd_rme96_get_inputtype_control, 22751da177e4SLinus Torvalds .put = snd_rme96_put_inputtype_control 22761da177e4SLinus Torvalds }, 22771da177e4SLinus Torvalds { 22781da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 22791da177e4SLinus Torvalds .name = "Loopback Input", 22801da177e4SLinus Torvalds .info = snd_rme96_info_loopback_control, 22811da177e4SLinus Torvalds .get = snd_rme96_get_loopback_control, 22821da177e4SLinus Torvalds .put = snd_rme96_put_loopback_control 22831da177e4SLinus Torvalds }, 22841da177e4SLinus Torvalds { 22851da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 22861da177e4SLinus Torvalds .name = "Sample Clock Source", 22871da177e4SLinus Torvalds .info = snd_rme96_info_clockmode_control, 22881da177e4SLinus Torvalds .get = snd_rme96_get_clockmode_control, 22891da177e4SLinus Torvalds .put = snd_rme96_put_clockmode_control 22901da177e4SLinus Torvalds }, 22911da177e4SLinus Torvalds { 22921da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 22931da177e4SLinus Torvalds .name = "Monitor Tracks", 22941da177e4SLinus Torvalds .info = snd_rme96_info_montracks_control, 22951da177e4SLinus Torvalds .get = snd_rme96_get_montracks_control, 22961da177e4SLinus Torvalds .put = snd_rme96_put_montracks_control 22971da177e4SLinus Torvalds }, 22981da177e4SLinus Torvalds { 22991da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 23001da177e4SLinus Torvalds .name = "Attenuation", 23011da177e4SLinus Torvalds .info = snd_rme96_info_attenuation_control, 23021da177e4SLinus Torvalds .get = snd_rme96_get_attenuation_control, 23031da177e4SLinus Torvalds .put = snd_rme96_put_attenuation_control 23041da177e4SLinus Torvalds }, 23051da177e4SLinus Torvalds { 23061da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 23071da177e4SLinus Torvalds .name = "DAC Playback Volume", 23081da177e4SLinus Torvalds .info = snd_rme96_dac_volume_info, 23091da177e4SLinus Torvalds .get = snd_rme96_dac_volume_get, 23101da177e4SLinus Torvalds .put = snd_rme96_dac_volume_put 23111da177e4SLinus Torvalds } 23121da177e4SLinus Torvalds }; 23131da177e4SLinus Torvalds 23141da177e4SLinus Torvalds static int 2315a3aefd88STakashi Iwai snd_rme96_create_switches(struct snd_card *card, 2316a3aefd88STakashi Iwai struct rme96 *rme96) 23171da177e4SLinus Torvalds { 23181da177e4SLinus Torvalds int idx, err; 2319a3aefd88STakashi Iwai struct snd_kcontrol *kctl; 23201da177e4SLinus Torvalds 23211da177e4SLinus Torvalds for (idx = 0; idx < 7; idx++) { 23221da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme96_controls[idx], rme96))) < 0) 23231da177e4SLinus Torvalds return err; 23241da177e4SLinus Torvalds if (idx == 1) /* IEC958 (S/PDIF) Stream */ 23251da177e4SLinus Torvalds rme96->spdif_ctl = kctl; 23261da177e4SLinus Torvalds } 23271da177e4SLinus Torvalds 23281da177e4SLinus Torvalds if (RME96_HAS_ANALOG_OUT(rme96)) { 23291da177e4SLinus Torvalds for (idx = 7; idx < 10; idx++) 23301da177e4SLinus Torvalds if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_rme96_controls[idx], rme96))) < 0) 23311da177e4SLinus Torvalds return err; 23321da177e4SLinus Torvalds } 23331da177e4SLinus Torvalds 23341da177e4SLinus Torvalds return 0; 23351da177e4SLinus Torvalds } 23361da177e4SLinus Torvalds 23371da177e4SLinus Torvalds /* 23381da177e4SLinus Torvalds * Card initialisation 23391da177e4SLinus Torvalds */ 23401da177e4SLinus Torvalds 2341a3aefd88STakashi Iwai static void snd_rme96_card_free(struct snd_card *card) 23421da177e4SLinus Torvalds { 23431da177e4SLinus Torvalds snd_rme96_free(card->private_data); 23441da177e4SLinus Torvalds } 23451da177e4SLinus Torvalds 23461da177e4SLinus Torvalds static int __devinit 23471da177e4SLinus Torvalds snd_rme96_probe(struct pci_dev *pci, 23481da177e4SLinus Torvalds const struct pci_device_id *pci_id) 23491da177e4SLinus Torvalds { 23501da177e4SLinus Torvalds static int dev; 2351a3aefd88STakashi Iwai struct rme96 *rme96; 2352a3aefd88STakashi Iwai struct snd_card *card; 23531da177e4SLinus Torvalds int err; 23541da177e4SLinus Torvalds u8 val; 23551da177e4SLinus Torvalds 23561da177e4SLinus Torvalds if (dev >= SNDRV_CARDS) { 23571da177e4SLinus Torvalds return -ENODEV; 23581da177e4SLinus Torvalds } 23591da177e4SLinus Torvalds if (!enable[dev]) { 23601da177e4SLinus Torvalds dev++; 23611da177e4SLinus Torvalds return -ENOENT; 23621da177e4SLinus Torvalds } 23631da177e4SLinus Torvalds if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE, 2364a3aefd88STakashi Iwai sizeof(struct rme96))) == NULL) 23651da177e4SLinus Torvalds return -ENOMEM; 23661da177e4SLinus Torvalds card->private_free = snd_rme96_card_free; 2367a3aefd88STakashi Iwai rme96 = (struct rme96 *)card->private_data; 23681da177e4SLinus Torvalds rme96->card = card; 23691da177e4SLinus Torvalds rme96->pci = pci; 23701da177e4SLinus Torvalds snd_card_set_dev(card, &pci->dev); 23711da177e4SLinus Torvalds if ((err = snd_rme96_create(rme96)) < 0) { 23721da177e4SLinus Torvalds snd_card_free(card); 23731da177e4SLinus Torvalds return err; 23741da177e4SLinus Torvalds } 23751da177e4SLinus Torvalds 23761da177e4SLinus Torvalds strcpy(card->driver, "Digi96"); 23771da177e4SLinus Torvalds switch (rme96->pci->device) { 23788b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96: 23791da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi96"); 23801da177e4SLinus Torvalds break; 23818b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8: 23821da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi96/8"); 23831da177e4SLinus Torvalds break; 23848b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PRO: 23851da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi96/8 PRO"); 23861da177e4SLinus Torvalds break; 23878b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: 23881da177e4SLinus Torvalds pci_read_config_byte(rme96->pci, 8, &val); 23891da177e4SLinus Torvalds if (val < 5) { 23901da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi96/8 PAD"); 23911da177e4SLinus Torvalds } else { 23921da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi96/8 PST"); 23931da177e4SLinus Torvalds } 23941da177e4SLinus Torvalds break; 23951da177e4SLinus Torvalds } 23961da177e4SLinus Torvalds sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname, 23971da177e4SLinus Torvalds rme96->port, rme96->irq); 23981da177e4SLinus Torvalds 23991da177e4SLinus Torvalds if ((err = snd_card_register(card)) < 0) { 24001da177e4SLinus Torvalds snd_card_free(card); 24011da177e4SLinus Torvalds return err; 24021da177e4SLinus Torvalds } 24031da177e4SLinus Torvalds pci_set_drvdata(pci, card); 24041da177e4SLinus Torvalds dev++; 24051da177e4SLinus Torvalds return 0; 24061da177e4SLinus Torvalds } 24071da177e4SLinus Torvalds 24081da177e4SLinus Torvalds static void __devexit snd_rme96_remove(struct pci_dev *pci) 24091da177e4SLinus Torvalds { 24101da177e4SLinus Torvalds snd_card_free(pci_get_drvdata(pci)); 24111da177e4SLinus Torvalds pci_set_drvdata(pci, NULL); 24121da177e4SLinus Torvalds } 24131da177e4SLinus Torvalds 24141da177e4SLinus Torvalds static struct pci_driver driver = { 24151da177e4SLinus Torvalds .name = "RME Digi96", 24161da177e4SLinus Torvalds .id_table = snd_rme96_ids, 24171da177e4SLinus Torvalds .probe = snd_rme96_probe, 24181da177e4SLinus Torvalds .remove = __devexit_p(snd_rme96_remove), 24191da177e4SLinus Torvalds }; 24201da177e4SLinus Torvalds 24211da177e4SLinus Torvalds static int __init alsa_card_rme96_init(void) 24221da177e4SLinus Torvalds { 242301d25d46STakashi Iwai return pci_register_driver(&driver); 24241da177e4SLinus Torvalds } 24251da177e4SLinus Torvalds 24261da177e4SLinus Torvalds static void __exit alsa_card_rme96_exit(void) 24271da177e4SLinus Torvalds { 24281da177e4SLinus Torvalds pci_unregister_driver(&driver); 24291da177e4SLinus Torvalds } 24301da177e4SLinus Torvalds 24311da177e4SLinus Torvalds module_init(alsa_card_rme96_init) 24321da177e4SLinus Torvalds module_exit(alsa_card_rme96_exit) 2433