11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * ALSA driver for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST audio 41da177e4SLinus Torvalds * interfaces 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Copyright (c) 2000, 2001 Anders Torger <torger@ludd.luth.se> 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Thanks to Henk Hesselink <henk@anda.nl> for the analog volume control 91da177e4SLinus Torvalds * code. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds #include <linux/delay.h> 131da177e4SLinus Torvalds #include <linux/init.h> 141da177e4SLinus Torvalds #include <linux/interrupt.h> 151da177e4SLinus Torvalds #include <linux/pci.h> 1665a77217SPaul Gortmaker #include <linux/module.h> 17a8cc2099SKnut Petersen #include <linux/vmalloc.h> 186cbbfe1cSTakashi Iwai #include <linux/io.h> 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds #include <sound/core.h> 211da177e4SLinus Torvalds #include <sound/info.h> 221da177e4SLinus Torvalds #include <sound/control.h> 231da177e4SLinus Torvalds #include <sound/pcm.h> 241da177e4SLinus Torvalds #include <sound/pcm_params.h> 251da177e4SLinus Torvalds #include <sound/asoundef.h> 261da177e4SLinus Torvalds #include <sound/initval.h> 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds /* note, two last pcis should be equal, it is not a bug */ 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds MODULE_AUTHOR("Anders Torger <torger@ludd.luth.se>"); 311da177e4SLinus Torvalds MODULE_DESCRIPTION("RME Digi96, Digi96/8, Digi96/8 PRO, Digi96/8 PST, " 321da177e4SLinus Torvalds "Digi96/8 PAD"); 331da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 361da177e4SLinus Torvalds static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 37a67ff6a5SRusty Russell static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds module_param_array(index, int, NULL, 0444); 401da177e4SLinus Torvalds MODULE_PARM_DESC(index, "Index value for RME Digi96 soundcard."); 411da177e4SLinus Torvalds module_param_array(id, charp, NULL, 0444); 421da177e4SLinus Torvalds MODULE_PARM_DESC(id, "ID string for RME Digi96 soundcard."); 431da177e4SLinus Torvalds module_param_array(enable, bool, NULL, 0444); 441da177e4SLinus Torvalds MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard."); 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds /* 471da177e4SLinus Torvalds * Defines for RME Digi96 series, from internal RME reference documents 481da177e4SLinus Torvalds * dated 12.01.00 491da177e4SLinus Torvalds */ 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds #define RME96_SPDIF_NCHANNELS 2 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds /* Playback and capture buffer size */ 541da177e4SLinus Torvalds #define RME96_BUFFER_SIZE 0x10000 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds /* IO area size */ 571da177e4SLinus Torvalds #define RME96_IO_SIZE 0x60000 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds /* IO area offsets */ 601da177e4SLinus Torvalds #define RME96_IO_PLAY_BUFFER 0x0 611da177e4SLinus Torvalds #define RME96_IO_REC_BUFFER 0x10000 621da177e4SLinus Torvalds #define RME96_IO_CONTROL_REGISTER 0x20000 631da177e4SLinus Torvalds #define RME96_IO_ADDITIONAL_REG 0x20004 641da177e4SLinus Torvalds #define RME96_IO_CONFIRM_PLAY_IRQ 0x20008 651da177e4SLinus Torvalds #define RME96_IO_CONFIRM_REC_IRQ 0x2000C 661da177e4SLinus Torvalds #define RME96_IO_SET_PLAY_POS 0x40000 671da177e4SLinus Torvalds #define RME96_IO_RESET_PLAY_POS 0x4FFFC 681da177e4SLinus Torvalds #define RME96_IO_SET_REC_POS 0x50000 691da177e4SLinus Torvalds #define RME96_IO_RESET_REC_POS 0x5FFFC 701da177e4SLinus Torvalds #define RME96_IO_GET_PLAY_POS 0x20000 711da177e4SLinus Torvalds #define RME96_IO_GET_REC_POS 0x30000 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds /* Write control register bits */ 741da177e4SLinus Torvalds #define RME96_WCR_START (1 << 0) 751da177e4SLinus Torvalds #define RME96_WCR_START_2 (1 << 1) 761da177e4SLinus Torvalds #define RME96_WCR_GAIN_0 (1 << 2) 771da177e4SLinus Torvalds #define RME96_WCR_GAIN_1 (1 << 3) 781da177e4SLinus Torvalds #define RME96_WCR_MODE24 (1 << 4) 791da177e4SLinus Torvalds #define RME96_WCR_MODE24_2 (1 << 5) 801da177e4SLinus Torvalds #define RME96_WCR_BM (1 << 6) 811da177e4SLinus Torvalds #define RME96_WCR_BM_2 (1 << 7) 821da177e4SLinus Torvalds #define RME96_WCR_ADAT (1 << 8) 831da177e4SLinus Torvalds #define RME96_WCR_FREQ_0 (1 << 9) 841da177e4SLinus Torvalds #define RME96_WCR_FREQ_1 (1 << 10) 851da177e4SLinus Torvalds #define RME96_WCR_DS (1 << 11) 861da177e4SLinus Torvalds #define RME96_WCR_PRO (1 << 12) 871da177e4SLinus Torvalds #define RME96_WCR_EMP (1 << 13) 881da177e4SLinus Torvalds #define RME96_WCR_SEL (1 << 14) 891da177e4SLinus Torvalds #define RME96_WCR_MASTER (1 << 15) 901da177e4SLinus Torvalds #define RME96_WCR_PD (1 << 16) 911da177e4SLinus Torvalds #define RME96_WCR_INP_0 (1 << 17) 921da177e4SLinus Torvalds #define RME96_WCR_INP_1 (1 << 18) 931da177e4SLinus Torvalds #define RME96_WCR_THRU_0 (1 << 19) 941da177e4SLinus Torvalds #define RME96_WCR_THRU_1 (1 << 20) 951da177e4SLinus Torvalds #define RME96_WCR_THRU_2 (1 << 21) 961da177e4SLinus Torvalds #define RME96_WCR_THRU_3 (1 << 22) 971da177e4SLinus Torvalds #define RME96_WCR_THRU_4 (1 << 23) 981da177e4SLinus Torvalds #define RME96_WCR_THRU_5 (1 << 24) 991da177e4SLinus Torvalds #define RME96_WCR_THRU_6 (1 << 25) 1001da177e4SLinus Torvalds #define RME96_WCR_THRU_7 (1 << 26) 1011da177e4SLinus Torvalds #define RME96_WCR_DOLBY (1 << 27) 1021da177e4SLinus Torvalds #define RME96_WCR_MONITOR_0 (1 << 28) 1031da177e4SLinus Torvalds #define RME96_WCR_MONITOR_1 (1 << 29) 1041da177e4SLinus Torvalds #define RME96_WCR_ISEL (1 << 30) 1051da177e4SLinus Torvalds #define RME96_WCR_IDIS (1 << 31) 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds #define RME96_WCR_BITPOS_GAIN_0 2 1081da177e4SLinus Torvalds #define RME96_WCR_BITPOS_GAIN_1 3 1091da177e4SLinus Torvalds #define RME96_WCR_BITPOS_FREQ_0 9 1101da177e4SLinus Torvalds #define RME96_WCR_BITPOS_FREQ_1 10 1111da177e4SLinus Torvalds #define RME96_WCR_BITPOS_INP_0 17 1121da177e4SLinus Torvalds #define RME96_WCR_BITPOS_INP_1 18 1131da177e4SLinus Torvalds #define RME96_WCR_BITPOS_MONITOR_0 28 1141da177e4SLinus Torvalds #define RME96_WCR_BITPOS_MONITOR_1 29 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds /* Read control register bits */ 1171da177e4SLinus Torvalds #define RME96_RCR_AUDIO_ADDR_MASK 0xFFFF 1181da177e4SLinus Torvalds #define RME96_RCR_IRQ_2 (1 << 16) 1191da177e4SLinus Torvalds #define RME96_RCR_T_OUT (1 << 17) 1201da177e4SLinus Torvalds #define RME96_RCR_DEV_ID_0 (1 << 21) 1211da177e4SLinus Torvalds #define RME96_RCR_DEV_ID_1 (1 << 22) 1221da177e4SLinus Torvalds #define RME96_RCR_LOCK (1 << 23) 1231da177e4SLinus Torvalds #define RME96_RCR_VERF (1 << 26) 1241da177e4SLinus Torvalds #define RME96_RCR_F0 (1 << 27) 1251da177e4SLinus Torvalds #define RME96_RCR_F1 (1 << 28) 1261da177e4SLinus Torvalds #define RME96_RCR_F2 (1 << 29) 1271da177e4SLinus Torvalds #define RME96_RCR_AUTOSYNC (1 << 30) 1281da177e4SLinus Torvalds #define RME96_RCR_IRQ (1 << 31) 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds #define RME96_RCR_BITPOS_F0 27 1311da177e4SLinus Torvalds #define RME96_RCR_BITPOS_F1 28 1321da177e4SLinus Torvalds #define RME96_RCR_BITPOS_F2 29 1331da177e4SLinus Torvalds 13425985edcSLucas De Marchi /* Additional register bits */ 1351da177e4SLinus Torvalds #define RME96_AR_WSEL (1 << 0) 1361da177e4SLinus Torvalds #define RME96_AR_ANALOG (1 << 1) 1371da177e4SLinus Torvalds #define RME96_AR_FREQPAD_0 (1 << 2) 1381da177e4SLinus Torvalds #define RME96_AR_FREQPAD_1 (1 << 3) 1391da177e4SLinus Torvalds #define RME96_AR_FREQPAD_2 (1 << 4) 1401da177e4SLinus Torvalds #define RME96_AR_PD2 (1 << 5) 1411da177e4SLinus Torvalds #define RME96_AR_DAC_EN (1 << 6) 1421da177e4SLinus Torvalds #define RME96_AR_CLATCH (1 << 7) 1431da177e4SLinus Torvalds #define RME96_AR_CCLK (1 << 8) 1441da177e4SLinus Torvalds #define RME96_AR_CDATA (1 << 9) 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds #define RME96_AR_BITPOS_F0 2 1471da177e4SLinus Torvalds #define RME96_AR_BITPOS_F1 3 1481da177e4SLinus Torvalds #define RME96_AR_BITPOS_F2 4 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds /* Monitor tracks */ 1511da177e4SLinus Torvalds #define RME96_MONITOR_TRACKS_1_2 0 1521da177e4SLinus Torvalds #define RME96_MONITOR_TRACKS_3_4 1 1531da177e4SLinus Torvalds #define RME96_MONITOR_TRACKS_5_6 2 1541da177e4SLinus Torvalds #define RME96_MONITOR_TRACKS_7_8 3 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds /* Attenuation */ 1571da177e4SLinus Torvalds #define RME96_ATTENUATION_0 0 1581da177e4SLinus Torvalds #define RME96_ATTENUATION_6 1 1591da177e4SLinus Torvalds #define RME96_ATTENUATION_12 2 1601da177e4SLinus Torvalds #define RME96_ATTENUATION_18 3 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds /* Input types */ 1631da177e4SLinus Torvalds #define RME96_INPUT_OPTICAL 0 1641da177e4SLinus Torvalds #define RME96_INPUT_COAXIAL 1 1651da177e4SLinus Torvalds #define RME96_INPUT_INTERNAL 2 1661da177e4SLinus Torvalds #define RME96_INPUT_XLR 3 1671da177e4SLinus Torvalds #define RME96_INPUT_ANALOG 4 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds /* Clock modes */ 1701da177e4SLinus Torvalds #define RME96_CLOCKMODE_SLAVE 0 1711da177e4SLinus Torvalds #define RME96_CLOCKMODE_MASTER 1 1721da177e4SLinus Torvalds #define RME96_CLOCKMODE_WORDCLOCK 2 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds /* Block sizes in bytes */ 1751da177e4SLinus Torvalds #define RME96_SMALL_BLOCK_SIZE 2048 1761da177e4SLinus Torvalds #define RME96_LARGE_BLOCK_SIZE 8192 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds /* Volume control */ 1791da177e4SLinus Torvalds #define RME96_AD1852_VOL_BITS 14 1801da177e4SLinus Torvalds #define RME96_AD1855_VOL_BITS 10 1811da177e4SLinus Torvalds 182b892ca1cSKnut Petersen /* Defines for snd_rme96_trigger */ 183b892ca1cSKnut Petersen #define RME96_TB_START_PLAYBACK 1 184b892ca1cSKnut Petersen #define RME96_TB_START_CAPTURE 2 185b892ca1cSKnut Petersen #define RME96_TB_STOP_PLAYBACK 4 186b892ca1cSKnut Petersen #define RME96_TB_STOP_CAPTURE 8 187b892ca1cSKnut Petersen #define RME96_TB_RESET_PLAYPOS 16 188b892ca1cSKnut Petersen #define RME96_TB_RESET_CAPTUREPOS 32 189b892ca1cSKnut Petersen #define RME96_TB_CLEAR_PLAYBACK_IRQ 64 190b892ca1cSKnut Petersen #define RME96_TB_CLEAR_CAPTURE_IRQ 128 191b892ca1cSKnut Petersen #define RME96_RESUME_PLAYBACK (RME96_TB_START_PLAYBACK) 192b892ca1cSKnut Petersen #define RME96_RESUME_CAPTURE (RME96_TB_START_CAPTURE) 193b892ca1cSKnut Petersen #define RME96_RESUME_BOTH (RME96_RESUME_PLAYBACK \ 194b892ca1cSKnut Petersen | RME96_RESUME_CAPTURE) 195b892ca1cSKnut Petersen #define RME96_START_PLAYBACK (RME96_TB_START_PLAYBACK \ 196b892ca1cSKnut Petersen | RME96_TB_RESET_PLAYPOS) 197b892ca1cSKnut Petersen #define RME96_START_CAPTURE (RME96_TB_START_CAPTURE \ 198b892ca1cSKnut Petersen | RME96_TB_RESET_CAPTUREPOS) 199b892ca1cSKnut Petersen #define RME96_START_BOTH (RME96_START_PLAYBACK \ 200b892ca1cSKnut Petersen | RME96_START_CAPTURE) 201b892ca1cSKnut Petersen #define RME96_STOP_PLAYBACK (RME96_TB_STOP_PLAYBACK \ 202b892ca1cSKnut Petersen | RME96_TB_CLEAR_PLAYBACK_IRQ) 203b892ca1cSKnut Petersen #define RME96_STOP_CAPTURE (RME96_TB_STOP_CAPTURE \ 204b892ca1cSKnut Petersen | RME96_TB_CLEAR_CAPTURE_IRQ) 205b892ca1cSKnut Petersen #define RME96_STOP_BOTH (RME96_STOP_PLAYBACK \ 206b892ca1cSKnut Petersen | RME96_STOP_CAPTURE) 2071da177e4SLinus Torvalds 208a3aefd88STakashi Iwai struct rme96 { 2091da177e4SLinus Torvalds spinlock_t lock; 2101da177e4SLinus Torvalds int irq; 2111da177e4SLinus Torvalds unsigned long port; 2121da177e4SLinus Torvalds void __iomem *iobase; 2131da177e4SLinus Torvalds 2141da177e4SLinus Torvalds u32 wcreg; /* cached write control register value */ 2151da177e4SLinus Torvalds u32 wcreg_spdif; /* S/PDIF setup */ 2161da177e4SLinus Torvalds u32 wcreg_spdif_stream; /* S/PDIF setup (temporary) */ 2171da177e4SLinus Torvalds u32 rcreg; /* cached read control register value */ 2181da177e4SLinus Torvalds u32 areg; /* cached additional register value */ 2191da177e4SLinus Torvalds u16 vol[2]; /* cached volume of analog output */ 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds u8 rev; /* card revision number */ 2221da177e4SLinus Torvalds 223a932be91STakashi Iwai #ifdef CONFIG_PM_SLEEP 224528ba522SKnut Petersen u32 playback_pointer; 225528ba522SKnut Petersen u32 capture_pointer; 226528ba522SKnut Petersen void *playback_suspend_buffer; 227528ba522SKnut Petersen void *capture_suspend_buffer; 228528ba522SKnut Petersen #endif 229528ba522SKnut Petersen 230a3aefd88STakashi Iwai struct snd_pcm_substream *playback_substream; 231a3aefd88STakashi Iwai struct snd_pcm_substream *capture_substream; 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds int playback_frlog; /* log2 of framesize */ 2341da177e4SLinus Torvalds int capture_frlog; 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds size_t playback_periodsize; /* in bytes, zero if not used */ 2371da177e4SLinus Torvalds size_t capture_periodsize; /* in bytes, zero if not used */ 2381da177e4SLinus Torvalds 239a3aefd88STakashi Iwai struct snd_card *card; 240a3aefd88STakashi Iwai struct snd_pcm *spdif_pcm; 241a3aefd88STakashi Iwai struct snd_pcm *adat_pcm; 2421da177e4SLinus Torvalds struct pci_dev *pci; 243a3aefd88STakashi Iwai struct snd_kcontrol *spdif_ctl; 244a3aefd88STakashi Iwai }; 2451da177e4SLinus Torvalds 2469baa3c34SBenoit Taine static const struct pci_device_id snd_rme96_ids[] = { 24728d27aaeSJoe Perches { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96), 0, }, 24828d27aaeSJoe Perches { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8), 0, }, 24928d27aaeSJoe Perches { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO), 0, }, 25028d27aaeSJoe Perches { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST), 0, }, 2511da177e4SLinus Torvalds { 0, } 2521da177e4SLinus Torvalds }; 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, snd_rme96_ids); 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds #define RME96_ISPLAYING(rme96) ((rme96)->wcreg & RME96_WCR_START) 2571da177e4SLinus Torvalds #define RME96_ISRECORDING(rme96) ((rme96)->wcreg & RME96_WCR_START_2) 2588b7fc421SRoland Dreier #define RME96_HAS_ANALOG_IN(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST) 2598b7fc421SRoland Dreier #define RME96_HAS_ANALOG_OUT(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO || \ 2608b7fc421SRoland Dreier (rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST) 2611da177e4SLinus Torvalds #define RME96_DAC_IS_1852(rme96) (RME96_HAS_ANALOG_OUT(rme96) && (rme96)->rev >= 4) 2628b7fc421SRoland Dreier #define RME96_DAC_IS_1855(rme96) (((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && (rme96)->rev < 4) || \ 2638b7fc421SRoland Dreier ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO && (rme96)->rev == 2)) 2641da177e4SLinus Torvalds #define RME96_185X_MAX_OUT(rme96) ((1 << (RME96_DAC_IS_1852(rme96) ? RME96_AD1852_VOL_BITS : RME96_AD1855_VOL_BITS)) - 1) 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds static int 267a3aefd88STakashi Iwai snd_rme96_playback_prepare(struct snd_pcm_substream *substream); 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds static int 270a3aefd88STakashi Iwai snd_rme96_capture_prepare(struct snd_pcm_substream *substream); 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds static int 273a3aefd88STakashi Iwai snd_rme96_playback_trigger(struct snd_pcm_substream *substream, 2741da177e4SLinus Torvalds int cmd); 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds static int 277a3aefd88STakashi Iwai snd_rme96_capture_trigger(struct snd_pcm_substream *substream, 2781da177e4SLinus Torvalds int cmd); 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds static snd_pcm_uframes_t 281a3aefd88STakashi Iwai snd_rme96_playback_pointer(struct snd_pcm_substream *substream); 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds static snd_pcm_uframes_t 284a3aefd88STakashi Iwai snd_rme96_capture_pointer(struct snd_pcm_substream *substream); 2851da177e4SLinus Torvalds 286e23e7a14SBill Pemberton static void snd_rme96_proc_init(struct rme96 *rme96); 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds static int 289a3aefd88STakashi Iwai snd_rme96_create_switches(struct snd_card *card, 290a3aefd88STakashi Iwai struct rme96 *rme96); 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds static int 293a3aefd88STakashi Iwai snd_rme96_getinputtype(struct rme96 *rme96); 2941da177e4SLinus Torvalds 2951da177e4SLinus Torvalds static inline unsigned int 296a3aefd88STakashi Iwai snd_rme96_playback_ptr(struct rme96 *rme96) 2971da177e4SLinus Torvalds { 2981da177e4SLinus Torvalds return (readl(rme96->iobase + RME96_IO_GET_PLAY_POS) 2991da177e4SLinus Torvalds & RME96_RCR_AUDIO_ADDR_MASK) >> rme96->playback_frlog; 3001da177e4SLinus Torvalds } 3011da177e4SLinus Torvalds 3021da177e4SLinus Torvalds static inline unsigned int 303a3aefd88STakashi Iwai snd_rme96_capture_ptr(struct rme96 *rme96) 3041da177e4SLinus Torvalds { 3051da177e4SLinus Torvalds return (readl(rme96->iobase + RME96_IO_GET_REC_POS) 3061da177e4SLinus Torvalds & RME96_RCR_AUDIO_ADDR_MASK) >> rme96->capture_frlog; 3071da177e4SLinus Torvalds } 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds static int 310a3aefd88STakashi Iwai snd_rme96_playback_silence(struct snd_pcm_substream *substream, 31153945f5bSTakashi Iwai int channel, unsigned long pos, unsigned long count) 3121da177e4SLinus Torvalds { 313a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 31453945f5bSTakashi Iwai 3151da177e4SLinus Torvalds memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, 3161da177e4SLinus Torvalds 0, count); 3171da177e4SLinus Torvalds return 0; 3181da177e4SLinus Torvalds } 3191da177e4SLinus Torvalds 3201da177e4SLinus Torvalds static int 321a3aefd88STakashi Iwai snd_rme96_playback_copy(struct snd_pcm_substream *substream, 32253945f5bSTakashi Iwai int channel, unsigned long pos, 32353945f5bSTakashi Iwai void __user *src, unsigned long count) 3241da177e4SLinus Torvalds { 325a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 32653945f5bSTakashi Iwai 32753945f5bSTakashi Iwai return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, 32853945f5bSTakashi Iwai src, count); 32953945f5bSTakashi Iwai } 33053945f5bSTakashi Iwai 33153945f5bSTakashi Iwai static int 33253945f5bSTakashi Iwai snd_rme96_playback_copy_kernel(struct snd_pcm_substream *substream, 33353945f5bSTakashi Iwai int channel, unsigned long pos, 33453945f5bSTakashi Iwai void *src, unsigned long count) 33553945f5bSTakashi Iwai { 33653945f5bSTakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 33753945f5bSTakashi Iwai 33853945f5bSTakashi Iwai memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, count); 33953945f5bSTakashi Iwai return 0; 3401da177e4SLinus Torvalds } 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds static int 343a3aefd88STakashi Iwai snd_rme96_capture_copy(struct snd_pcm_substream *substream, 34453945f5bSTakashi Iwai int channel, unsigned long pos, 34553945f5bSTakashi Iwai void __user *dst, unsigned long count) 3461da177e4SLinus Torvalds { 347a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 34853945f5bSTakashi Iwai 34953945f5bSTakashi Iwai return copy_to_user_fromio(dst, 35053945f5bSTakashi Iwai rme96->iobase + RME96_IO_REC_BUFFER + pos, 3511da177e4SLinus Torvalds count); 3521da177e4SLinus Torvalds } 3531da177e4SLinus Torvalds 35453945f5bSTakashi Iwai static int 35553945f5bSTakashi Iwai snd_rme96_capture_copy_kernel(struct snd_pcm_substream *substream, 35653945f5bSTakashi Iwai int channel, unsigned long pos, 35753945f5bSTakashi Iwai void *dst, unsigned long count) 35853945f5bSTakashi Iwai { 35953945f5bSTakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 36053945f5bSTakashi Iwai 36153945f5bSTakashi Iwai memcpy_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, count); 36253945f5bSTakashi Iwai return 0; 36353945f5bSTakashi Iwai } 36453945f5bSTakashi Iwai 3651da177e4SLinus Torvalds /* 3667f927fccSAlexey Dobriyan * Digital output capabilities (S/PDIF) 3671da177e4SLinus Torvalds */ 368dee49895SBhumika Goyal static const struct snd_pcm_hardware snd_rme96_playback_spdif_info = 3691da177e4SLinus Torvalds { 3701da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP_IOMEM | 3711da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 372b892ca1cSKnut Petersen SNDRV_PCM_INFO_SYNC_START | 373528ba522SKnut Petersen SNDRV_PCM_INFO_RESUME | 3741da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 3751da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE), 3761da177e4SLinus Torvalds .formats = (SNDRV_PCM_FMTBIT_S16_LE | 3771da177e4SLinus Torvalds SNDRV_PCM_FMTBIT_S32_LE), 3781da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_32000 | 3791da177e4SLinus Torvalds SNDRV_PCM_RATE_44100 | 3801da177e4SLinus Torvalds SNDRV_PCM_RATE_48000 | 3811da177e4SLinus Torvalds SNDRV_PCM_RATE_64000 | 3821da177e4SLinus Torvalds SNDRV_PCM_RATE_88200 | 3831da177e4SLinus Torvalds SNDRV_PCM_RATE_96000), 3841da177e4SLinus Torvalds .rate_min = 32000, 3851da177e4SLinus Torvalds .rate_max = 96000, 3861da177e4SLinus Torvalds .channels_min = 2, 3871da177e4SLinus Torvalds .channels_max = 2, 3881da177e4SLinus Torvalds .buffer_bytes_max = RME96_BUFFER_SIZE, 3891da177e4SLinus Torvalds .period_bytes_min = RME96_SMALL_BLOCK_SIZE, 3901da177e4SLinus Torvalds .period_bytes_max = RME96_LARGE_BLOCK_SIZE, 3911da177e4SLinus Torvalds .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, 3921da177e4SLinus Torvalds .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, 3931da177e4SLinus Torvalds .fifo_size = 0, 3941da177e4SLinus Torvalds }; 3951da177e4SLinus Torvalds 3961da177e4SLinus Torvalds /* 3977f927fccSAlexey Dobriyan * Digital input capabilities (S/PDIF) 3981da177e4SLinus Torvalds */ 399dee49895SBhumika Goyal static const struct snd_pcm_hardware snd_rme96_capture_spdif_info = 4001da177e4SLinus Torvalds { 4011da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP_IOMEM | 4021da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 403b892ca1cSKnut Petersen SNDRV_PCM_INFO_SYNC_START | 404528ba522SKnut Petersen SNDRV_PCM_INFO_RESUME | 4051da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 4061da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE), 4071da177e4SLinus Torvalds .formats = (SNDRV_PCM_FMTBIT_S16_LE | 4081da177e4SLinus Torvalds SNDRV_PCM_FMTBIT_S32_LE), 4091da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_32000 | 4101da177e4SLinus Torvalds SNDRV_PCM_RATE_44100 | 4111da177e4SLinus Torvalds SNDRV_PCM_RATE_48000 | 4121da177e4SLinus Torvalds SNDRV_PCM_RATE_64000 | 4131da177e4SLinus Torvalds SNDRV_PCM_RATE_88200 | 4141da177e4SLinus Torvalds SNDRV_PCM_RATE_96000), 4151da177e4SLinus Torvalds .rate_min = 32000, 4161da177e4SLinus Torvalds .rate_max = 96000, 4171da177e4SLinus Torvalds .channels_min = 2, 4181da177e4SLinus Torvalds .channels_max = 2, 4191da177e4SLinus Torvalds .buffer_bytes_max = RME96_BUFFER_SIZE, 4201da177e4SLinus Torvalds .period_bytes_min = RME96_SMALL_BLOCK_SIZE, 4211da177e4SLinus Torvalds .period_bytes_max = RME96_LARGE_BLOCK_SIZE, 4221da177e4SLinus Torvalds .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, 4231da177e4SLinus Torvalds .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, 4241da177e4SLinus Torvalds .fifo_size = 0, 4251da177e4SLinus Torvalds }; 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds /* 4287f927fccSAlexey Dobriyan * Digital output capabilities (ADAT) 4291da177e4SLinus Torvalds */ 430dee49895SBhumika Goyal static const struct snd_pcm_hardware snd_rme96_playback_adat_info = 4311da177e4SLinus Torvalds { 4321da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP_IOMEM | 4331da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 434b892ca1cSKnut Petersen SNDRV_PCM_INFO_SYNC_START | 435528ba522SKnut Petersen SNDRV_PCM_INFO_RESUME | 4361da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 4371da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE), 4381da177e4SLinus Torvalds .formats = (SNDRV_PCM_FMTBIT_S16_LE | 4391da177e4SLinus Torvalds SNDRV_PCM_FMTBIT_S32_LE), 4401da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_44100 | 4411da177e4SLinus Torvalds SNDRV_PCM_RATE_48000), 4421da177e4SLinus Torvalds .rate_min = 44100, 4431da177e4SLinus Torvalds .rate_max = 48000, 4441da177e4SLinus Torvalds .channels_min = 8, 4451da177e4SLinus Torvalds .channels_max = 8, 4461da177e4SLinus Torvalds .buffer_bytes_max = RME96_BUFFER_SIZE, 4471da177e4SLinus Torvalds .period_bytes_min = RME96_SMALL_BLOCK_SIZE, 4481da177e4SLinus Torvalds .period_bytes_max = RME96_LARGE_BLOCK_SIZE, 4491da177e4SLinus Torvalds .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, 4501da177e4SLinus Torvalds .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, 4511da177e4SLinus Torvalds .fifo_size = 0, 4521da177e4SLinus Torvalds }; 4531da177e4SLinus Torvalds 4541da177e4SLinus Torvalds /* 4557f927fccSAlexey Dobriyan * Digital input capabilities (ADAT) 4561da177e4SLinus Torvalds */ 457dee49895SBhumika Goyal static const struct snd_pcm_hardware snd_rme96_capture_adat_info = 4581da177e4SLinus Torvalds { 4591da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP_IOMEM | 4601da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID | 461b892ca1cSKnut Petersen SNDRV_PCM_INFO_SYNC_START | 462528ba522SKnut Petersen SNDRV_PCM_INFO_RESUME | 4631da177e4SLinus Torvalds SNDRV_PCM_INFO_INTERLEAVED | 4641da177e4SLinus Torvalds SNDRV_PCM_INFO_PAUSE), 4651da177e4SLinus Torvalds .formats = (SNDRV_PCM_FMTBIT_S16_LE | 4661da177e4SLinus Torvalds SNDRV_PCM_FMTBIT_S32_LE), 4671da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_44100 | 4681da177e4SLinus Torvalds SNDRV_PCM_RATE_48000), 4691da177e4SLinus Torvalds .rate_min = 44100, 4701da177e4SLinus Torvalds .rate_max = 48000, 4711da177e4SLinus Torvalds .channels_min = 8, 4721da177e4SLinus Torvalds .channels_max = 8, 4731da177e4SLinus Torvalds .buffer_bytes_max = RME96_BUFFER_SIZE, 4741da177e4SLinus Torvalds .period_bytes_min = RME96_SMALL_BLOCK_SIZE, 4751da177e4SLinus Torvalds .period_bytes_max = RME96_LARGE_BLOCK_SIZE, 4761da177e4SLinus Torvalds .periods_min = RME96_BUFFER_SIZE / RME96_LARGE_BLOCK_SIZE, 4771da177e4SLinus Torvalds .periods_max = RME96_BUFFER_SIZE / RME96_SMALL_BLOCK_SIZE, 4781da177e4SLinus Torvalds .fifo_size = 0, 4791da177e4SLinus Torvalds }; 4801da177e4SLinus Torvalds 4811da177e4SLinus Torvalds /* 4821da177e4SLinus Torvalds * The CDATA, CCLK and CLATCH bits can be used to write to the SPI interface 4831da177e4SLinus Torvalds * of the AD1852 or AD1852 D/A converter on the board. CDATA must be set up 4841da177e4SLinus Torvalds * on the falling edge of CCLK and be stable on the rising edge. The rising 4851da177e4SLinus Torvalds * edge of CLATCH after the last data bit clocks in the whole data word. 4861da177e4SLinus Torvalds * A fast processor could probably drive the SPI interface faster than the 4871da177e4SLinus Torvalds * DAC can handle (3MHz for the 1855, unknown for the 1852). The udelay(1) 4881da177e4SLinus Torvalds * limits the data rate to 500KHz and only causes a delay of 33 microsecs. 4891da177e4SLinus Torvalds * 4901da177e4SLinus Torvalds * NOTE: increased delay from 1 to 10, since there where problems setting 4911da177e4SLinus Torvalds * the volume. 4921da177e4SLinus Torvalds */ 4931da177e4SLinus Torvalds static void 494a3aefd88STakashi Iwai snd_rme96_write_SPI(struct rme96 *rme96, u16 val) 4951da177e4SLinus Torvalds { 4961da177e4SLinus Torvalds int i; 4971da177e4SLinus Torvalds 4981da177e4SLinus Torvalds for (i = 0; i < 16; i++) { 4991da177e4SLinus Torvalds if (val & 0x8000) { 5001da177e4SLinus Torvalds rme96->areg |= RME96_AR_CDATA; 5011da177e4SLinus Torvalds } else { 5021da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_CDATA; 5031da177e4SLinus Torvalds } 5041da177e4SLinus Torvalds rme96->areg &= ~(RME96_AR_CCLK | RME96_AR_CLATCH); 5051da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 5061da177e4SLinus Torvalds udelay(10); 5071da177e4SLinus Torvalds rme96->areg |= RME96_AR_CCLK; 5081da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 5091da177e4SLinus Torvalds udelay(10); 5101da177e4SLinus Torvalds val <<= 1; 5111da177e4SLinus Torvalds } 5121da177e4SLinus Torvalds rme96->areg &= ~(RME96_AR_CCLK | RME96_AR_CDATA); 5131da177e4SLinus Torvalds rme96->areg |= RME96_AR_CLATCH; 5141da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 5151da177e4SLinus Torvalds udelay(10); 5161da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_CLATCH; 5171da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 5181da177e4SLinus Torvalds } 5191da177e4SLinus Torvalds 5201da177e4SLinus Torvalds static void 521a3aefd88STakashi Iwai snd_rme96_apply_dac_volume(struct rme96 *rme96) 5221da177e4SLinus Torvalds { 5231da177e4SLinus Torvalds if (RME96_DAC_IS_1852(rme96)) { 5241da177e4SLinus Torvalds snd_rme96_write_SPI(rme96, (rme96->vol[0] << 2) | 0x0); 5251da177e4SLinus Torvalds snd_rme96_write_SPI(rme96, (rme96->vol[1] << 2) | 0x2); 5261da177e4SLinus Torvalds } else if (RME96_DAC_IS_1855(rme96)) { 5271da177e4SLinus Torvalds snd_rme96_write_SPI(rme96, (rme96->vol[0] & 0x3FF) | 0x000); 5281da177e4SLinus Torvalds snd_rme96_write_SPI(rme96, (rme96->vol[1] & 0x3FF) | 0x400); 5291da177e4SLinus Torvalds } 5301da177e4SLinus Torvalds } 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds static void 533a3aefd88STakashi Iwai snd_rme96_reset_dac(struct rme96 *rme96) 5341da177e4SLinus Torvalds { 5351da177e4SLinus Torvalds writel(rme96->wcreg | RME96_WCR_PD, 5361da177e4SLinus Torvalds rme96->iobase + RME96_IO_CONTROL_REGISTER); 5371da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 5381da177e4SLinus Torvalds } 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds static int 541a3aefd88STakashi Iwai snd_rme96_getmontracks(struct rme96 *rme96) 5421da177e4SLinus Torvalds { 5431da177e4SLinus Torvalds return ((rme96->wcreg >> RME96_WCR_BITPOS_MONITOR_0) & 1) + 5441da177e4SLinus Torvalds (((rme96->wcreg >> RME96_WCR_BITPOS_MONITOR_1) & 1) << 1); 5451da177e4SLinus Torvalds } 5461da177e4SLinus Torvalds 5471da177e4SLinus Torvalds static int 548a3aefd88STakashi Iwai snd_rme96_setmontracks(struct rme96 *rme96, 5491da177e4SLinus Torvalds int montracks) 5501da177e4SLinus Torvalds { 5511da177e4SLinus Torvalds if (montracks & 1) { 5521da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MONITOR_0; 5531da177e4SLinus Torvalds } else { 5541da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_MONITOR_0; 5551da177e4SLinus Torvalds } 5561da177e4SLinus Torvalds if (montracks & 2) { 5571da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MONITOR_1; 5581da177e4SLinus Torvalds } else { 5591da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_MONITOR_1; 5601da177e4SLinus Torvalds } 5611da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 5621da177e4SLinus Torvalds return 0; 5631da177e4SLinus Torvalds } 5641da177e4SLinus Torvalds 5651da177e4SLinus Torvalds static int 566a3aefd88STakashi Iwai snd_rme96_getattenuation(struct rme96 *rme96) 5671da177e4SLinus Torvalds { 5681da177e4SLinus Torvalds return ((rme96->wcreg >> RME96_WCR_BITPOS_GAIN_0) & 1) + 5691da177e4SLinus Torvalds (((rme96->wcreg >> RME96_WCR_BITPOS_GAIN_1) & 1) << 1); 5701da177e4SLinus Torvalds } 5711da177e4SLinus Torvalds 5721da177e4SLinus Torvalds static int 573a3aefd88STakashi Iwai snd_rme96_setattenuation(struct rme96 *rme96, 5741da177e4SLinus Torvalds int attenuation) 5751da177e4SLinus Torvalds { 5761da177e4SLinus Torvalds switch (attenuation) { 5771da177e4SLinus Torvalds case 0: 5781da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg & ~RME96_WCR_GAIN_0) & 5791da177e4SLinus Torvalds ~RME96_WCR_GAIN_1; 5801da177e4SLinus Torvalds break; 5811da177e4SLinus Torvalds case 1: 5821da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_GAIN_0) & 5831da177e4SLinus Torvalds ~RME96_WCR_GAIN_1; 5841da177e4SLinus Torvalds break; 5851da177e4SLinus Torvalds case 2: 5861da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg & ~RME96_WCR_GAIN_0) | 5871da177e4SLinus Torvalds RME96_WCR_GAIN_1; 5881da177e4SLinus Torvalds break; 5891da177e4SLinus Torvalds case 3: 5901da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_GAIN_0) | 5911da177e4SLinus Torvalds RME96_WCR_GAIN_1; 5921da177e4SLinus Torvalds break; 5931da177e4SLinus Torvalds default: 5941da177e4SLinus Torvalds return -EINVAL; 5951da177e4SLinus Torvalds } 5961da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 5971da177e4SLinus Torvalds return 0; 5981da177e4SLinus Torvalds } 5991da177e4SLinus Torvalds 6001da177e4SLinus Torvalds static int 601a3aefd88STakashi Iwai snd_rme96_capture_getrate(struct rme96 *rme96, 6021da177e4SLinus Torvalds int *is_adat) 6031da177e4SLinus Torvalds { 6041da177e4SLinus Torvalds int n, rate; 6051da177e4SLinus Torvalds 6061da177e4SLinus Torvalds *is_adat = 0; 6071da177e4SLinus Torvalds if (rme96->areg & RME96_AR_ANALOG) { 6081da177e4SLinus Torvalds /* Analog input, overrides S/PDIF setting */ 6091da177e4SLinus Torvalds n = ((rme96->areg >> RME96_AR_BITPOS_F0) & 1) + 6101da177e4SLinus Torvalds (((rme96->areg >> RME96_AR_BITPOS_F1) & 1) << 1); 6111da177e4SLinus Torvalds switch (n) { 6121da177e4SLinus Torvalds case 1: 6131da177e4SLinus Torvalds rate = 32000; 6141da177e4SLinus Torvalds break; 6151da177e4SLinus Torvalds case 2: 6161da177e4SLinus Torvalds rate = 44100; 6171da177e4SLinus Torvalds break; 6181da177e4SLinus Torvalds case 3: 6191da177e4SLinus Torvalds rate = 48000; 6201da177e4SLinus Torvalds break; 6211da177e4SLinus Torvalds default: 6221da177e4SLinus Torvalds return -1; 6231da177e4SLinus Torvalds } 6241da177e4SLinus Torvalds return (rme96->areg & RME96_AR_BITPOS_F2) ? rate << 1 : rate; 6251da177e4SLinus Torvalds } 6261da177e4SLinus Torvalds 6271da177e4SLinus Torvalds rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 6281da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_LOCK) { 6291da177e4SLinus Torvalds /* ADAT rate */ 6301da177e4SLinus Torvalds *is_adat = 1; 6311da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_T_OUT) { 6321da177e4SLinus Torvalds return 48000; 6331da177e4SLinus Torvalds } 6341da177e4SLinus Torvalds return 44100; 6351da177e4SLinus Torvalds } 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_VERF) { 6381da177e4SLinus Torvalds return -1; 6391da177e4SLinus Torvalds } 6401da177e4SLinus Torvalds 6411da177e4SLinus Torvalds /* S/PDIF rate */ 6421da177e4SLinus Torvalds n = ((rme96->rcreg >> RME96_RCR_BITPOS_F0) & 1) + 6431da177e4SLinus Torvalds (((rme96->rcreg >> RME96_RCR_BITPOS_F1) & 1) << 1) + 6441da177e4SLinus Torvalds (((rme96->rcreg >> RME96_RCR_BITPOS_F2) & 1) << 2); 6451da177e4SLinus Torvalds 6461da177e4SLinus Torvalds switch (n) { 6471da177e4SLinus Torvalds case 0: 6481da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_T_OUT) { 6491da177e4SLinus Torvalds return 64000; 6501da177e4SLinus Torvalds } 6511da177e4SLinus Torvalds return -1; 6521da177e4SLinus Torvalds case 3: return 96000; 6531da177e4SLinus Torvalds case 4: return 88200; 6541da177e4SLinus Torvalds case 5: return 48000; 6551da177e4SLinus Torvalds case 6: return 44100; 6561da177e4SLinus Torvalds case 7: return 32000; 6571da177e4SLinus Torvalds default: 6581da177e4SLinus Torvalds break; 6591da177e4SLinus Torvalds } 6601da177e4SLinus Torvalds return -1; 6611da177e4SLinus Torvalds } 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds static int 664a3aefd88STakashi Iwai snd_rme96_playback_getrate(struct rme96 *rme96) 6651da177e4SLinus Torvalds { 6661da177e4SLinus Torvalds int rate, dummy; 6671da177e4SLinus Torvalds 6681da177e4SLinus Torvalds if (!(rme96->wcreg & RME96_WCR_MASTER) && 669da8eedb1STakashi Iwai snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) { 670da8eedb1STakashi Iwai rate = snd_rme96_capture_getrate(rme96, &dummy); 671da8eedb1STakashi Iwai if (rate > 0) { 6721da177e4SLinus Torvalds /* slave clock */ 6731da177e4SLinus Torvalds return rate; 6741da177e4SLinus Torvalds } 675da8eedb1STakashi Iwai } 676da8eedb1STakashi Iwai 6771da177e4SLinus Torvalds rate = ((rme96->wcreg >> RME96_WCR_BITPOS_FREQ_0) & 1) + 6781da177e4SLinus Torvalds (((rme96->wcreg >> RME96_WCR_BITPOS_FREQ_1) & 1) << 1); 6791da177e4SLinus Torvalds switch (rate) { 6801da177e4SLinus Torvalds case 1: 6811da177e4SLinus Torvalds rate = 32000; 6821da177e4SLinus Torvalds break; 6831da177e4SLinus Torvalds case 2: 6841da177e4SLinus Torvalds rate = 44100; 6851da177e4SLinus Torvalds break; 6861da177e4SLinus Torvalds case 3: 6871da177e4SLinus Torvalds rate = 48000; 6881da177e4SLinus Torvalds break; 6891da177e4SLinus Torvalds default: 6901da177e4SLinus Torvalds return -1; 6911da177e4SLinus Torvalds } 6921da177e4SLinus Torvalds return (rme96->wcreg & RME96_WCR_DS) ? rate << 1 : rate; 6931da177e4SLinus Torvalds } 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds static int 696a3aefd88STakashi Iwai snd_rme96_playback_setrate(struct rme96 *rme96, 6971da177e4SLinus Torvalds int rate) 6981da177e4SLinus Torvalds { 6991da177e4SLinus Torvalds int ds; 7001da177e4SLinus Torvalds 7011da177e4SLinus Torvalds ds = rme96->wcreg & RME96_WCR_DS; 7021da177e4SLinus Torvalds switch (rate) { 7031da177e4SLinus Torvalds case 32000: 7041da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_DS; 7051da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) & 7061da177e4SLinus Torvalds ~RME96_WCR_FREQ_1; 7071da177e4SLinus Torvalds break; 7081da177e4SLinus Torvalds case 44100: 7091da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_DS; 7101da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_1) & 7111da177e4SLinus Torvalds ~RME96_WCR_FREQ_0; 7121da177e4SLinus Torvalds break; 7131da177e4SLinus Torvalds case 48000: 7141da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_DS; 7151da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) | 7161da177e4SLinus Torvalds RME96_WCR_FREQ_1; 7171da177e4SLinus Torvalds break; 7181da177e4SLinus Torvalds case 64000: 7191da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_DS; 7201da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) & 7211da177e4SLinus Torvalds ~RME96_WCR_FREQ_1; 7221da177e4SLinus Torvalds break; 7231da177e4SLinus Torvalds case 88200: 7241da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_DS; 7251da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_1) & 7261da177e4SLinus Torvalds ~RME96_WCR_FREQ_0; 7271da177e4SLinus Torvalds break; 7281da177e4SLinus Torvalds case 96000: 7291da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_DS; 7301da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_FREQ_0) | 7311da177e4SLinus Torvalds RME96_WCR_FREQ_1; 7321da177e4SLinus Torvalds break; 7331da177e4SLinus Torvalds default: 7341da177e4SLinus Torvalds return -EINVAL; 7351da177e4SLinus Torvalds } 7361da177e4SLinus Torvalds if ((!ds && rme96->wcreg & RME96_WCR_DS) || 7371da177e4SLinus Torvalds (ds && !(rme96->wcreg & RME96_WCR_DS))) 7381da177e4SLinus Torvalds { 7391da177e4SLinus Torvalds /* change to/from double-speed: reset the DAC (if available) */ 7401da177e4SLinus Torvalds snd_rme96_reset_dac(rme96); 741a74a8216STakashi Iwai return 1; /* need to restore volume */ 7421da177e4SLinus Torvalds } else { 7431da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 7441da177e4SLinus Torvalds return 0; 7451da177e4SLinus Torvalds } 746a74a8216STakashi Iwai } 7471da177e4SLinus Torvalds 7481da177e4SLinus Torvalds static int 749a3aefd88STakashi Iwai snd_rme96_capture_analog_setrate(struct rme96 *rme96, 7501da177e4SLinus Torvalds int rate) 7511da177e4SLinus Torvalds { 7521da177e4SLinus Torvalds switch (rate) { 7531da177e4SLinus Torvalds case 32000: 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 44100: 7581da177e4SLinus Torvalds rme96->areg = ((rme96->areg & ~RME96_AR_FREQPAD_0) | 7591da177e4SLinus Torvalds RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2; 7601da177e4SLinus Torvalds break; 7611da177e4SLinus Torvalds case 48000: 7621da177e4SLinus Torvalds rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) | 7631da177e4SLinus Torvalds RME96_AR_FREQPAD_1) & ~RME96_AR_FREQPAD_2; 7641da177e4SLinus Torvalds break; 7651da177e4SLinus Torvalds case 64000: 7661da177e4SLinus Torvalds if (rme96->rev < 4) { 7671da177e4SLinus Torvalds return -EINVAL; 7681da177e4SLinus Torvalds } 7691da177e4SLinus Torvalds rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) & 7701da177e4SLinus Torvalds ~RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2; 7711da177e4SLinus Torvalds break; 7721da177e4SLinus Torvalds case 88200: 7731da177e4SLinus Torvalds if (rme96->rev < 4) { 7741da177e4SLinus Torvalds return -EINVAL; 7751da177e4SLinus Torvalds } 7761da177e4SLinus Torvalds rme96->areg = ((rme96->areg & ~RME96_AR_FREQPAD_0) | 7771da177e4SLinus Torvalds RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2; 7781da177e4SLinus Torvalds break; 7791da177e4SLinus Torvalds case 96000: 7801da177e4SLinus Torvalds rme96->areg = ((rme96->areg | RME96_AR_FREQPAD_0) | 7811da177e4SLinus Torvalds RME96_AR_FREQPAD_1) | RME96_AR_FREQPAD_2; 7821da177e4SLinus Torvalds break; 7831da177e4SLinus Torvalds default: 7841da177e4SLinus Torvalds return -EINVAL; 7851da177e4SLinus Torvalds } 7861da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 7871da177e4SLinus Torvalds return 0; 7881da177e4SLinus Torvalds } 7891da177e4SLinus Torvalds 7901da177e4SLinus Torvalds static int 791a3aefd88STakashi Iwai snd_rme96_setclockmode(struct rme96 *rme96, 7921da177e4SLinus Torvalds int mode) 7931da177e4SLinus Torvalds { 7941da177e4SLinus Torvalds switch (mode) { 7951da177e4SLinus Torvalds case RME96_CLOCKMODE_SLAVE: 7961da177e4SLinus Torvalds /* AutoSync */ 7971da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_MASTER; 7981da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_WSEL; 7991da177e4SLinus Torvalds break; 8001da177e4SLinus Torvalds case RME96_CLOCKMODE_MASTER: 8011da177e4SLinus Torvalds /* Internal */ 8021da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MASTER; 8031da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_WSEL; 8041da177e4SLinus Torvalds break; 8051da177e4SLinus Torvalds case RME96_CLOCKMODE_WORDCLOCK: 8061da177e4SLinus Torvalds /* Word clock is a master mode */ 8071da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MASTER; 8081da177e4SLinus Torvalds rme96->areg |= RME96_AR_WSEL; 8091da177e4SLinus Torvalds break; 8101da177e4SLinus Torvalds default: 8111da177e4SLinus Torvalds return -EINVAL; 8121da177e4SLinus Torvalds } 8131da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 8141da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 8151da177e4SLinus Torvalds return 0; 8161da177e4SLinus Torvalds } 8171da177e4SLinus Torvalds 8181da177e4SLinus Torvalds static int 819a3aefd88STakashi Iwai snd_rme96_getclockmode(struct rme96 *rme96) 8201da177e4SLinus Torvalds { 8211da177e4SLinus Torvalds if (rme96->areg & RME96_AR_WSEL) { 8221da177e4SLinus Torvalds return RME96_CLOCKMODE_WORDCLOCK; 8231da177e4SLinus Torvalds } 8241da177e4SLinus Torvalds return (rme96->wcreg & RME96_WCR_MASTER) ? RME96_CLOCKMODE_MASTER : 8251da177e4SLinus Torvalds RME96_CLOCKMODE_SLAVE; 8261da177e4SLinus Torvalds } 8271da177e4SLinus Torvalds 8281da177e4SLinus Torvalds static int 829a3aefd88STakashi Iwai snd_rme96_setinputtype(struct rme96 *rme96, 8301da177e4SLinus Torvalds int type) 8311da177e4SLinus Torvalds { 8321da177e4SLinus Torvalds int n; 8331da177e4SLinus Torvalds 8341da177e4SLinus Torvalds switch (type) { 8351da177e4SLinus Torvalds case RME96_INPUT_OPTICAL: 8361da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg & ~RME96_WCR_INP_0) & 8371da177e4SLinus Torvalds ~RME96_WCR_INP_1; 8381da177e4SLinus Torvalds break; 8391da177e4SLinus Torvalds case RME96_INPUT_COAXIAL: 8401da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_INP_0) & 8411da177e4SLinus Torvalds ~RME96_WCR_INP_1; 8421da177e4SLinus Torvalds break; 8431da177e4SLinus Torvalds case RME96_INPUT_INTERNAL: 8441da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg & ~RME96_WCR_INP_0) | 8451da177e4SLinus Torvalds RME96_WCR_INP_1; 8461da177e4SLinus Torvalds break; 8471da177e4SLinus Torvalds case RME96_INPUT_XLR: 8488b7fc421SRoland Dreier if ((rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && 8498b7fc421SRoland Dreier rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PRO) || 8508b7fc421SRoland Dreier (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && 8511da177e4SLinus Torvalds rme96->rev > 4)) 8521da177e4SLinus Torvalds { 8531da177e4SLinus Torvalds /* Only Digi96/8 PRO and Digi96/8 PAD supports XLR */ 8541da177e4SLinus Torvalds return -EINVAL; 8551da177e4SLinus Torvalds } 8561da177e4SLinus Torvalds rme96->wcreg = (rme96->wcreg | RME96_WCR_INP_0) | 8571da177e4SLinus Torvalds RME96_WCR_INP_1; 8581da177e4SLinus Torvalds break; 8591da177e4SLinus Torvalds case RME96_INPUT_ANALOG: 8601da177e4SLinus Torvalds if (!RME96_HAS_ANALOG_IN(rme96)) { 8611da177e4SLinus Torvalds return -EINVAL; 8621da177e4SLinus Torvalds } 8631da177e4SLinus Torvalds rme96->areg |= RME96_AR_ANALOG; 8641da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 8651da177e4SLinus Torvalds if (rme96->rev < 4) { 8661da177e4SLinus Torvalds /* 8671da177e4SLinus Torvalds * Revision less than 004 does not support 64 and 8681da177e4SLinus Torvalds * 88.2 kHz 8691da177e4SLinus Torvalds */ 8701da177e4SLinus Torvalds if (snd_rme96_capture_getrate(rme96, &n) == 88200) { 8711da177e4SLinus Torvalds snd_rme96_capture_analog_setrate(rme96, 44100); 8721da177e4SLinus Torvalds } 8731da177e4SLinus Torvalds if (snd_rme96_capture_getrate(rme96, &n) == 64000) { 8741da177e4SLinus Torvalds snd_rme96_capture_analog_setrate(rme96, 32000); 8751da177e4SLinus Torvalds } 8761da177e4SLinus Torvalds } 8771da177e4SLinus Torvalds return 0; 8781da177e4SLinus Torvalds default: 8791da177e4SLinus Torvalds return -EINVAL; 8801da177e4SLinus Torvalds } 8811da177e4SLinus Torvalds if (type != RME96_INPUT_ANALOG && RME96_HAS_ANALOG_IN(rme96)) { 8821da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_ANALOG; 8831da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 8841da177e4SLinus Torvalds } 8851da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 8861da177e4SLinus Torvalds return 0; 8871da177e4SLinus Torvalds } 8881da177e4SLinus Torvalds 8891da177e4SLinus Torvalds static int 890a3aefd88STakashi Iwai snd_rme96_getinputtype(struct rme96 *rme96) 8911da177e4SLinus Torvalds { 8921da177e4SLinus Torvalds if (rme96->areg & RME96_AR_ANALOG) { 8931da177e4SLinus Torvalds return RME96_INPUT_ANALOG; 8941da177e4SLinus Torvalds } 8951da177e4SLinus Torvalds return ((rme96->wcreg >> RME96_WCR_BITPOS_INP_0) & 1) + 8961da177e4SLinus Torvalds (((rme96->wcreg >> RME96_WCR_BITPOS_INP_1) & 1) << 1); 8971da177e4SLinus Torvalds } 8981da177e4SLinus Torvalds 8991da177e4SLinus Torvalds static void 900a3aefd88STakashi Iwai snd_rme96_setframelog(struct rme96 *rme96, 9011da177e4SLinus Torvalds int n_channels, 9021da177e4SLinus Torvalds int is_playback) 9031da177e4SLinus Torvalds { 9041da177e4SLinus Torvalds int frlog; 9051da177e4SLinus Torvalds 9061da177e4SLinus Torvalds if (n_channels == 2) { 9071da177e4SLinus Torvalds frlog = 1; 9081da177e4SLinus Torvalds } else { 9091da177e4SLinus Torvalds /* assume 8 channels */ 9101da177e4SLinus Torvalds frlog = 3; 9111da177e4SLinus Torvalds } 9121da177e4SLinus Torvalds if (is_playback) { 9131da177e4SLinus Torvalds frlog += (rme96->wcreg & RME96_WCR_MODE24) ? 2 : 1; 9141da177e4SLinus Torvalds rme96->playback_frlog = frlog; 9151da177e4SLinus Torvalds } else { 9161da177e4SLinus Torvalds frlog += (rme96->wcreg & RME96_WCR_MODE24_2) ? 2 : 1; 9171da177e4SLinus Torvalds rme96->capture_frlog = frlog; 9181da177e4SLinus Torvalds } 9191da177e4SLinus Torvalds } 9201da177e4SLinus Torvalds 9211da177e4SLinus Torvalds static int 9226c869d30STakashi Iwai snd_rme96_playback_setformat(struct rme96 *rme96, snd_pcm_format_t format) 9231da177e4SLinus Torvalds { 9241da177e4SLinus Torvalds switch (format) { 9251da177e4SLinus Torvalds case SNDRV_PCM_FORMAT_S16_LE: 9261da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_MODE24; 9271da177e4SLinus Torvalds break; 9281da177e4SLinus Torvalds case SNDRV_PCM_FORMAT_S32_LE: 9291da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MODE24; 9301da177e4SLinus Torvalds break; 9311da177e4SLinus Torvalds default: 9321da177e4SLinus Torvalds return -EINVAL; 9331da177e4SLinus Torvalds } 9341da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 9351da177e4SLinus Torvalds return 0; 9361da177e4SLinus Torvalds } 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds static int 9396c869d30STakashi Iwai snd_rme96_capture_setformat(struct rme96 *rme96, snd_pcm_format_t format) 9401da177e4SLinus Torvalds { 9411da177e4SLinus Torvalds switch (format) { 9421da177e4SLinus Torvalds case SNDRV_PCM_FORMAT_S16_LE: 9431da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_MODE24_2; 9441da177e4SLinus Torvalds break; 9451da177e4SLinus Torvalds case SNDRV_PCM_FORMAT_S32_LE: 9461da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_MODE24_2; 9471da177e4SLinus Torvalds break; 9481da177e4SLinus Torvalds default: 9491da177e4SLinus Torvalds return -EINVAL; 9501da177e4SLinus Torvalds } 9511da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 9521da177e4SLinus Torvalds return 0; 9531da177e4SLinus Torvalds } 9541da177e4SLinus Torvalds 9551da177e4SLinus Torvalds static void 956a3aefd88STakashi Iwai snd_rme96_set_period_properties(struct rme96 *rme96, 9571da177e4SLinus Torvalds size_t period_bytes) 9581da177e4SLinus Torvalds { 9591da177e4SLinus Torvalds switch (period_bytes) { 9601da177e4SLinus Torvalds case RME96_LARGE_BLOCK_SIZE: 9611da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_ISEL; 9621da177e4SLinus Torvalds break; 9631da177e4SLinus Torvalds case RME96_SMALL_BLOCK_SIZE: 9641da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_ISEL; 9651da177e4SLinus Torvalds break; 9661da177e4SLinus Torvalds default: 9671da177e4SLinus Torvalds snd_BUG(); 9681da177e4SLinus Torvalds break; 9691da177e4SLinus Torvalds } 9701da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_IDIS; 9711da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 9721da177e4SLinus Torvalds } 9731da177e4SLinus Torvalds 9741da177e4SLinus Torvalds static int 975a3aefd88STakashi Iwai snd_rme96_playback_hw_params(struct snd_pcm_substream *substream, 976a3aefd88STakashi Iwai struct snd_pcm_hw_params *params) 9771da177e4SLinus Torvalds { 978a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 979a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 9801da177e4SLinus Torvalds int err, rate, dummy; 981a74a8216STakashi Iwai bool apply_dac_volume = false; 9821da177e4SLinus Torvalds 9834d23359bSClemens Ladisch runtime->dma_area = (void __force *)(rme96->iobase + 9844d23359bSClemens Ladisch RME96_IO_PLAY_BUFFER); 9851da177e4SLinus Torvalds runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER; 9861da177e4SLinus Torvalds runtime->dma_bytes = RME96_BUFFER_SIZE; 9871da177e4SLinus Torvalds 9881da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 989da8eedb1STakashi Iwai rate = 0; 9901da177e4SLinus Torvalds if (!(rme96->wcreg & RME96_WCR_MASTER) && 991da8eedb1STakashi Iwai snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) 992da8eedb1STakashi Iwai rate = snd_rme96_capture_getrate(rme96, &dummy); 993da8eedb1STakashi Iwai if (rate > 0) { 9941da177e4SLinus Torvalds /* slave clock */ 9951da177e4SLinus Torvalds if ((int)params_rate(params) != rate) { 996a74a8216STakashi Iwai err = -EIO; 997a74a8216STakashi Iwai goto error; 9981da177e4SLinus Torvalds } 999a74a8216STakashi Iwai } else { 1000a74a8216STakashi Iwai err = snd_rme96_playback_setrate(rme96, params_rate(params)); 1001a74a8216STakashi Iwai if (err < 0) 1002a74a8216STakashi Iwai goto error; 1003a74a8216STakashi Iwai apply_dac_volume = err > 0; /* need to restore volume later? */ 10041da177e4SLinus Torvalds } 1005a74a8216STakashi Iwai 1006a74a8216STakashi Iwai err = snd_rme96_playback_setformat(rme96, params_format(params)); 1007a74a8216STakashi Iwai if (err < 0) 1008a74a8216STakashi Iwai goto error; 10091da177e4SLinus Torvalds snd_rme96_setframelog(rme96, params_channels(params), 1); 10101da177e4SLinus Torvalds if (rme96->capture_periodsize != 0) { 10111da177e4SLinus Torvalds if (params_period_size(params) << rme96->playback_frlog != 10121da177e4SLinus Torvalds rme96->capture_periodsize) 10131da177e4SLinus Torvalds { 1014a74a8216STakashi Iwai err = -EBUSY; 1015a74a8216STakashi Iwai goto error; 10161da177e4SLinus Torvalds } 10171da177e4SLinus Torvalds } 10181da177e4SLinus Torvalds rme96->playback_periodsize = 10191da177e4SLinus Torvalds params_period_size(params) << rme96->playback_frlog; 10201da177e4SLinus Torvalds snd_rme96_set_period_properties(rme96, rme96->playback_periodsize); 10211da177e4SLinus Torvalds /* S/PDIF setup */ 10221da177e4SLinus Torvalds if ((rme96->wcreg & RME96_WCR_ADAT) == 0) { 10231da177e4SLinus Torvalds rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); 10241da177e4SLinus Torvalds writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER); 10251da177e4SLinus Torvalds } 10261da177e4SLinus Torvalds 1027a74a8216STakashi Iwai err = 0; 1028a74a8216STakashi Iwai error: 1029a74a8216STakashi Iwai spin_unlock_irq(&rme96->lock); 1030a74a8216STakashi Iwai if (apply_dac_volume) { 1031a74a8216STakashi Iwai usleep_range(3000, 10000); 1032a74a8216STakashi Iwai snd_rme96_apply_dac_volume(rme96); 1033a74a8216STakashi Iwai } 1034a74a8216STakashi Iwai 1035a74a8216STakashi Iwai return err; 10361da177e4SLinus Torvalds } 10371da177e4SLinus Torvalds 10381da177e4SLinus Torvalds static int 1039a3aefd88STakashi Iwai snd_rme96_capture_hw_params(struct snd_pcm_substream *substream, 1040a3aefd88STakashi Iwai struct snd_pcm_hw_params *params) 10411da177e4SLinus Torvalds { 1042a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1043a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 10441da177e4SLinus Torvalds int err, isadat, rate; 10451da177e4SLinus Torvalds 10464d23359bSClemens Ladisch runtime->dma_area = (void __force *)(rme96->iobase + 10474d23359bSClemens Ladisch RME96_IO_REC_BUFFER); 10481da177e4SLinus Torvalds runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER; 10491da177e4SLinus Torvalds runtime->dma_bytes = RME96_BUFFER_SIZE; 10501da177e4SLinus Torvalds 10511da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 1052da8eedb1STakashi Iwai err = snd_rme96_capture_setformat(rme96, params_format(params)); 1053da8eedb1STakashi Iwai if (err < 0) { 10541da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10551da177e4SLinus Torvalds return err; 10561da177e4SLinus Torvalds } 10571da177e4SLinus Torvalds if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { 1058da8eedb1STakashi Iwai err = snd_rme96_capture_analog_setrate(rme96, params_rate(params)); 1059da8eedb1STakashi Iwai if (err < 0) { 10601da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10611da177e4SLinus Torvalds return err; 10621da177e4SLinus Torvalds } 1063da8eedb1STakashi Iwai } else { 1064da8eedb1STakashi Iwai rate = snd_rme96_capture_getrate(rme96, &isadat); 1065da8eedb1STakashi Iwai if (rate > 0) { 10661da177e4SLinus Torvalds if ((int)params_rate(params) != rate) { 10671da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10681da177e4SLinus Torvalds return -EIO; 10691da177e4SLinus Torvalds } 10701da177e4SLinus Torvalds if ((isadat && runtime->hw.channels_min == 2) || 1071da8eedb1STakashi Iwai (!isadat && runtime->hw.channels_min == 8)) { 10721da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10731da177e4SLinus Torvalds return -EIO; 10741da177e4SLinus Torvalds } 10751da177e4SLinus Torvalds } 1076da8eedb1STakashi Iwai } 10771da177e4SLinus Torvalds snd_rme96_setframelog(rme96, params_channels(params), 0); 10781da177e4SLinus Torvalds if (rme96->playback_periodsize != 0) { 10791da177e4SLinus Torvalds if (params_period_size(params) << rme96->capture_frlog != 10801da177e4SLinus Torvalds rme96->playback_periodsize) 10811da177e4SLinus Torvalds { 10821da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10831da177e4SLinus Torvalds return -EBUSY; 10841da177e4SLinus Torvalds } 10851da177e4SLinus Torvalds } 10861da177e4SLinus Torvalds rme96->capture_periodsize = 10871da177e4SLinus Torvalds params_period_size(params) << rme96->capture_frlog; 10881da177e4SLinus Torvalds snd_rme96_set_period_properties(rme96, rme96->capture_periodsize); 10891da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 10901da177e4SLinus Torvalds 10911da177e4SLinus Torvalds return 0; 10921da177e4SLinus Torvalds } 10931da177e4SLinus Torvalds 10941da177e4SLinus Torvalds static void 1095b892ca1cSKnut Petersen snd_rme96_trigger(struct rme96 *rme96, 1096b892ca1cSKnut Petersen int op) 10971da177e4SLinus Torvalds { 1098b892ca1cSKnut Petersen if (op & RME96_TB_RESET_PLAYPOS) 10991da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); 1100b892ca1cSKnut Petersen if (op & RME96_TB_RESET_CAPTUREPOS) 11011da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); 1102b892ca1cSKnut Petersen if (op & RME96_TB_CLEAR_PLAYBACK_IRQ) { 11031da177e4SLinus Torvalds rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 1104b892ca1cSKnut Petersen if (rme96->rcreg & RME96_RCR_IRQ) 11051da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ); 11061da177e4SLinus Torvalds } 1107b892ca1cSKnut Petersen if (op & RME96_TB_CLEAR_CAPTURE_IRQ) { 11081da177e4SLinus Torvalds rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 1109b892ca1cSKnut Petersen if (rme96->rcreg & RME96_RCR_IRQ_2) 11101da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ); 11111da177e4SLinus Torvalds } 1112b892ca1cSKnut Petersen if (op & RME96_TB_START_PLAYBACK) 1113b892ca1cSKnut Petersen rme96->wcreg |= RME96_WCR_START; 1114b892ca1cSKnut Petersen if (op & RME96_TB_STOP_PLAYBACK) 1115b892ca1cSKnut Petersen rme96->wcreg &= ~RME96_WCR_START; 1116b892ca1cSKnut Petersen if (op & RME96_TB_START_CAPTURE) 1117b892ca1cSKnut Petersen rme96->wcreg |= RME96_WCR_START_2; 1118b892ca1cSKnut Petersen if (op & RME96_TB_STOP_CAPTURE) 11191da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_START_2; 11201da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 11211da177e4SLinus Torvalds } 11221da177e4SLinus Torvalds 1123b892ca1cSKnut Petersen 1124b892ca1cSKnut Petersen 11251da177e4SLinus Torvalds static irqreturn_t 11261da177e4SLinus Torvalds snd_rme96_interrupt(int irq, 11277d12e780SDavid Howells void *dev_id) 11281da177e4SLinus Torvalds { 1129a3aefd88STakashi Iwai struct rme96 *rme96 = (struct rme96 *)dev_id; 11301da177e4SLinus Torvalds 11311da177e4SLinus Torvalds rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 11321da177e4SLinus Torvalds /* fastpath out, to ease interrupt sharing */ 11331da177e4SLinus Torvalds if (!((rme96->rcreg & RME96_RCR_IRQ) || 11341da177e4SLinus Torvalds (rme96->rcreg & RME96_RCR_IRQ_2))) 11351da177e4SLinus Torvalds { 11361da177e4SLinus Torvalds return IRQ_NONE; 11371da177e4SLinus Torvalds } 11381da177e4SLinus Torvalds 11391da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_IRQ) { 11401da177e4SLinus Torvalds /* playback */ 11411da177e4SLinus Torvalds snd_pcm_period_elapsed(rme96->playback_substream); 11421da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_CONFIRM_PLAY_IRQ); 11431da177e4SLinus Torvalds } 11441da177e4SLinus Torvalds if (rme96->rcreg & RME96_RCR_IRQ_2) { 11451da177e4SLinus Torvalds /* capture */ 11461da177e4SLinus Torvalds snd_pcm_period_elapsed(rme96->capture_substream); 11471da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_CONFIRM_REC_IRQ); 11481da177e4SLinus Torvalds } 11491da177e4SLinus Torvalds return IRQ_HANDLED; 11501da177e4SLinus Torvalds } 11511da177e4SLinus Torvalds 115284e7b998STakashi Iwai static const unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE }; 11531da177e4SLinus Torvalds 115484e7b998STakashi Iwai static const struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { 11551da177e4SLinus Torvalds .count = ARRAY_SIZE(period_bytes), 11561da177e4SLinus Torvalds .list = period_bytes, 11571da177e4SLinus Torvalds .mask = 0 11581da177e4SLinus Torvalds }; 11591da177e4SLinus Torvalds 11602ce7fb57STakashi Iwai static void 11612ce7fb57STakashi Iwai rme96_set_buffer_size_constraint(struct rme96 *rme96, 11622ce7fb57STakashi Iwai struct snd_pcm_runtime *runtime) 11632ce7fb57STakashi Iwai { 11642ce7fb57STakashi Iwai unsigned int size; 11652ce7fb57STakashi Iwai 11661a8e41efSLars-Peter Clausen snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 11671a8e41efSLars-Peter Clausen RME96_BUFFER_SIZE); 1168da8eedb1STakashi Iwai size = rme96->playback_periodsize; 1169da8eedb1STakashi Iwai if (!size) 1170da8eedb1STakashi Iwai size = rme96->capture_periodsize; 1171da8eedb1STakashi Iwai if (size) 11721a8e41efSLars-Peter Clausen snd_pcm_hw_constraint_single(runtime, 11732ce7fb57STakashi Iwai SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 11741a8e41efSLars-Peter Clausen size); 11752ce7fb57STakashi Iwai else 11762ce7fb57STakashi Iwai snd_pcm_hw_constraint_list(runtime, 0, 11772ce7fb57STakashi Iwai SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 11782ce7fb57STakashi Iwai &hw_constraints_period_bytes); 11792ce7fb57STakashi Iwai } 11802ce7fb57STakashi Iwai 11811da177e4SLinus Torvalds static int 1182a3aefd88STakashi Iwai snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) 11831da177e4SLinus Torvalds { 11841da177e4SLinus Torvalds int rate, dummy; 1185a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1186a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 11871da177e4SLinus Torvalds 1188b892ca1cSKnut Petersen snd_pcm_set_sync(substream); 11891da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 11902cb98d01SMarkus Elfring if (rme96->playback_substream) { 11911da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 11921da177e4SLinus Torvalds return -EBUSY; 11931da177e4SLinus Torvalds } 11941da177e4SLinus Torvalds rme96->wcreg &= ~RME96_WCR_ADAT; 11951da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 11961da177e4SLinus Torvalds rme96->playback_substream = substream; 11971da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 11981da177e4SLinus Torvalds 11991da177e4SLinus Torvalds runtime->hw = snd_rme96_playback_spdif_info; 12001da177e4SLinus Torvalds if (!(rme96->wcreg & RME96_WCR_MASTER) && 1201da8eedb1STakashi Iwai snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) { 1202da8eedb1STakashi Iwai rate = snd_rme96_capture_getrate(rme96, &dummy); 1203da8eedb1STakashi Iwai if (rate > 0) { 12041da177e4SLinus Torvalds /* slave clock */ 1205918f3a0eSClemens Ladisch runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); 12061da177e4SLinus Torvalds runtime->hw.rate_min = rate; 12071da177e4SLinus Torvalds runtime->hw.rate_max = rate; 12081da177e4SLinus Torvalds } 1209da8eedb1STakashi Iwai } 12102ce7fb57STakashi Iwai rme96_set_buffer_size_constraint(rme96, runtime); 12111da177e4SLinus Torvalds 12121da177e4SLinus Torvalds rme96->wcreg_spdif_stream = rme96->wcreg_spdif; 12131da177e4SLinus Torvalds rme96->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; 12141da177e4SLinus Torvalds snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE | 12151da177e4SLinus Torvalds SNDRV_CTL_EVENT_MASK_INFO, &rme96->spdif_ctl->id); 12161da177e4SLinus Torvalds return 0; 12171da177e4SLinus Torvalds } 12181da177e4SLinus Torvalds 12191da177e4SLinus Torvalds static int 1220a3aefd88STakashi Iwai snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) 12211da177e4SLinus Torvalds { 12221da177e4SLinus Torvalds int isadat, rate; 1223a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1224a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 12251da177e4SLinus Torvalds 1226b892ca1cSKnut Petersen snd_pcm_set_sync(substream); 12271da177e4SLinus Torvalds runtime->hw = snd_rme96_capture_spdif_info; 1228da8eedb1STakashi Iwai if (snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) { 1229da8eedb1STakashi Iwai rate = snd_rme96_capture_getrate(rme96, &isadat); 1230da8eedb1STakashi Iwai if (rate > 0) { 1231da8eedb1STakashi Iwai if (isadat) 12321da177e4SLinus Torvalds return -EIO; 1233918f3a0eSClemens Ladisch runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); 12341da177e4SLinus Torvalds runtime->hw.rate_min = rate; 12351da177e4SLinus Torvalds runtime->hw.rate_max = rate; 12361da177e4SLinus Torvalds } 1237da8eedb1STakashi Iwai } 12381da177e4SLinus Torvalds 12391da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 12402cb98d01SMarkus Elfring if (rme96->capture_substream) { 12411da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 12421da177e4SLinus Torvalds return -EBUSY; 12431da177e4SLinus Torvalds } 12441da177e4SLinus Torvalds rme96->capture_substream = substream; 12451da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 12461da177e4SLinus Torvalds 12472ce7fb57STakashi Iwai rme96_set_buffer_size_constraint(rme96, runtime); 12481da177e4SLinus Torvalds return 0; 12491da177e4SLinus Torvalds } 12501da177e4SLinus Torvalds 12511da177e4SLinus Torvalds static int 1252a3aefd88STakashi Iwai snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) 12531da177e4SLinus Torvalds { 12541da177e4SLinus Torvalds int rate, dummy; 1255a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1256a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 12571da177e4SLinus Torvalds 1258b892ca1cSKnut Petersen snd_pcm_set_sync(substream); 12591da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 12602cb98d01SMarkus Elfring if (rme96->playback_substream) { 12611da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 12621da177e4SLinus Torvalds return -EBUSY; 12631da177e4SLinus Torvalds } 12641da177e4SLinus Torvalds rme96->wcreg |= RME96_WCR_ADAT; 12651da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 12661da177e4SLinus Torvalds rme96->playback_substream = substream; 12671da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 12681da177e4SLinus Torvalds 12691da177e4SLinus Torvalds runtime->hw = snd_rme96_playback_adat_info; 12701da177e4SLinus Torvalds if (!(rme96->wcreg & RME96_WCR_MASTER) && 1271da8eedb1STakashi Iwai snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG) { 1272da8eedb1STakashi Iwai rate = snd_rme96_capture_getrate(rme96, &dummy); 1273da8eedb1STakashi Iwai if (rate > 0) { 12741da177e4SLinus Torvalds /* slave clock */ 1275918f3a0eSClemens Ladisch runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); 12761da177e4SLinus Torvalds runtime->hw.rate_min = rate; 12771da177e4SLinus Torvalds runtime->hw.rate_max = rate; 12781da177e4SLinus Torvalds } 1279da8eedb1STakashi Iwai } 1280da8eedb1STakashi Iwai 12812ce7fb57STakashi Iwai rme96_set_buffer_size_constraint(rme96, runtime); 12821da177e4SLinus Torvalds return 0; 12831da177e4SLinus Torvalds } 12841da177e4SLinus Torvalds 12851da177e4SLinus Torvalds static int 1286a3aefd88STakashi Iwai snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) 12871da177e4SLinus Torvalds { 12881da177e4SLinus Torvalds int isadat, rate; 1289a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1290a3aefd88STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime; 12911da177e4SLinus Torvalds 1292b892ca1cSKnut Petersen snd_pcm_set_sync(substream); 12931da177e4SLinus Torvalds runtime->hw = snd_rme96_capture_adat_info; 12941da177e4SLinus Torvalds if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { 12951da177e4SLinus Torvalds /* makes no sense to use analog input. Note that analog 12961da177e4SLinus Torvalds expension cards AEB4/8-I are RME96_INPUT_INTERNAL */ 12971da177e4SLinus Torvalds return -EIO; 12981da177e4SLinus Torvalds } 1299da8eedb1STakashi Iwai rate = snd_rme96_capture_getrate(rme96, &isadat); 1300da8eedb1STakashi Iwai if (rate > 0) { 13011da177e4SLinus Torvalds if (!isadat) { 13021da177e4SLinus Torvalds return -EIO; 13031da177e4SLinus Torvalds } 1304918f3a0eSClemens Ladisch runtime->hw.rates = snd_pcm_rate_to_rate_bit(rate); 13051da177e4SLinus Torvalds runtime->hw.rate_min = rate; 13061da177e4SLinus Torvalds runtime->hw.rate_max = rate; 13071da177e4SLinus Torvalds } 13081da177e4SLinus Torvalds 13091da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 13102cb98d01SMarkus Elfring if (rme96->capture_substream) { 13111da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 13121da177e4SLinus Torvalds return -EBUSY; 13131da177e4SLinus Torvalds } 13141da177e4SLinus Torvalds rme96->capture_substream = substream; 13151da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 13161da177e4SLinus Torvalds 13172ce7fb57STakashi Iwai rme96_set_buffer_size_constraint(rme96, runtime); 13181da177e4SLinus Torvalds return 0; 13191da177e4SLinus Torvalds } 13201da177e4SLinus Torvalds 13211da177e4SLinus Torvalds static int 1322a3aefd88STakashi Iwai snd_rme96_playback_close(struct snd_pcm_substream *substream) 13231da177e4SLinus Torvalds { 1324a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 13251da177e4SLinus Torvalds int spdif = 0; 13261da177e4SLinus Torvalds 13271da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 13281da177e4SLinus Torvalds if (RME96_ISPLAYING(rme96)) { 1329b892ca1cSKnut Petersen snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK); 13301da177e4SLinus Torvalds } 13311da177e4SLinus Torvalds rme96->playback_substream = NULL; 13321da177e4SLinus Torvalds rme96->playback_periodsize = 0; 13331da177e4SLinus Torvalds spdif = (rme96->wcreg & RME96_WCR_ADAT) == 0; 13341da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 13351da177e4SLinus Torvalds if (spdif) { 13361da177e4SLinus Torvalds rme96->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; 13371da177e4SLinus Torvalds snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE | 13381da177e4SLinus Torvalds SNDRV_CTL_EVENT_MASK_INFO, &rme96->spdif_ctl->id); 13391da177e4SLinus Torvalds } 13401da177e4SLinus Torvalds return 0; 13411da177e4SLinus Torvalds } 13421da177e4SLinus Torvalds 13431da177e4SLinus Torvalds static int 1344a3aefd88STakashi Iwai snd_rme96_capture_close(struct snd_pcm_substream *substream) 13451da177e4SLinus Torvalds { 1346a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 13471da177e4SLinus Torvalds 13481da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 13491da177e4SLinus Torvalds if (RME96_ISRECORDING(rme96)) { 1350b892ca1cSKnut Petersen snd_rme96_trigger(rme96, RME96_STOP_CAPTURE); 13511da177e4SLinus Torvalds } 13521da177e4SLinus Torvalds rme96->capture_substream = NULL; 13531da177e4SLinus Torvalds rme96->capture_periodsize = 0; 13541da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 13551da177e4SLinus Torvalds return 0; 13561da177e4SLinus Torvalds } 13571da177e4SLinus Torvalds 13581da177e4SLinus Torvalds static int 1359a3aefd88STakashi Iwai snd_rme96_playback_prepare(struct snd_pcm_substream *substream) 13601da177e4SLinus Torvalds { 1361a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 13621da177e4SLinus Torvalds 13631da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 13641da177e4SLinus Torvalds if (RME96_ISPLAYING(rme96)) { 1365b892ca1cSKnut Petersen snd_rme96_trigger(rme96, RME96_STOP_PLAYBACK); 13661da177e4SLinus Torvalds } 13671da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); 13681da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 13691da177e4SLinus Torvalds return 0; 13701da177e4SLinus Torvalds } 13711da177e4SLinus Torvalds 13721da177e4SLinus Torvalds static int 1373a3aefd88STakashi Iwai snd_rme96_capture_prepare(struct snd_pcm_substream *substream) 13741da177e4SLinus Torvalds { 1375a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 13761da177e4SLinus Torvalds 13771da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 13781da177e4SLinus Torvalds if (RME96_ISRECORDING(rme96)) { 1379b892ca1cSKnut Petersen snd_rme96_trigger(rme96, RME96_STOP_CAPTURE); 13801da177e4SLinus Torvalds } 13811da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); 13821da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 13831da177e4SLinus Torvalds return 0; 13841da177e4SLinus Torvalds } 13851da177e4SLinus Torvalds 13861da177e4SLinus Torvalds static int 1387a3aefd88STakashi Iwai snd_rme96_playback_trigger(struct snd_pcm_substream *substream, 13881da177e4SLinus Torvalds int cmd) 13891da177e4SLinus Torvalds { 1390a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1391b892ca1cSKnut Petersen struct snd_pcm_substream *s; 1392b892ca1cSKnut Petersen bool sync; 1393b892ca1cSKnut Petersen 1394b892ca1cSKnut Petersen snd_pcm_group_for_each_entry(s, substream) { 1395b892ca1cSKnut Petersen if (snd_pcm_substream_chip(s) == rme96) 1396b892ca1cSKnut Petersen snd_pcm_trigger_done(s, substream); 1397b892ca1cSKnut Petersen } 1398b892ca1cSKnut Petersen 1399b892ca1cSKnut Petersen sync = (rme96->playback_substream && rme96->capture_substream) && 1400b892ca1cSKnut Petersen (rme96->playback_substream->group == 1401b892ca1cSKnut Petersen rme96->capture_substream->group); 14021da177e4SLinus Torvalds 14031da177e4SLinus Torvalds switch (cmd) { 14041da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_START: 14051da177e4SLinus Torvalds if (!RME96_ISPLAYING(rme96)) { 1406b892ca1cSKnut Petersen if (substream != rme96->playback_substream) 14071da177e4SLinus Torvalds return -EBUSY; 1408b892ca1cSKnut Petersen snd_rme96_trigger(rme96, sync ? RME96_START_BOTH 1409b892ca1cSKnut Petersen : RME96_START_PLAYBACK); 14101da177e4SLinus Torvalds } 14111da177e4SLinus Torvalds break; 14121da177e4SLinus Torvalds 1413528ba522SKnut Petersen case SNDRV_PCM_TRIGGER_SUSPEND: 14141da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_STOP: 14151da177e4SLinus Torvalds if (RME96_ISPLAYING(rme96)) { 1416b892ca1cSKnut Petersen if (substream != rme96->playback_substream) 14171da177e4SLinus Torvalds return -EBUSY; 1418b892ca1cSKnut Petersen snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH 1419b892ca1cSKnut Petersen : RME96_STOP_PLAYBACK); 14201da177e4SLinus Torvalds } 14211da177e4SLinus Torvalds break; 14221da177e4SLinus Torvalds 14231da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1424b892ca1cSKnut Petersen if (RME96_ISPLAYING(rme96)) 1425b892ca1cSKnut Petersen snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH 1426b892ca1cSKnut Petersen : RME96_STOP_PLAYBACK); 14271da177e4SLinus Torvalds break; 14281da177e4SLinus Torvalds 1429528ba522SKnut Petersen case SNDRV_PCM_TRIGGER_RESUME: 14301da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 1431b892ca1cSKnut Petersen if (!RME96_ISPLAYING(rme96)) 1432b892ca1cSKnut Petersen snd_rme96_trigger(rme96, sync ? RME96_RESUME_BOTH 1433b892ca1cSKnut Petersen : RME96_RESUME_PLAYBACK); 14341da177e4SLinus Torvalds break; 14351da177e4SLinus Torvalds 14361da177e4SLinus Torvalds default: 14371da177e4SLinus Torvalds return -EINVAL; 14381da177e4SLinus Torvalds } 1439b892ca1cSKnut Petersen 14401da177e4SLinus Torvalds return 0; 14411da177e4SLinus Torvalds } 14421da177e4SLinus Torvalds 14431da177e4SLinus Torvalds static int 1444a3aefd88STakashi Iwai snd_rme96_capture_trigger(struct snd_pcm_substream *substream, 14451da177e4SLinus Torvalds int cmd) 14461da177e4SLinus Torvalds { 1447a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 1448b892ca1cSKnut Petersen struct snd_pcm_substream *s; 1449b892ca1cSKnut Petersen bool sync; 1450b892ca1cSKnut Petersen 1451b892ca1cSKnut Petersen snd_pcm_group_for_each_entry(s, substream) { 1452b892ca1cSKnut Petersen if (snd_pcm_substream_chip(s) == rme96) 1453b892ca1cSKnut Petersen snd_pcm_trigger_done(s, substream); 1454b892ca1cSKnut Petersen } 1455b892ca1cSKnut Petersen 1456b892ca1cSKnut Petersen sync = (rme96->playback_substream && rme96->capture_substream) && 1457b892ca1cSKnut Petersen (rme96->playback_substream->group == 1458b892ca1cSKnut Petersen rme96->capture_substream->group); 14591da177e4SLinus Torvalds 14601da177e4SLinus Torvalds switch (cmd) { 14611da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_START: 14621da177e4SLinus Torvalds if (!RME96_ISRECORDING(rme96)) { 1463b892ca1cSKnut Petersen if (substream != rme96->capture_substream) 14641da177e4SLinus Torvalds return -EBUSY; 1465b892ca1cSKnut Petersen snd_rme96_trigger(rme96, sync ? RME96_START_BOTH 1466b892ca1cSKnut Petersen : RME96_START_CAPTURE); 14671da177e4SLinus Torvalds } 14681da177e4SLinus Torvalds break; 14691da177e4SLinus Torvalds 1470528ba522SKnut Petersen case SNDRV_PCM_TRIGGER_SUSPEND: 14711da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_STOP: 14721da177e4SLinus Torvalds if (RME96_ISRECORDING(rme96)) { 1473b892ca1cSKnut Petersen if (substream != rme96->capture_substream) 14741da177e4SLinus Torvalds return -EBUSY; 1475b892ca1cSKnut Petersen snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH 1476b892ca1cSKnut Petersen : RME96_STOP_CAPTURE); 14771da177e4SLinus Torvalds } 14781da177e4SLinus Torvalds break; 14791da177e4SLinus Torvalds 14801da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 1481b892ca1cSKnut Petersen if (RME96_ISRECORDING(rme96)) 1482b892ca1cSKnut Petersen snd_rme96_trigger(rme96, sync ? RME96_STOP_BOTH 1483b892ca1cSKnut Petersen : RME96_STOP_CAPTURE); 14841da177e4SLinus Torvalds break; 14851da177e4SLinus Torvalds 1486528ba522SKnut Petersen case SNDRV_PCM_TRIGGER_RESUME: 14871da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 1488b892ca1cSKnut Petersen if (!RME96_ISRECORDING(rme96)) 1489b892ca1cSKnut Petersen snd_rme96_trigger(rme96, sync ? RME96_RESUME_BOTH 1490b892ca1cSKnut Petersen : RME96_RESUME_CAPTURE); 14911da177e4SLinus Torvalds break; 14921da177e4SLinus Torvalds 14931da177e4SLinus Torvalds default: 14941da177e4SLinus Torvalds return -EINVAL; 14951da177e4SLinus Torvalds } 14961da177e4SLinus Torvalds 14971da177e4SLinus Torvalds return 0; 14981da177e4SLinus Torvalds } 14991da177e4SLinus Torvalds 15001da177e4SLinus Torvalds static snd_pcm_uframes_t 1501a3aefd88STakashi Iwai snd_rme96_playback_pointer(struct snd_pcm_substream *substream) 15021da177e4SLinus Torvalds { 1503a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 15041da177e4SLinus Torvalds return snd_rme96_playback_ptr(rme96); 15051da177e4SLinus Torvalds } 15061da177e4SLinus Torvalds 15071da177e4SLinus Torvalds static snd_pcm_uframes_t 1508a3aefd88STakashi Iwai snd_rme96_capture_pointer(struct snd_pcm_substream *substream) 15091da177e4SLinus Torvalds { 1510a3aefd88STakashi Iwai struct rme96 *rme96 = snd_pcm_substream_chip(substream); 15111da177e4SLinus Torvalds return snd_rme96_capture_ptr(rme96); 15121da177e4SLinus Torvalds } 15131da177e4SLinus Torvalds 15146769e988SJulia Lawall static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = { 15151da177e4SLinus Torvalds .open = snd_rme96_playback_spdif_open, 15161da177e4SLinus Torvalds .close = snd_rme96_playback_close, 15171da177e4SLinus Torvalds .hw_params = snd_rme96_playback_hw_params, 15181da177e4SLinus Torvalds .prepare = snd_rme96_playback_prepare, 15191da177e4SLinus Torvalds .trigger = snd_rme96_playback_trigger, 15201da177e4SLinus Torvalds .pointer = snd_rme96_playback_pointer, 152153945f5bSTakashi Iwai .copy_user = snd_rme96_playback_copy, 152253945f5bSTakashi Iwai .copy_kernel = snd_rme96_playback_copy_kernel, 152353945f5bSTakashi Iwai .fill_silence = snd_rme96_playback_silence, 15241da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 15251da177e4SLinus Torvalds }; 15261da177e4SLinus Torvalds 15276769e988SJulia Lawall static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = { 15281da177e4SLinus Torvalds .open = snd_rme96_capture_spdif_open, 15291da177e4SLinus Torvalds .close = snd_rme96_capture_close, 15301da177e4SLinus Torvalds .hw_params = snd_rme96_capture_hw_params, 15311da177e4SLinus Torvalds .prepare = snd_rme96_capture_prepare, 15321da177e4SLinus Torvalds .trigger = snd_rme96_capture_trigger, 15331da177e4SLinus Torvalds .pointer = snd_rme96_capture_pointer, 153453945f5bSTakashi Iwai .copy_user = snd_rme96_capture_copy, 153553945f5bSTakashi Iwai .copy_kernel = snd_rme96_capture_copy_kernel, 15361da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 15371da177e4SLinus Torvalds }; 15381da177e4SLinus Torvalds 15396769e988SJulia Lawall static const struct snd_pcm_ops snd_rme96_playback_adat_ops = { 15401da177e4SLinus Torvalds .open = snd_rme96_playback_adat_open, 15411da177e4SLinus Torvalds .close = snd_rme96_playback_close, 15421da177e4SLinus Torvalds .hw_params = snd_rme96_playback_hw_params, 15431da177e4SLinus Torvalds .prepare = snd_rme96_playback_prepare, 15441da177e4SLinus Torvalds .trigger = snd_rme96_playback_trigger, 15451da177e4SLinus Torvalds .pointer = snd_rme96_playback_pointer, 154653945f5bSTakashi Iwai .copy_user = snd_rme96_playback_copy, 154753945f5bSTakashi Iwai .copy_kernel = snd_rme96_playback_copy_kernel, 154853945f5bSTakashi Iwai .fill_silence = snd_rme96_playback_silence, 15491da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 15501da177e4SLinus Torvalds }; 15511da177e4SLinus Torvalds 15526769e988SJulia Lawall static const struct snd_pcm_ops snd_rme96_capture_adat_ops = { 15531da177e4SLinus Torvalds .open = snd_rme96_capture_adat_open, 15541da177e4SLinus Torvalds .close = snd_rme96_capture_close, 15551da177e4SLinus Torvalds .hw_params = snd_rme96_capture_hw_params, 15561da177e4SLinus Torvalds .prepare = snd_rme96_capture_prepare, 15571da177e4SLinus Torvalds .trigger = snd_rme96_capture_trigger, 15581da177e4SLinus Torvalds .pointer = snd_rme96_capture_pointer, 155953945f5bSTakashi Iwai .copy_user = snd_rme96_capture_copy, 156053945f5bSTakashi Iwai .copy_kernel = snd_rme96_capture_copy_kernel, 15611da177e4SLinus Torvalds .mmap = snd_pcm_lib_mmap_iomem, 15621da177e4SLinus Torvalds }; 15631da177e4SLinus Torvalds 15641da177e4SLinus Torvalds static void 1565*df06df7cSTakashi Iwai snd_rme96_free(struct rme96 *rme96) 15661da177e4SLinus Torvalds { 15671da177e4SLinus Torvalds if (rme96->irq >= 0) { 1568b892ca1cSKnut Petersen snd_rme96_trigger(rme96, RME96_STOP_BOTH); 15691da177e4SLinus Torvalds rme96->areg &= ~RME96_AR_DAC_EN; 15701da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 15711da177e4SLinus Torvalds } 1572a932be91STakashi Iwai #ifdef CONFIG_PM_SLEEP 1573528ba522SKnut Petersen vfree(rme96->playback_suspend_buffer); 1574528ba522SKnut Petersen vfree(rme96->capture_suspend_buffer); 1575528ba522SKnut Petersen #endif 15761da177e4SLinus Torvalds } 15771da177e4SLinus Torvalds 15781da177e4SLinus Torvalds static void 1579a3aefd88STakashi Iwai snd_rme96_free_spdif_pcm(struct snd_pcm *pcm) 15801da177e4SLinus Torvalds { 15819fe856e4SJoe Perches struct rme96 *rme96 = pcm->private_data; 15821da177e4SLinus Torvalds rme96->spdif_pcm = NULL; 15831da177e4SLinus Torvalds } 15841da177e4SLinus Torvalds 15851da177e4SLinus Torvalds static void 1586a3aefd88STakashi Iwai snd_rme96_free_adat_pcm(struct snd_pcm *pcm) 15871da177e4SLinus Torvalds { 15889fe856e4SJoe Perches struct rme96 *rme96 = pcm->private_data; 15891da177e4SLinus Torvalds rme96->adat_pcm = NULL; 15901da177e4SLinus Torvalds } 15911da177e4SLinus Torvalds 1592e23e7a14SBill Pemberton static int 1593a3aefd88STakashi Iwai snd_rme96_create(struct rme96 *rme96) 15941da177e4SLinus Torvalds { 15951da177e4SLinus Torvalds struct pci_dev *pci = rme96->pci; 15961da177e4SLinus Torvalds int err; 15971da177e4SLinus Torvalds 15981da177e4SLinus Torvalds rme96->irq = -1; 15991da177e4SLinus Torvalds spin_lock_init(&rme96->lock); 16001da177e4SLinus Torvalds 1601*df06df7cSTakashi Iwai err = pcim_enable_device(pci); 1602da8eedb1STakashi Iwai if (err < 0) 16031da177e4SLinus Torvalds return err; 16041da177e4SLinus Torvalds 1605da8eedb1STakashi Iwai err = pci_request_regions(pci, "RME96"); 1606da8eedb1STakashi Iwai if (err < 0) 16071da177e4SLinus Torvalds return err; 16081da177e4SLinus Torvalds rme96->port = pci_resource_start(rme96->pci, 0); 16091da177e4SLinus Torvalds 1610*df06df7cSTakashi Iwai rme96->iobase = devm_ioremap(&pci->dev, rme96->port, RME96_IO_SIZE); 161144977b71SHarvey Harrison if (!rme96->iobase) { 1612342cd934STakashi Iwai dev_err(rme96->card->dev, 1613342cd934STakashi Iwai "unable to remap memory region 0x%lx-0x%lx\n", 1614342cd934STakashi Iwai rme96->port, rme96->port + RME96_IO_SIZE - 1); 1615*df06df7cSTakashi Iwai return -EBUSY; 1616688956f2STakashi Iwai } 1617688956f2STakashi Iwai 1618*df06df7cSTakashi Iwai if (devm_request_irq(&pci->dev, pci->irq, snd_rme96_interrupt, 1619*df06df7cSTakashi Iwai IRQF_SHARED, KBUILD_MODNAME, rme96)) { 1620342cd934STakashi Iwai dev_err(rme96->card->dev, "unable to grab IRQ %d\n", pci->irq); 16211da177e4SLinus Torvalds return -EBUSY; 16221da177e4SLinus Torvalds } 16231da177e4SLinus Torvalds rme96->irq = pci->irq; 16245fcf46bcSTakashi Iwai rme96->card->sync_irq = rme96->irq; 16251da177e4SLinus Torvalds 16261da177e4SLinus Torvalds /* read the card's revision number */ 16271da177e4SLinus Torvalds pci_read_config_byte(pci, 8, &rme96->rev); 16281da177e4SLinus Torvalds 16291da177e4SLinus Torvalds /* set up ALSA pcm device for S/PDIF */ 1630da8eedb1STakashi Iwai err = snd_pcm_new(rme96->card, "Digi96 IEC958", 0, 1631da8eedb1STakashi Iwai 1, 1, &rme96->spdif_pcm); 1632da8eedb1STakashi Iwai if (err < 0) 16331da177e4SLinus Torvalds return err; 1634da8eedb1STakashi Iwai 16351da177e4SLinus Torvalds rme96->spdif_pcm->private_data = rme96; 16361da177e4SLinus Torvalds rme96->spdif_pcm->private_free = snd_rme96_free_spdif_pcm; 16371da177e4SLinus Torvalds strcpy(rme96->spdif_pcm->name, "Digi96 IEC958"); 16381da177e4SLinus Torvalds snd_pcm_set_ops(rme96->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme96_playback_spdif_ops); 16391da177e4SLinus Torvalds snd_pcm_set_ops(rme96->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_spdif_ops); 16401da177e4SLinus Torvalds 16411da177e4SLinus Torvalds rme96->spdif_pcm->info_flags = 0; 16421da177e4SLinus Torvalds 16431da177e4SLinus Torvalds /* set up ALSA pcm device for ADAT */ 16448b7fc421SRoland Dreier if (pci->device == PCI_DEVICE_ID_RME_DIGI96) { 16451da177e4SLinus Torvalds /* ADAT is not available on the base model */ 16461da177e4SLinus Torvalds rme96->adat_pcm = NULL; 16471da177e4SLinus Torvalds } else { 1648da8eedb1STakashi Iwai err = snd_pcm_new(rme96->card, "Digi96 ADAT", 1, 1649da8eedb1STakashi Iwai 1, 1, &rme96->adat_pcm); 1650da8eedb1STakashi Iwai if (err < 0) 16511da177e4SLinus Torvalds return err; 16521da177e4SLinus Torvalds rme96->adat_pcm->private_data = rme96; 16531da177e4SLinus Torvalds rme96->adat_pcm->private_free = snd_rme96_free_adat_pcm; 16541da177e4SLinus Torvalds strcpy(rme96->adat_pcm->name, "Digi96 ADAT"); 16551da177e4SLinus Torvalds snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme96_playback_adat_ops); 16561da177e4SLinus Torvalds snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_adat_ops); 16571da177e4SLinus Torvalds 16581da177e4SLinus Torvalds rme96->adat_pcm->info_flags = 0; 16591da177e4SLinus Torvalds } 16601da177e4SLinus Torvalds 16611da177e4SLinus Torvalds rme96->playback_periodsize = 0; 16621da177e4SLinus Torvalds rme96->capture_periodsize = 0; 16631da177e4SLinus Torvalds 16641da177e4SLinus Torvalds /* make sure playback/capture is stopped, if by some reason active */ 1665b892ca1cSKnut Petersen snd_rme96_trigger(rme96, RME96_STOP_BOTH); 16661da177e4SLinus Torvalds 16671da177e4SLinus Torvalds /* set default values in registers */ 16681da177e4SLinus Torvalds rme96->wcreg = 16691da177e4SLinus Torvalds RME96_WCR_FREQ_1 | /* set 44.1 kHz playback */ 16701da177e4SLinus Torvalds RME96_WCR_SEL | /* normal playback */ 16711da177e4SLinus Torvalds RME96_WCR_MASTER | /* set to master clock mode */ 16721da177e4SLinus Torvalds RME96_WCR_INP_0; /* set coaxial input */ 16731da177e4SLinus Torvalds 16741da177e4SLinus Torvalds rme96->areg = RME96_AR_FREQPAD_1; /* set 44.1 kHz analog capture */ 16751da177e4SLinus Torvalds 16761da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 16771da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 16781da177e4SLinus Torvalds 16791da177e4SLinus Torvalds /* reset the ADC */ 16801da177e4SLinus Torvalds writel(rme96->areg | RME96_AR_PD2, 16811da177e4SLinus Torvalds rme96->iobase + RME96_IO_ADDITIONAL_REG); 16821da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 16831da177e4SLinus Torvalds 16841da177e4SLinus Torvalds /* reset and enable the DAC (order is important). */ 16851da177e4SLinus Torvalds snd_rme96_reset_dac(rme96); 16861da177e4SLinus Torvalds rme96->areg |= RME96_AR_DAC_EN; 16871da177e4SLinus Torvalds writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 16881da177e4SLinus Torvalds 16891da177e4SLinus Torvalds /* reset playback and record buffer pointers */ 16901da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS); 16911da177e4SLinus Torvalds writel(0, rme96->iobase + RME96_IO_RESET_REC_POS); 16921da177e4SLinus Torvalds 16931da177e4SLinus Torvalds /* reset volume */ 16941da177e4SLinus Torvalds rme96->vol[0] = rme96->vol[1] = 0; 16951da177e4SLinus Torvalds if (RME96_HAS_ANALOG_OUT(rme96)) { 16961da177e4SLinus Torvalds snd_rme96_apply_dac_volume(rme96); 16971da177e4SLinus Torvalds } 16981da177e4SLinus Torvalds 16991da177e4SLinus Torvalds /* init switch interface */ 1700da8eedb1STakashi Iwai err = snd_rme96_create_switches(rme96->card, rme96); 1701da8eedb1STakashi Iwai if (err < 0) 17021da177e4SLinus Torvalds return err; 17031da177e4SLinus Torvalds 17041da177e4SLinus Torvalds /* init proc interface */ 17051da177e4SLinus Torvalds snd_rme96_proc_init(rme96); 17061da177e4SLinus Torvalds 17071da177e4SLinus Torvalds return 0; 17081da177e4SLinus Torvalds } 17091da177e4SLinus Torvalds 17101da177e4SLinus Torvalds /* 17111da177e4SLinus Torvalds * proc interface 17121da177e4SLinus Torvalds */ 17131da177e4SLinus Torvalds 17141da177e4SLinus Torvalds static void 1715a3aefd88STakashi Iwai snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 17161da177e4SLinus Torvalds { 17171da177e4SLinus Torvalds int n; 17189fe856e4SJoe Perches struct rme96 *rme96 = entry->private_data; 17191da177e4SLinus Torvalds 17201da177e4SLinus Torvalds rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 17211da177e4SLinus Torvalds 17221da177e4SLinus Torvalds snd_iprintf(buffer, rme96->card->longname); 17231da177e4SLinus Torvalds snd_iprintf(buffer, " (index #%d)\n", rme96->card->number + 1); 17241da177e4SLinus Torvalds 17251da177e4SLinus Torvalds snd_iprintf(buffer, "\nGeneral settings\n"); 17261da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_IDIS) { 17271da177e4SLinus Torvalds snd_iprintf(buffer, " period size: N/A (interrupts " 17281da177e4SLinus Torvalds "disabled)\n"); 17291da177e4SLinus Torvalds } else if (rme96->wcreg & RME96_WCR_ISEL) { 17301da177e4SLinus Torvalds snd_iprintf(buffer, " period size: 2048 bytes\n"); 17311da177e4SLinus Torvalds } else { 17321da177e4SLinus Torvalds snd_iprintf(buffer, " period size: 8192 bytes\n"); 17331da177e4SLinus Torvalds } 17341da177e4SLinus Torvalds snd_iprintf(buffer, "\nInput settings\n"); 17351da177e4SLinus Torvalds switch (snd_rme96_getinputtype(rme96)) { 17361da177e4SLinus Torvalds case RME96_INPUT_OPTICAL: 17371da177e4SLinus Torvalds snd_iprintf(buffer, " input: optical"); 17381da177e4SLinus Torvalds break; 17391da177e4SLinus Torvalds case RME96_INPUT_COAXIAL: 17401da177e4SLinus Torvalds snd_iprintf(buffer, " input: coaxial"); 17411da177e4SLinus Torvalds break; 17421da177e4SLinus Torvalds case RME96_INPUT_INTERNAL: 17431da177e4SLinus Torvalds snd_iprintf(buffer, " input: internal"); 17441da177e4SLinus Torvalds break; 17451da177e4SLinus Torvalds case RME96_INPUT_XLR: 17461da177e4SLinus Torvalds snd_iprintf(buffer, " input: XLR"); 17471da177e4SLinus Torvalds break; 17481da177e4SLinus Torvalds case RME96_INPUT_ANALOG: 17491da177e4SLinus Torvalds snd_iprintf(buffer, " input: analog"); 17501da177e4SLinus Torvalds break; 17511da177e4SLinus Torvalds } 17521da177e4SLinus Torvalds if (snd_rme96_capture_getrate(rme96, &n) < 0) { 17531da177e4SLinus Torvalds snd_iprintf(buffer, "\n sample rate: no valid signal\n"); 17541da177e4SLinus Torvalds } else { 17551da177e4SLinus Torvalds if (n) { 17561da177e4SLinus Torvalds snd_iprintf(buffer, " (8 channels)\n"); 17571da177e4SLinus Torvalds } else { 17581da177e4SLinus Torvalds snd_iprintf(buffer, " (2 channels)\n"); 17591da177e4SLinus Torvalds } 17601da177e4SLinus Torvalds snd_iprintf(buffer, " sample rate: %d Hz\n", 17611da177e4SLinus Torvalds snd_rme96_capture_getrate(rme96, &n)); 17621da177e4SLinus Torvalds } 17631da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_MODE24_2) { 17641da177e4SLinus Torvalds snd_iprintf(buffer, " sample format: 24 bit\n"); 17651da177e4SLinus Torvalds } else { 17661da177e4SLinus Torvalds snd_iprintf(buffer, " sample format: 16 bit\n"); 17671da177e4SLinus Torvalds } 17681da177e4SLinus Torvalds 17691da177e4SLinus Torvalds snd_iprintf(buffer, "\nOutput settings\n"); 17701da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_SEL) { 17711da177e4SLinus Torvalds snd_iprintf(buffer, " output signal: normal playback\n"); 17721da177e4SLinus Torvalds } else { 17731da177e4SLinus Torvalds snd_iprintf(buffer, " output signal: same as input\n"); 17741da177e4SLinus Torvalds } 17751da177e4SLinus Torvalds snd_iprintf(buffer, " sample rate: %d Hz\n", 17761da177e4SLinus Torvalds snd_rme96_playback_getrate(rme96)); 17771da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_MODE24) { 17781da177e4SLinus Torvalds snd_iprintf(buffer, " sample format: 24 bit\n"); 17791da177e4SLinus Torvalds } else { 17801da177e4SLinus Torvalds snd_iprintf(buffer, " sample format: 16 bit\n"); 17811da177e4SLinus Torvalds } 17821da177e4SLinus Torvalds if (rme96->areg & RME96_AR_WSEL) { 17831da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: word clock\n"); 17841da177e4SLinus Torvalds } else if (rme96->wcreg & RME96_WCR_MASTER) { 17851da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: internal\n"); 17861da177e4SLinus Torvalds } else if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) { 17871da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: autosync (internal anyway due to analog input setting)\n"); 17881da177e4SLinus Torvalds } else if (snd_rme96_capture_getrate(rme96, &n) < 0) { 17891da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: autosync (internal anyway due to no valid signal)\n"); 17901da177e4SLinus Torvalds } else { 17911da177e4SLinus Torvalds snd_iprintf(buffer, " sample clock source: autosync\n"); 17921da177e4SLinus Torvalds } 17931da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_PRO) { 17941da177e4SLinus Torvalds snd_iprintf(buffer, " format: AES/EBU (professional)\n"); 17951da177e4SLinus Torvalds } else { 17961da177e4SLinus Torvalds snd_iprintf(buffer, " format: IEC958 (consumer)\n"); 17971da177e4SLinus Torvalds } 17981da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_EMP) { 17991da177e4SLinus Torvalds snd_iprintf(buffer, " emphasis: on\n"); 18001da177e4SLinus Torvalds } else { 18011da177e4SLinus Torvalds snd_iprintf(buffer, " emphasis: off\n"); 18021da177e4SLinus Torvalds } 18031da177e4SLinus Torvalds if (rme96->wcreg & RME96_WCR_DOLBY) { 18041da177e4SLinus Torvalds snd_iprintf(buffer, " non-audio (dolby): on\n"); 18051da177e4SLinus Torvalds } else { 18061da177e4SLinus Torvalds snd_iprintf(buffer, " non-audio (dolby): off\n"); 18071da177e4SLinus Torvalds } 18081da177e4SLinus Torvalds if (RME96_HAS_ANALOG_IN(rme96)) { 18091da177e4SLinus Torvalds snd_iprintf(buffer, "\nAnalog output settings\n"); 18101da177e4SLinus Torvalds switch (snd_rme96_getmontracks(rme96)) { 18111da177e4SLinus Torvalds case RME96_MONITOR_TRACKS_1_2: 18121da177e4SLinus Torvalds snd_iprintf(buffer, " monitored ADAT tracks: 1+2\n"); 18131da177e4SLinus Torvalds break; 18141da177e4SLinus Torvalds case RME96_MONITOR_TRACKS_3_4: 18151da177e4SLinus Torvalds snd_iprintf(buffer, " monitored ADAT tracks: 3+4\n"); 18161da177e4SLinus Torvalds break; 18171da177e4SLinus Torvalds case RME96_MONITOR_TRACKS_5_6: 18181da177e4SLinus Torvalds snd_iprintf(buffer, " monitored ADAT tracks: 5+6\n"); 18191da177e4SLinus Torvalds break; 18201da177e4SLinus Torvalds case RME96_MONITOR_TRACKS_7_8: 18211da177e4SLinus Torvalds snd_iprintf(buffer, " monitored ADAT tracks: 7+8\n"); 18221da177e4SLinus Torvalds break; 18231da177e4SLinus Torvalds } 18241da177e4SLinus Torvalds switch (snd_rme96_getattenuation(rme96)) { 18251da177e4SLinus Torvalds case RME96_ATTENUATION_0: 18261da177e4SLinus Torvalds snd_iprintf(buffer, " attenuation: 0 dB\n"); 18271da177e4SLinus Torvalds break; 18281da177e4SLinus Torvalds case RME96_ATTENUATION_6: 18291da177e4SLinus Torvalds snd_iprintf(buffer, " attenuation: -6 dB\n"); 18301da177e4SLinus Torvalds break; 18311da177e4SLinus Torvalds case RME96_ATTENUATION_12: 18321da177e4SLinus Torvalds snd_iprintf(buffer, " attenuation: -12 dB\n"); 18331da177e4SLinus Torvalds break; 18341da177e4SLinus Torvalds case RME96_ATTENUATION_18: 18351da177e4SLinus Torvalds snd_iprintf(buffer, " attenuation: -18 dB\n"); 18361da177e4SLinus Torvalds break; 18371da177e4SLinus Torvalds } 18381da177e4SLinus Torvalds snd_iprintf(buffer, " volume left: %u\n", rme96->vol[0]); 18391da177e4SLinus Torvalds snd_iprintf(buffer, " volume right: %u\n", rme96->vol[1]); 18401da177e4SLinus Torvalds } 18411da177e4SLinus Torvalds } 18421da177e4SLinus Torvalds 1843e23e7a14SBill Pemberton static void snd_rme96_proc_init(struct rme96 *rme96) 18441da177e4SLinus Torvalds { 184547f2769bSTakashi Iwai snd_card_ro_proc_new(rme96->card, "rme96", rme96, snd_rme96_proc_read); 18461da177e4SLinus Torvalds } 18471da177e4SLinus Torvalds 18481da177e4SLinus Torvalds /* 18491da177e4SLinus Torvalds * control interface 18501da177e4SLinus Torvalds */ 18511da177e4SLinus Torvalds 1852a5ce8890STakashi Iwai #define snd_rme96_info_loopback_control snd_ctl_boolean_mono_info 1853a5ce8890STakashi Iwai 18541da177e4SLinus Torvalds static int 1855a3aefd88STakashi Iwai snd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 18561da177e4SLinus Torvalds { 1857a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 18581da177e4SLinus Torvalds 18591da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 18601da177e4SLinus Torvalds ucontrol->value.integer.value[0] = rme96->wcreg & RME96_WCR_SEL ? 0 : 1; 18611da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 18621da177e4SLinus Torvalds return 0; 18631da177e4SLinus Torvalds } 18641da177e4SLinus Torvalds static int 1865a3aefd88STakashi Iwai snd_rme96_put_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 18661da177e4SLinus Torvalds { 1867a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 18681da177e4SLinus Torvalds unsigned int val; 18691da177e4SLinus Torvalds int change; 18701da177e4SLinus Torvalds 18711da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] ? 0 : RME96_WCR_SEL; 18721da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 18731da177e4SLinus Torvalds val = (rme96->wcreg & ~RME96_WCR_SEL) | val; 18741da177e4SLinus Torvalds change = val != rme96->wcreg; 18751da177e4SLinus Torvalds rme96->wcreg = val; 18761da177e4SLinus Torvalds writel(val, rme96->iobase + RME96_IO_CONTROL_REGISTER); 18771da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 18781da177e4SLinus Torvalds return change; 18791da177e4SLinus Torvalds } 18801da177e4SLinus Torvalds 18811da177e4SLinus Torvalds static int 1882a3aefd88STakashi Iwai snd_rme96_info_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 18831da177e4SLinus Torvalds { 18849c30d46aSTakashi Iwai static const char * const _texts[5] = { 18859c30d46aSTakashi Iwai "Optical", "Coaxial", "Internal", "XLR", "Analog" 18869c30d46aSTakashi Iwai }; 1887a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 18889c30d46aSTakashi Iwai const char *texts[5] = { 18899c30d46aSTakashi Iwai _texts[0], _texts[1], _texts[2], _texts[3], _texts[4] 18909c30d46aSTakashi Iwai }; 18919c30d46aSTakashi Iwai int num_items; 18921da177e4SLinus Torvalds 18931da177e4SLinus Torvalds switch (rme96->pci->device) { 18948b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96: 18958b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8: 18969c30d46aSTakashi Iwai num_items = 3; 18971da177e4SLinus Torvalds break; 18988b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PRO: 18999c30d46aSTakashi Iwai num_items = 4; 19001da177e4SLinus Torvalds break; 19018b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: 19021da177e4SLinus Torvalds if (rme96->rev > 4) { 19031da177e4SLinus Torvalds /* PST */ 19049c30d46aSTakashi Iwai num_items = 4; 19051da177e4SLinus Torvalds texts[3] = _texts[4]; /* Analog instead of XLR */ 19061da177e4SLinus Torvalds } else { 19071da177e4SLinus Torvalds /* PAD */ 19089c30d46aSTakashi Iwai num_items = 5; 19091da177e4SLinus Torvalds } 19101da177e4SLinus Torvalds break; 19111da177e4SLinus Torvalds default: 19121da177e4SLinus Torvalds snd_BUG(); 19139c30d46aSTakashi Iwai return -EINVAL; 19141da177e4SLinus Torvalds } 19159c30d46aSTakashi Iwai return snd_ctl_enum_info(uinfo, 1, num_items, texts); 19161da177e4SLinus Torvalds } 19171da177e4SLinus Torvalds static int 1918a3aefd88STakashi Iwai snd_rme96_get_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 19191da177e4SLinus Torvalds { 1920a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 19211da177e4SLinus Torvalds unsigned int items = 3; 19221da177e4SLinus Torvalds 19231da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 19241da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96); 19251da177e4SLinus Torvalds 19261da177e4SLinus Torvalds switch (rme96->pci->device) { 19278b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96: 19288b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8: 19291da177e4SLinus Torvalds items = 3; 19301da177e4SLinus Torvalds break; 19318b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PRO: 19321da177e4SLinus Torvalds items = 4; 19331da177e4SLinus Torvalds break; 19348b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: 19351da177e4SLinus Torvalds if (rme96->rev > 4) { 19361da177e4SLinus Torvalds /* for handling PST case, (INPUT_ANALOG is moved to INPUT_XLR */ 19371da177e4SLinus Torvalds if (ucontrol->value.enumerated.item[0] == RME96_INPUT_ANALOG) { 19381da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = RME96_INPUT_XLR; 19391da177e4SLinus Torvalds } 19401da177e4SLinus Torvalds items = 4; 19411da177e4SLinus Torvalds } else { 19421da177e4SLinus Torvalds items = 5; 19431da177e4SLinus Torvalds } 19441da177e4SLinus Torvalds break; 19451da177e4SLinus Torvalds default: 19461da177e4SLinus Torvalds snd_BUG(); 19471da177e4SLinus Torvalds break; 19481da177e4SLinus Torvalds } 19491da177e4SLinus Torvalds if (ucontrol->value.enumerated.item[0] >= items) { 19501da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = items - 1; 19511da177e4SLinus Torvalds } 19521da177e4SLinus Torvalds 19531da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 19541da177e4SLinus Torvalds return 0; 19551da177e4SLinus Torvalds } 19561da177e4SLinus Torvalds static int 1957a3aefd88STakashi Iwai snd_rme96_put_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 19581da177e4SLinus Torvalds { 1959a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 19601da177e4SLinus Torvalds unsigned int val; 19611da177e4SLinus Torvalds int change, items = 3; 19621da177e4SLinus Torvalds 19631da177e4SLinus Torvalds switch (rme96->pci->device) { 19648b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96: 19658b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8: 19661da177e4SLinus Torvalds items = 3; 19671da177e4SLinus Torvalds break; 19688b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PRO: 19691da177e4SLinus Torvalds items = 4; 19701da177e4SLinus Torvalds break; 19718b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: 19721da177e4SLinus Torvalds if (rme96->rev > 4) { 19731da177e4SLinus Torvalds items = 4; 19741da177e4SLinus Torvalds } else { 19751da177e4SLinus Torvalds items = 5; 19761da177e4SLinus Torvalds } 19771da177e4SLinus Torvalds break; 19781da177e4SLinus Torvalds default: 19791da177e4SLinus Torvalds snd_BUG(); 19801da177e4SLinus Torvalds break; 19811da177e4SLinus Torvalds } 19821da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % items; 19831da177e4SLinus Torvalds 19841da177e4SLinus Torvalds /* special case for PST */ 19858b7fc421SRoland Dreier if (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && rme96->rev > 4) { 19861da177e4SLinus Torvalds if (val == RME96_INPUT_XLR) { 19871da177e4SLinus Torvalds val = RME96_INPUT_ANALOG; 19881da177e4SLinus Torvalds } 19891da177e4SLinus Torvalds } 19901da177e4SLinus Torvalds 19911da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 19921da177e4SLinus Torvalds change = (int)val != snd_rme96_getinputtype(rme96); 19931da177e4SLinus Torvalds snd_rme96_setinputtype(rme96, val); 19941da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 19951da177e4SLinus Torvalds return change; 19961da177e4SLinus Torvalds } 19971da177e4SLinus Torvalds 19981da177e4SLinus Torvalds static int 1999a3aefd88STakashi Iwai snd_rme96_info_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 20001da177e4SLinus Torvalds { 20019c30d46aSTakashi Iwai static const char * const texts[3] = { "AutoSync", "Internal", "Word" }; 20021da177e4SLinus Torvalds 20039c30d46aSTakashi Iwai return snd_ctl_enum_info(uinfo, 1, 3, texts); 20041da177e4SLinus Torvalds } 20051da177e4SLinus Torvalds static int 2006a3aefd88STakashi Iwai snd_rme96_get_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 20071da177e4SLinus Torvalds { 2008a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 20091da177e4SLinus Torvalds 20101da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20111da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = snd_rme96_getclockmode(rme96); 20121da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20131da177e4SLinus Torvalds return 0; 20141da177e4SLinus Torvalds } 20151da177e4SLinus Torvalds static int 2016a3aefd88STakashi Iwai snd_rme96_put_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 20171da177e4SLinus Torvalds { 2018a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 20191da177e4SLinus Torvalds unsigned int val; 20201da177e4SLinus Torvalds int change; 20211da177e4SLinus Torvalds 20221da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % 3; 20231da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20241da177e4SLinus Torvalds change = (int)val != snd_rme96_getclockmode(rme96); 20251da177e4SLinus Torvalds snd_rme96_setclockmode(rme96, val); 20261da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20271da177e4SLinus Torvalds return change; 20281da177e4SLinus Torvalds } 20291da177e4SLinus Torvalds 20301da177e4SLinus Torvalds static int 2031a3aefd88STakashi Iwai snd_rme96_info_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 20321da177e4SLinus Torvalds { 20339c30d46aSTakashi Iwai static const char * const texts[4] = { 20349c30d46aSTakashi Iwai "0 dB", "-6 dB", "-12 dB", "-18 dB" 20359c30d46aSTakashi Iwai }; 20361da177e4SLinus Torvalds 20379c30d46aSTakashi Iwai return snd_ctl_enum_info(uinfo, 1, 4, texts); 20381da177e4SLinus Torvalds } 20391da177e4SLinus Torvalds static int 2040a3aefd88STakashi Iwai snd_rme96_get_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 20411da177e4SLinus Torvalds { 2042a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 20431da177e4SLinus Torvalds 20441da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20451da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = snd_rme96_getattenuation(rme96); 20461da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20471da177e4SLinus Torvalds return 0; 20481da177e4SLinus Torvalds } 20491da177e4SLinus Torvalds static int 2050a3aefd88STakashi Iwai snd_rme96_put_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 20511da177e4SLinus Torvalds { 2052a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 20531da177e4SLinus Torvalds unsigned int val; 20541da177e4SLinus Torvalds int change; 20551da177e4SLinus Torvalds 20561da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % 4; 20571da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20581da177e4SLinus Torvalds 20591da177e4SLinus Torvalds change = (int)val != snd_rme96_getattenuation(rme96); 20601da177e4SLinus Torvalds snd_rme96_setattenuation(rme96, val); 20611da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20621da177e4SLinus Torvalds return change; 20631da177e4SLinus Torvalds } 20641da177e4SLinus Torvalds 20651da177e4SLinus Torvalds static int 2066a3aefd88STakashi Iwai snd_rme96_info_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 20671da177e4SLinus Torvalds { 20689c30d46aSTakashi Iwai static const char * const texts[4] = { "1+2", "3+4", "5+6", "7+8" }; 20691da177e4SLinus Torvalds 20709c30d46aSTakashi Iwai return snd_ctl_enum_info(uinfo, 1, 4, texts); 20711da177e4SLinus Torvalds } 20721da177e4SLinus Torvalds static int 2073a3aefd88STakashi Iwai snd_rme96_get_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 20771da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20781da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = snd_rme96_getmontracks(rme96); 20791da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20801da177e4SLinus Torvalds return 0; 20811da177e4SLinus Torvalds } 20821da177e4SLinus Torvalds static int 2083a3aefd88STakashi Iwai snd_rme96_put_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 20841da177e4SLinus Torvalds { 2085a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 20861da177e4SLinus Torvalds unsigned int val; 20871da177e4SLinus Torvalds int change; 20881da177e4SLinus Torvalds 20891da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % 4; 20901da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 20911da177e4SLinus Torvalds change = (int)val != snd_rme96_getmontracks(rme96); 20921da177e4SLinus Torvalds snd_rme96_setmontracks(rme96, val); 20931da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 20941da177e4SLinus Torvalds return change; 20951da177e4SLinus Torvalds } 20961da177e4SLinus Torvalds 2097a3aefd88STakashi Iwai static u32 snd_rme96_convert_from_aes(struct snd_aes_iec958 *aes) 20981da177e4SLinus Torvalds { 20991da177e4SLinus Torvalds u32 val = 0; 21001da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME96_WCR_PRO : 0; 21011da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? RME96_WCR_DOLBY : 0; 21021da177e4SLinus Torvalds if (val & RME96_WCR_PRO) 21031da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? RME96_WCR_EMP : 0; 21041da177e4SLinus Torvalds else 21051da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? RME96_WCR_EMP : 0; 21061da177e4SLinus Torvalds return val; 21071da177e4SLinus Torvalds } 21081da177e4SLinus Torvalds 2109a3aefd88STakashi Iwai static void snd_rme96_convert_to_aes(struct snd_aes_iec958 *aes, u32 val) 21101da177e4SLinus Torvalds { 21111da177e4SLinus Torvalds aes->status[0] = ((val & RME96_WCR_PRO) ? IEC958_AES0_PROFESSIONAL : 0) | 21121da177e4SLinus Torvalds ((val & RME96_WCR_DOLBY) ? IEC958_AES0_NONAUDIO : 0); 21131da177e4SLinus Torvalds if (val & RME96_WCR_PRO) 21141da177e4SLinus Torvalds aes->status[0] |= (val & RME96_WCR_EMP) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; 21151da177e4SLinus Torvalds else 21161da177e4SLinus Torvalds aes->status[0] |= (val & RME96_WCR_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0; 21171da177e4SLinus Torvalds } 21181da177e4SLinus Torvalds 2119a3aefd88STakashi Iwai static int snd_rme96_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 21201da177e4SLinus Torvalds { 21211da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 21221da177e4SLinus Torvalds uinfo->count = 1; 21231da177e4SLinus Torvalds return 0; 21241da177e4SLinus Torvalds } 21251da177e4SLinus Torvalds 2126a3aefd88STakashi Iwai static int snd_rme96_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 21271da177e4SLinus Torvalds { 2128a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21291da177e4SLinus Torvalds 21301da177e4SLinus Torvalds snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif); 21311da177e4SLinus Torvalds return 0; 21321da177e4SLinus Torvalds } 21331da177e4SLinus Torvalds 2134a3aefd88STakashi Iwai static int snd_rme96_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 21351da177e4SLinus Torvalds { 2136a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21371da177e4SLinus Torvalds int change; 21381da177e4SLinus Torvalds u32 val; 21391da177e4SLinus Torvalds 21401da177e4SLinus Torvalds val = snd_rme96_convert_from_aes(&ucontrol->value.iec958); 21411da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 21421da177e4SLinus Torvalds change = val != rme96->wcreg_spdif; 21431da177e4SLinus Torvalds rme96->wcreg_spdif = val; 21441da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 21451da177e4SLinus Torvalds return change; 21461da177e4SLinus Torvalds } 21471da177e4SLinus Torvalds 2148a3aefd88STakashi Iwai static int snd_rme96_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 21491da177e4SLinus Torvalds { 21501da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 21511da177e4SLinus Torvalds uinfo->count = 1; 21521da177e4SLinus Torvalds return 0; 21531da177e4SLinus Torvalds } 21541da177e4SLinus Torvalds 2155a3aefd88STakashi Iwai static int snd_rme96_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 21561da177e4SLinus Torvalds { 2157a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21581da177e4SLinus Torvalds 21591da177e4SLinus Torvalds snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif_stream); 21601da177e4SLinus Torvalds return 0; 21611da177e4SLinus Torvalds } 21621da177e4SLinus Torvalds 2163a3aefd88STakashi Iwai static int snd_rme96_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 21641da177e4SLinus Torvalds { 2165a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21661da177e4SLinus Torvalds int change; 21671da177e4SLinus Torvalds u32 val; 21681da177e4SLinus Torvalds 21691da177e4SLinus Torvalds val = snd_rme96_convert_from_aes(&ucontrol->value.iec958); 21701da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 21711da177e4SLinus Torvalds change = val != rme96->wcreg_spdif_stream; 21721da177e4SLinus Torvalds rme96->wcreg_spdif_stream = val; 21731da177e4SLinus Torvalds rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP); 21741da177e4SLinus Torvalds rme96->wcreg |= val; 21751da177e4SLinus Torvalds writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER); 21761da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 21771da177e4SLinus Torvalds return change; 21781da177e4SLinus Torvalds } 21791da177e4SLinus Torvalds 2180a3aefd88STakashi Iwai static int snd_rme96_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 21811da177e4SLinus Torvalds { 21821da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 21831da177e4SLinus Torvalds uinfo->count = 1; 21841da177e4SLinus Torvalds return 0; 21851da177e4SLinus Torvalds } 21861da177e4SLinus Torvalds 2187a3aefd88STakashi Iwai static int snd_rme96_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 21881da177e4SLinus Torvalds { 21891da177e4SLinus Torvalds ucontrol->value.iec958.status[0] = kcontrol->private_value; 21901da177e4SLinus Torvalds return 0; 21911da177e4SLinus Torvalds } 21921da177e4SLinus Torvalds 21931da177e4SLinus Torvalds static int 2194a3aefd88STakashi Iwai snd_rme96_dac_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 21951da177e4SLinus Torvalds { 2196a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 21971da177e4SLinus Torvalds 21981da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 21991da177e4SLinus Torvalds uinfo->count = 2; 22001da177e4SLinus Torvalds uinfo->value.integer.min = 0; 22011da177e4SLinus Torvalds uinfo->value.integer.max = RME96_185X_MAX_OUT(rme96); 22021da177e4SLinus Torvalds return 0; 22031da177e4SLinus Torvalds } 22041da177e4SLinus Torvalds 22051da177e4SLinus Torvalds static int 2206a3aefd88STakashi Iwai snd_rme96_dac_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u) 22071da177e4SLinus Torvalds { 2208a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 22091da177e4SLinus Torvalds 22101da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 22111da177e4SLinus Torvalds u->value.integer.value[0] = rme96->vol[0]; 22121da177e4SLinus Torvalds u->value.integer.value[1] = rme96->vol[1]; 22131da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 22141da177e4SLinus Torvalds 22151da177e4SLinus Torvalds return 0; 22161da177e4SLinus Torvalds } 22171da177e4SLinus Torvalds 22181da177e4SLinus Torvalds static int 2219a3aefd88STakashi Iwai snd_rme96_dac_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u) 22201da177e4SLinus Torvalds { 2221a3aefd88STakashi Iwai struct rme96 *rme96 = snd_kcontrol_chip(kcontrol); 22221da177e4SLinus Torvalds int change = 0; 22234e98d6a7STakashi Iwai unsigned int vol, maxvol; 22241da177e4SLinus Torvalds 22254e98d6a7STakashi Iwai 22264e98d6a7STakashi Iwai if (!RME96_HAS_ANALOG_OUT(rme96)) 22271da177e4SLinus Torvalds return -EINVAL; 22284e98d6a7STakashi Iwai maxvol = RME96_185X_MAX_OUT(rme96); 22291da177e4SLinus Torvalds spin_lock_irq(&rme96->lock); 22304e98d6a7STakashi Iwai vol = u->value.integer.value[0]; 22314e98d6a7STakashi Iwai if (vol != rme96->vol[0] && vol <= maxvol) { 22324e98d6a7STakashi Iwai rme96->vol[0] = vol; 22331da177e4SLinus Torvalds change = 1; 22341da177e4SLinus Torvalds } 22354e98d6a7STakashi Iwai vol = u->value.integer.value[1]; 22364e98d6a7STakashi Iwai if (vol != rme96->vol[1] && vol <= maxvol) { 22374e98d6a7STakashi Iwai rme96->vol[1] = vol; 22381da177e4SLinus Torvalds change = 1; 22391da177e4SLinus Torvalds } 22404e98d6a7STakashi Iwai if (change) 22411da177e4SLinus Torvalds snd_rme96_apply_dac_volume(rme96); 22421da177e4SLinus Torvalds spin_unlock_irq(&rme96->lock); 22431da177e4SLinus Torvalds 22441da177e4SLinus Torvalds return change; 22451da177e4SLinus Torvalds } 22461da177e4SLinus Torvalds 2247b4e5e707STakashi Iwai static const struct snd_kcontrol_new snd_rme96_controls[] = { 22481da177e4SLinus Torvalds { 22491da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 22501da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 22511da177e4SLinus Torvalds .info = snd_rme96_control_spdif_info, 22521da177e4SLinus Torvalds .get = snd_rme96_control_spdif_get, 22531da177e4SLinus Torvalds .put = snd_rme96_control_spdif_put 22541da177e4SLinus Torvalds }, 22551da177e4SLinus Torvalds { 22561da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 22571da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 22581da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), 22591da177e4SLinus Torvalds .info = snd_rme96_control_spdif_stream_info, 22601da177e4SLinus Torvalds .get = snd_rme96_control_spdif_stream_get, 22611da177e4SLinus Torvalds .put = snd_rme96_control_spdif_stream_put 22621da177e4SLinus Torvalds }, 22631da177e4SLinus Torvalds { 22641da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, 226567ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 22661da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), 22671da177e4SLinus Torvalds .info = snd_rme96_control_spdif_mask_info, 22681da177e4SLinus Torvalds .get = snd_rme96_control_spdif_mask_get, 22691da177e4SLinus Torvalds .private_value = IEC958_AES0_NONAUDIO | 22701da177e4SLinus Torvalds IEC958_AES0_PROFESSIONAL | 22711da177e4SLinus Torvalds IEC958_AES0_CON_EMPHASIS 22721da177e4SLinus Torvalds }, 22731da177e4SLinus Torvalds { 22741da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, 227567ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 22761da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), 22771da177e4SLinus Torvalds .info = snd_rme96_control_spdif_mask_info, 22781da177e4SLinus Torvalds .get = snd_rme96_control_spdif_mask_get, 22791da177e4SLinus Torvalds .private_value = IEC958_AES0_NONAUDIO | 22801da177e4SLinus Torvalds IEC958_AES0_PROFESSIONAL | 22811da177e4SLinus Torvalds IEC958_AES0_PRO_EMPHASIS 22821da177e4SLinus Torvalds }, 22831da177e4SLinus Torvalds { 22841da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 22851da177e4SLinus Torvalds .name = "Input Connector", 22861da177e4SLinus Torvalds .info = snd_rme96_info_inputtype_control, 22871da177e4SLinus Torvalds .get = snd_rme96_get_inputtype_control, 22881da177e4SLinus Torvalds .put = snd_rme96_put_inputtype_control 22891da177e4SLinus Torvalds }, 22901da177e4SLinus Torvalds { 22911da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 22921da177e4SLinus Torvalds .name = "Loopback Input", 22931da177e4SLinus Torvalds .info = snd_rme96_info_loopback_control, 22941da177e4SLinus Torvalds .get = snd_rme96_get_loopback_control, 22951da177e4SLinus Torvalds .put = snd_rme96_put_loopback_control 22961da177e4SLinus Torvalds }, 22971da177e4SLinus Torvalds { 22981da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 22991da177e4SLinus Torvalds .name = "Sample Clock Source", 23001da177e4SLinus Torvalds .info = snd_rme96_info_clockmode_control, 23011da177e4SLinus Torvalds .get = snd_rme96_get_clockmode_control, 23021da177e4SLinus Torvalds .put = snd_rme96_put_clockmode_control 23031da177e4SLinus Torvalds }, 23041da177e4SLinus Torvalds { 23051da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 23061da177e4SLinus Torvalds .name = "Monitor Tracks", 23071da177e4SLinus Torvalds .info = snd_rme96_info_montracks_control, 23081da177e4SLinus Torvalds .get = snd_rme96_get_montracks_control, 23091da177e4SLinus Torvalds .put = snd_rme96_put_montracks_control 23101da177e4SLinus Torvalds }, 23111da177e4SLinus Torvalds { 23121da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 23131da177e4SLinus Torvalds .name = "Attenuation", 23141da177e4SLinus Torvalds .info = snd_rme96_info_attenuation_control, 23151da177e4SLinus Torvalds .get = snd_rme96_get_attenuation_control, 23161da177e4SLinus Torvalds .put = snd_rme96_put_attenuation_control 23171da177e4SLinus Torvalds }, 23181da177e4SLinus Torvalds { 23191da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 23201da177e4SLinus Torvalds .name = "DAC Playback Volume", 23211da177e4SLinus Torvalds .info = snd_rme96_dac_volume_info, 23221da177e4SLinus Torvalds .get = snd_rme96_dac_volume_get, 23231da177e4SLinus Torvalds .put = snd_rme96_dac_volume_put 23241da177e4SLinus Torvalds } 23251da177e4SLinus Torvalds }; 23261da177e4SLinus Torvalds 23271da177e4SLinus Torvalds static int 2328a3aefd88STakashi Iwai snd_rme96_create_switches(struct snd_card *card, 2329a3aefd88STakashi Iwai struct rme96 *rme96) 23301da177e4SLinus Torvalds { 23311da177e4SLinus Torvalds int idx, err; 2332a3aefd88STakashi Iwai struct snd_kcontrol *kctl; 23331da177e4SLinus Torvalds 23341da177e4SLinus Torvalds for (idx = 0; idx < 7; idx++) { 2335da8eedb1STakashi Iwai kctl = snd_ctl_new1(&snd_rme96_controls[idx], rme96); 2336da8eedb1STakashi Iwai err = snd_ctl_add(card, kctl); 2337da8eedb1STakashi Iwai if (err < 0) 23381da177e4SLinus Torvalds return err; 23391da177e4SLinus Torvalds if (idx == 1) /* IEC958 (S/PDIF) Stream */ 23401da177e4SLinus Torvalds rme96->spdif_ctl = kctl; 23411da177e4SLinus Torvalds } 23421da177e4SLinus Torvalds 23431da177e4SLinus Torvalds if (RME96_HAS_ANALOG_OUT(rme96)) { 2344da8eedb1STakashi Iwai for (idx = 7; idx < 10; idx++) { 2345da8eedb1STakashi Iwai err = snd_ctl_add(card, snd_ctl_new1(&snd_rme96_controls[idx], rme96)); 2346da8eedb1STakashi Iwai if (err < 0) 23471da177e4SLinus Torvalds return err; 23481da177e4SLinus Torvalds } 2349da8eedb1STakashi Iwai } 23501da177e4SLinus Torvalds 23511da177e4SLinus Torvalds return 0; 23521da177e4SLinus Torvalds } 23531da177e4SLinus Torvalds 23541da177e4SLinus Torvalds /* 23551da177e4SLinus Torvalds * Card initialisation 23561da177e4SLinus Torvalds */ 23571da177e4SLinus Torvalds 2358a932be91STakashi Iwai #ifdef CONFIG_PM_SLEEP 2359528ba522SKnut Petersen 2360a932be91STakashi Iwai static int rme96_suspend(struct device *dev) 2361528ba522SKnut Petersen { 2362a932be91STakashi Iwai struct snd_card *card = dev_get_drvdata(dev); 2363528ba522SKnut Petersen struct rme96 *rme96 = card->private_data; 2364528ba522SKnut Petersen 2365528ba522SKnut Petersen snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 2366528ba522SKnut Petersen 2367528ba522SKnut Petersen /* save capture & playback pointers */ 2368528ba522SKnut Petersen rme96->playback_pointer = readl(rme96->iobase + RME96_IO_GET_PLAY_POS) 2369528ba522SKnut Petersen & RME96_RCR_AUDIO_ADDR_MASK; 2370528ba522SKnut Petersen rme96->capture_pointer = readl(rme96->iobase + RME96_IO_GET_REC_POS) 2371528ba522SKnut Petersen & RME96_RCR_AUDIO_ADDR_MASK; 2372528ba522SKnut Petersen 2373528ba522SKnut Petersen /* save playback and capture buffers */ 2374528ba522SKnut Petersen memcpy_fromio(rme96->playback_suspend_buffer, 2375528ba522SKnut Petersen rme96->iobase + RME96_IO_PLAY_BUFFER, RME96_BUFFER_SIZE); 2376528ba522SKnut Petersen memcpy_fromio(rme96->capture_suspend_buffer, 2377528ba522SKnut Petersen rme96->iobase + RME96_IO_REC_BUFFER, RME96_BUFFER_SIZE); 2378528ba522SKnut Petersen 2379528ba522SKnut Petersen /* disable the DAC */ 2380528ba522SKnut Petersen rme96->areg &= ~RME96_AR_DAC_EN; 2381528ba522SKnut Petersen writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 2382528ba522SKnut Petersen return 0; 2383528ba522SKnut Petersen } 2384528ba522SKnut Petersen 2385a932be91STakashi Iwai static int rme96_resume(struct device *dev) 2386528ba522SKnut Petersen { 2387a932be91STakashi Iwai struct snd_card *card = dev_get_drvdata(dev); 2388528ba522SKnut Petersen struct rme96 *rme96 = card->private_data; 2389528ba522SKnut Petersen 2390528ba522SKnut Petersen /* reset playback and record buffer pointers */ 2391528ba522SKnut Petersen writel(0, rme96->iobase + RME96_IO_SET_PLAY_POS 2392528ba522SKnut Petersen + rme96->playback_pointer); 2393528ba522SKnut Petersen writel(0, rme96->iobase + RME96_IO_SET_REC_POS 2394528ba522SKnut Petersen + rme96->capture_pointer); 2395528ba522SKnut Petersen 2396528ba522SKnut Petersen /* restore playback and capture buffers */ 2397528ba522SKnut Petersen memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER, 2398528ba522SKnut Petersen rme96->playback_suspend_buffer, RME96_BUFFER_SIZE); 2399528ba522SKnut Petersen memcpy_toio(rme96->iobase + RME96_IO_REC_BUFFER, 2400528ba522SKnut Petersen rme96->capture_suspend_buffer, RME96_BUFFER_SIZE); 2401528ba522SKnut Petersen 2402528ba522SKnut Petersen /* reset the ADC */ 2403528ba522SKnut Petersen writel(rme96->areg | RME96_AR_PD2, 2404528ba522SKnut Petersen rme96->iobase + RME96_IO_ADDITIONAL_REG); 2405528ba522SKnut Petersen writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 2406528ba522SKnut Petersen 2407528ba522SKnut Petersen /* reset and enable DAC, restore analog volume */ 2408528ba522SKnut Petersen snd_rme96_reset_dac(rme96); 2409528ba522SKnut Petersen rme96->areg |= RME96_AR_DAC_EN; 2410528ba522SKnut Petersen writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG); 2411528ba522SKnut Petersen if (RME96_HAS_ANALOG_OUT(rme96)) { 2412528ba522SKnut Petersen usleep_range(3000, 10000); 2413528ba522SKnut Petersen snd_rme96_apply_dac_volume(rme96); 2414528ba522SKnut Petersen } 2415528ba522SKnut Petersen 2416528ba522SKnut Petersen snd_power_change_state(card, SNDRV_CTL_POWER_D0); 2417528ba522SKnut Petersen 2418528ba522SKnut Petersen return 0; 2419528ba522SKnut Petersen } 2420528ba522SKnut Petersen 2421a932be91STakashi Iwai static SIMPLE_DEV_PM_OPS(rme96_pm, rme96_suspend, rme96_resume); 2422a932be91STakashi Iwai #define RME96_PM_OPS &rme96_pm 2423a932be91STakashi Iwai #else 2424a932be91STakashi Iwai #define RME96_PM_OPS NULL 2425a932be91STakashi Iwai #endif /* CONFIG_PM_SLEEP */ 2426528ba522SKnut Petersen 2427a3aefd88STakashi Iwai static void snd_rme96_card_free(struct snd_card *card) 24281da177e4SLinus Torvalds { 24291da177e4SLinus Torvalds snd_rme96_free(card->private_data); 24301da177e4SLinus Torvalds } 24311da177e4SLinus Torvalds 2432e23e7a14SBill Pemberton static int 24331da177e4SLinus Torvalds snd_rme96_probe(struct pci_dev *pci, 24341da177e4SLinus Torvalds const struct pci_device_id *pci_id) 24351da177e4SLinus Torvalds { 24361da177e4SLinus Torvalds static int dev; 2437a3aefd88STakashi Iwai struct rme96 *rme96; 2438a3aefd88STakashi Iwai struct snd_card *card; 24391da177e4SLinus Torvalds int err; 24401da177e4SLinus Torvalds u8 val; 24411da177e4SLinus Torvalds 24421da177e4SLinus Torvalds if (dev >= SNDRV_CARDS) { 24431da177e4SLinus Torvalds return -ENODEV; 24441da177e4SLinus Torvalds } 24451da177e4SLinus Torvalds if (!enable[dev]) { 24461da177e4SLinus Torvalds dev++; 24471da177e4SLinus Torvalds return -ENOENT; 24481da177e4SLinus Torvalds } 2449*df06df7cSTakashi Iwai err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 2450*df06df7cSTakashi Iwai sizeof(*rme96), &card); 2451e58de7baSTakashi Iwai if (err < 0) 2452e58de7baSTakashi Iwai return err; 24531da177e4SLinus Torvalds card->private_free = snd_rme96_card_free; 24549fe856e4SJoe Perches rme96 = card->private_data; 24551da177e4SLinus Torvalds rme96->card = card; 24561da177e4SLinus Torvalds rme96->pci = pci; 2457d72a8010SMarkus Elfring err = snd_rme96_create(rme96); 2458d72a8010SMarkus Elfring if (err) 2459*df06df7cSTakashi Iwai return err; 24601da177e4SLinus Torvalds 2461a932be91STakashi Iwai #ifdef CONFIG_PM_SLEEP 2462528ba522SKnut Petersen rme96->playback_suspend_buffer = vmalloc(RME96_BUFFER_SIZE); 2463*df06df7cSTakashi Iwai if (!rme96->playback_suspend_buffer) 2464*df06df7cSTakashi Iwai return -ENOMEM; 2465528ba522SKnut Petersen rme96->capture_suspend_buffer = vmalloc(RME96_BUFFER_SIZE); 2466*df06df7cSTakashi Iwai if (!rme96->capture_suspend_buffer) 2467*df06df7cSTakashi Iwai return -ENOMEM; 2468528ba522SKnut Petersen #endif 2469528ba522SKnut Petersen 24701da177e4SLinus Torvalds strcpy(card->driver, "Digi96"); 24711da177e4SLinus Torvalds switch (rme96->pci->device) { 24728b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96: 24731da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi96"); 24741da177e4SLinus Torvalds break; 24758b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8: 24761da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi96/8"); 24771da177e4SLinus Torvalds break; 24788b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PRO: 24791da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi96/8 PRO"); 24801da177e4SLinus Torvalds break; 24818b7fc421SRoland Dreier case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: 24821da177e4SLinus Torvalds pci_read_config_byte(rme96->pci, 8, &val); 24831da177e4SLinus Torvalds if (val < 5) { 24841da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi96/8 PAD"); 24851da177e4SLinus Torvalds } else { 24861da177e4SLinus Torvalds strcpy(card->shortname, "RME Digi96/8 PST"); 24871da177e4SLinus Torvalds } 24881da177e4SLinus Torvalds break; 24891da177e4SLinus Torvalds } 24901da177e4SLinus Torvalds sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname, 24911da177e4SLinus Torvalds rme96->port, rme96->irq); 2492d72a8010SMarkus Elfring err = snd_card_register(card); 2493d72a8010SMarkus Elfring if (err) 2494*df06df7cSTakashi Iwai return err; 24951da177e4SLinus Torvalds 24961da177e4SLinus Torvalds pci_set_drvdata(pci, card); 24971da177e4SLinus Torvalds dev++; 24981da177e4SLinus Torvalds return 0; 24991da177e4SLinus Torvalds } 25001da177e4SLinus Torvalds 2501e9f66d9bSTakashi Iwai static struct pci_driver rme96_driver = { 25023733e424STakashi Iwai .name = KBUILD_MODNAME, 25031da177e4SLinus Torvalds .id_table = snd_rme96_ids, 25041da177e4SLinus Torvalds .probe = snd_rme96_probe, 2505a932be91STakashi Iwai .driver = { 2506a932be91STakashi Iwai .pm = RME96_PM_OPS, 2507a932be91STakashi Iwai }, 25081da177e4SLinus Torvalds }; 25091da177e4SLinus Torvalds 2510e9f66d9bSTakashi Iwai module_pci_driver(rme96_driver); 2511