11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * ALSA driver for RME Digi9652 audio interfaces
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (c) 1999 IEM - Winfried Ritsch
61da177e4SLinus Torvalds * Copyright (c) 1999-2001 Paul Davis
71da177e4SLinus Torvalds */
81da177e4SLinus Torvalds
91da177e4SLinus Torvalds #include <linux/delay.h>
101da177e4SLinus Torvalds #include <linux/init.h>
111da177e4SLinus Torvalds #include <linux/interrupt.h>
121da177e4SLinus Torvalds #include <linux/pci.h>
1365a77217SPaul Gortmaker #include <linux/module.h>
146cbbfe1cSTakashi Iwai #include <linux/io.h>
15f526afcdSTakashi Iwai #include <linux/nospec.h>
161da177e4SLinus Torvalds
171da177e4SLinus Torvalds #include <sound/core.h>
181da177e4SLinus Torvalds #include <sound/control.h>
191da177e4SLinus Torvalds #include <sound/pcm.h>
201da177e4SLinus Torvalds #include <sound/info.h>
211da177e4SLinus Torvalds #include <sound/asoundef.h>
221da177e4SLinus Torvalds #include <sound/initval.h>
231da177e4SLinus Torvalds
241da177e4SLinus Torvalds #include <asm/current.h>
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
271da177e4SLinus Torvalds static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
28a67ff6a5SRusty Russell static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
29a67ff6a5SRusty Russell static bool precise_ptr[SNDRV_CARDS]; /* Enable precise pointer */
301da177e4SLinus Torvalds
311da177e4SLinus Torvalds module_param_array(index, int, NULL, 0444);
321da177e4SLinus Torvalds MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard.");
331da177e4SLinus Torvalds module_param_array(id, charp, NULL, 0444);
341da177e4SLinus Torvalds MODULE_PARM_DESC(id, "ID string for RME Digi9652 (Hammerfall) soundcard.");
351da177e4SLinus Torvalds module_param_array(enable, bool, NULL, 0444);
361da177e4SLinus Torvalds MODULE_PARM_DESC(enable, "Enable/disable specific RME96{52,36} soundcards.");
371da177e4SLinus Torvalds module_param_array(precise_ptr, bool, NULL, 0444);
381da177e4SLinus Torvalds MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably).");
391da177e4SLinus Torvalds MODULE_AUTHOR("Paul Davis <pbd@op.net>, Winfried Ritsch");
401da177e4SLinus Torvalds MODULE_DESCRIPTION("RME Digi9652/Digi9636");
411da177e4SLinus Torvalds MODULE_LICENSE("GPL");
421da177e4SLinus Torvalds
431da177e4SLinus Torvalds /* The Hammerfall has two sets of 24 ADAT + 2 S/PDIF channels, one for
441da177e4SLinus Torvalds capture, one for playback. Both the ADAT and S/PDIF channels appear
451da177e4SLinus Torvalds to the host CPU in the same block of memory. There is no functional
461da177e4SLinus Torvalds difference between them in terms of access.
471da177e4SLinus Torvalds
481da177e4SLinus Torvalds The Hammerfall Light is identical to the Hammerfall, except that it
491da177e4SLinus Torvalds has 2 sets 18 channels (16 ADAT + 2 S/PDIF) for capture and playback.
501da177e4SLinus Torvalds */
511da177e4SLinus Torvalds
521da177e4SLinus Torvalds #define RME9652_NCHANNELS 26
531da177e4SLinus Torvalds #define RME9636_NCHANNELS 18
541da177e4SLinus Torvalds
551da177e4SLinus Torvalds /* Preferred sync source choices - used by "sync_pref" control switch */
561da177e4SLinus Torvalds
571da177e4SLinus Torvalds #define RME9652_SYNC_FROM_SPDIF 0
581da177e4SLinus Torvalds #define RME9652_SYNC_FROM_ADAT1 1
591da177e4SLinus Torvalds #define RME9652_SYNC_FROM_ADAT2 2
601da177e4SLinus Torvalds #define RME9652_SYNC_FROM_ADAT3 3
611da177e4SLinus Torvalds
621da177e4SLinus Torvalds /* Possible sources of S/PDIF input */
631da177e4SLinus Torvalds
641da177e4SLinus Torvalds #define RME9652_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */
651da177e4SLinus Torvalds #define RME9652_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */
661da177e4SLinus Torvalds #define RME9652_SPDIFIN_INTERN 2 /* internal (CDROM) */
671da177e4SLinus Torvalds
681da177e4SLinus Torvalds /* ------------- Status-Register bits --------------------- */
691da177e4SLinus Torvalds
701da177e4SLinus Torvalds #define RME9652_IRQ (1<<0) /* IRQ is High if not reset by irq_clear */
711da177e4SLinus Torvalds #define RME9652_lock_2 (1<<1) /* ADAT 3-PLL: 1=locked, 0=unlocked */
721da177e4SLinus Torvalds #define RME9652_lock_1 (1<<2) /* ADAT 2-PLL: 1=locked, 0=unlocked */
731da177e4SLinus Torvalds #define RME9652_lock_0 (1<<3) /* ADAT 1-PLL: 1=locked, 0=unlocked */
741da177e4SLinus Torvalds #define RME9652_fs48 (1<<4) /* sample rate is 0=44.1/88.2,1=48/96 Khz */
751da177e4SLinus Torvalds #define RME9652_wsel_rd (1<<5) /* if Word-Clock is used and valid then 1 */
761da177e4SLinus Torvalds /* bits 6-15 encode h/w buffer pointer position */
771da177e4SLinus Torvalds #define RME9652_sync_2 (1<<16) /* if ADAT-IN 3 in sync to system clock */
781da177e4SLinus Torvalds #define RME9652_sync_1 (1<<17) /* if ADAT-IN 2 in sync to system clock */
791da177e4SLinus Torvalds #define RME9652_sync_0 (1<<18) /* if ADAT-IN 1 in sync to system clock */
801da177e4SLinus Torvalds #define RME9652_DS_rd (1<<19) /* 1=Double Speed Mode, 0=Normal Speed */
811da177e4SLinus Torvalds #define RME9652_tc_busy (1<<20) /* 1=time-code copy in progress (960ms) */
821da177e4SLinus Torvalds #define RME9652_tc_out (1<<21) /* time-code out bit */
831da177e4SLinus Torvalds #define RME9652_F_0 (1<<22) /* 000=64kHz, 100=88.2kHz, 011=96kHz */
841da177e4SLinus Torvalds #define RME9652_F_1 (1<<23) /* 111=32kHz, 110=44.1kHz, 101=48kHz, */
851da177e4SLinus Torvalds #define RME9652_F_2 (1<<24) /* external Crystal Chip if ERF=1 */
861da177e4SLinus Torvalds #define RME9652_ERF (1<<25) /* Error-Flag of SDPIF Receiver (1=No Lock) */
871da177e4SLinus Torvalds #define RME9652_buffer_id (1<<26) /* toggles by each interrupt on rec/play */
881da177e4SLinus Torvalds #define RME9652_tc_valid (1<<27) /* 1 = a signal is detected on time-code input */
891da177e4SLinus Torvalds #define RME9652_SPDIF_READ (1<<28) /* byte available from Rev 1.5+ S/PDIF interface */
901da177e4SLinus Torvalds
911da177e4SLinus Torvalds #define RME9652_sync (RME9652_sync_0|RME9652_sync_1|RME9652_sync_2)
921da177e4SLinus Torvalds #define RME9652_lock (RME9652_lock_0|RME9652_lock_1|RME9652_lock_2)
931da177e4SLinus Torvalds #define RME9652_F (RME9652_F_0|RME9652_F_1|RME9652_F_2)
941da177e4SLinus Torvalds #define rme9652_decode_spdif_rate(x) ((x)>>22)
951da177e4SLinus Torvalds
961da177e4SLinus Torvalds /* Bit 6..15 : h/w buffer pointer */
971da177e4SLinus Torvalds
981da177e4SLinus Torvalds #define RME9652_buf_pos 0x000FFC0
991da177e4SLinus Torvalds
1001da177e4SLinus Torvalds /* Bits 31,30,29 are bits 5,4,3 of h/w pointer position on later
1011da177e4SLinus Torvalds Rev G EEPROMS and Rev 1.5 cards or later.
1021da177e4SLinus Torvalds */
1031da177e4SLinus Torvalds
1041da177e4SLinus Torvalds #define RME9652_REV15_buf_pos(x) ((((x)&0xE0000000)>>26)|((x)&RME9652_buf_pos))
1051da177e4SLinus Torvalds
1061da177e4SLinus Torvalds /* amount of io space we remap for register access. i'm not sure we
1071da177e4SLinus Torvalds even need this much, but 1K is nice round number :)
1081da177e4SLinus Torvalds */
1091da177e4SLinus Torvalds
1101da177e4SLinus Torvalds #define RME9652_IO_EXTENT 1024
1111da177e4SLinus Torvalds
1121da177e4SLinus Torvalds #define RME9652_init_buffer 0
1131da177e4SLinus Torvalds #define RME9652_play_buffer 32 /* holds ptr to 26x64kBit host RAM */
1141da177e4SLinus Torvalds #define RME9652_rec_buffer 36 /* holds ptr to 26x64kBit host RAM */
1151da177e4SLinus Torvalds #define RME9652_control_register 64
1161da177e4SLinus Torvalds #define RME9652_irq_clear 96
1171da177e4SLinus Torvalds #define RME9652_time_code 100 /* useful if used with alesis adat */
1181da177e4SLinus Torvalds #define RME9652_thru_base 128 /* 132...228 Thru for 26 channels */
1191da177e4SLinus Torvalds
1201da177e4SLinus Torvalds /* Read-only registers */
1211da177e4SLinus Torvalds
1221da177e4SLinus Torvalds /* Writing to any of the register locations writes to the status
1231da177e4SLinus Torvalds register. We'll use the first location as our point of access.
1241da177e4SLinus Torvalds */
1251da177e4SLinus Torvalds
1261da177e4SLinus Torvalds #define RME9652_status_register 0
1271da177e4SLinus Torvalds
1281da177e4SLinus Torvalds /* --------- Control-Register Bits ---------------- */
1291da177e4SLinus Torvalds
1301da177e4SLinus Torvalds
1311da177e4SLinus Torvalds #define RME9652_start_bit (1<<0) /* start record/play */
1321da177e4SLinus Torvalds /* bits 1-3 encode buffersize/latency */
1331da177e4SLinus Torvalds #define RME9652_Master (1<<4) /* Clock Mode Master=1,Slave/Auto=0 */
134561de31aSJoe Perches #define RME9652_IE (1<<5) /* Interrupt Enable */
1351da177e4SLinus Torvalds #define RME9652_freq (1<<6) /* samplerate 0=44.1/88.2, 1=48/96 kHz */
1361da177e4SLinus Torvalds #define RME9652_freq1 (1<<7) /* if 0, 32kHz, else always 1 */
1371da177e4SLinus Torvalds #define RME9652_DS (1<<8) /* Doule Speed 0=44.1/48, 1=88.2/96 Khz */
1381da177e4SLinus Torvalds #define RME9652_PRO (1<<9) /* S/PDIF out: 0=consumer, 1=professional */
1391da177e4SLinus Torvalds #define RME9652_EMP (1<<10) /* Emphasis 0=None, 1=ON */
1401da177e4SLinus Torvalds #define RME9652_Dolby (1<<11) /* Non-audio bit 1=set, 0=unset */
1411da177e4SLinus Torvalds #define RME9652_opt_out (1<<12) /* Use 1st optical OUT as SPDIF: 1=yes,0=no */
1421da177e4SLinus Torvalds #define RME9652_wsel (1<<13) /* use Wordclock as sync (overwrites master) */
1431da177e4SLinus Torvalds #define RME9652_inp_0 (1<<14) /* SPDIF-IN: 00=optical (ADAT1), */
1441da177e4SLinus Torvalds #define RME9652_inp_1 (1<<15) /* 01=koaxial (Cinch), 10=Internal CDROM */
1451da177e4SLinus Torvalds #define RME9652_SyncPref_ADAT2 (1<<16)
1461da177e4SLinus Torvalds #define RME9652_SyncPref_ADAT3 (1<<17)
1471da177e4SLinus Torvalds #define RME9652_SPDIF_RESET (1<<18) /* Rev 1.5+: h/w S/PDIF receiver */
1481da177e4SLinus Torvalds #define RME9652_SPDIF_SELECT (1<<19)
1491da177e4SLinus Torvalds #define RME9652_SPDIF_CLOCK (1<<20)
1501da177e4SLinus Torvalds #define RME9652_SPDIF_WRITE (1<<21)
1511da177e4SLinus Torvalds #define RME9652_ADAT1_INTERNAL (1<<22) /* Rev 1.5+: if set, internal CD connector carries ADAT */
1521da177e4SLinus Torvalds
1531da177e4SLinus Torvalds /* buffersize = 512Bytes * 2^n, where n is made from Bit2 ... Bit0 */
1541da177e4SLinus Torvalds
1551da177e4SLinus Torvalds #define RME9652_latency 0x0e
1561da177e4SLinus Torvalds #define rme9652_encode_latency(x) (((x)&0x7)<<1)
1571da177e4SLinus Torvalds #define rme9652_decode_latency(x) (((x)>>1)&0x7)
1581da177e4SLinus Torvalds #define rme9652_running_double_speed(s) ((s)->control_register & RME9652_DS)
1591da177e4SLinus Torvalds #define RME9652_inp (RME9652_inp_0|RME9652_inp_1)
1601da177e4SLinus Torvalds #define rme9652_encode_spdif_in(x) (((x)&0x3)<<14)
1611da177e4SLinus Torvalds #define rme9652_decode_spdif_in(x) (((x)>>14)&0x3)
1621da177e4SLinus Torvalds
1631da177e4SLinus Torvalds #define RME9652_SyncPref_Mask (RME9652_SyncPref_ADAT2|RME9652_SyncPref_ADAT3)
1641da177e4SLinus Torvalds #define RME9652_SyncPref_ADAT1 0
1651da177e4SLinus Torvalds #define RME9652_SyncPref_SPDIF (RME9652_SyncPref_ADAT2|RME9652_SyncPref_ADAT3)
1661da177e4SLinus Torvalds
1671da177e4SLinus Torvalds /* the size of a substream (1 mono data stream) */
1681da177e4SLinus Torvalds
1691da177e4SLinus Torvalds #define RME9652_CHANNEL_BUFFER_SAMPLES (16*1024)
1701da177e4SLinus Torvalds #define RME9652_CHANNEL_BUFFER_BYTES (4*RME9652_CHANNEL_BUFFER_SAMPLES)
1711da177e4SLinus Torvalds
1721da177e4SLinus Torvalds /* the size of the area we need to allocate for DMA transfers. the
1731da177e4SLinus Torvalds size is the same regardless of the number of channels - the
1741da177e4SLinus Torvalds 9636 still uses the same memory area.
1751da177e4SLinus Torvalds
1761da177e4SLinus Torvalds Note that we allocate 1 more channel than is apparently needed
1771da177e4SLinus Torvalds because the h/w seems to write 1 byte beyond the end of the last
1781da177e4SLinus Torvalds page. Sigh.
1791da177e4SLinus Torvalds */
1801da177e4SLinus Torvalds
1811da177e4SLinus Torvalds #define RME9652_DMA_AREA_BYTES ((RME9652_NCHANNELS+1) * RME9652_CHANNEL_BUFFER_BYTES)
1821da177e4SLinus Torvalds #define RME9652_DMA_AREA_KILOBYTES (RME9652_DMA_AREA_BYTES/1024)
1831da177e4SLinus Torvalds
184abfd67bdSTakashi Iwai struct snd_rme9652 {
1851da177e4SLinus Torvalds int dev;
1861da177e4SLinus Torvalds
1871da177e4SLinus Torvalds spinlock_t lock;
1881da177e4SLinus Torvalds int irq;
1891da177e4SLinus Torvalds unsigned long port;
1901da177e4SLinus Torvalds void __iomem *iobase;
1911da177e4SLinus Torvalds
1921da177e4SLinus Torvalds int precise_ptr;
1931da177e4SLinus Torvalds
1941da177e4SLinus Torvalds u32 control_register; /* cached value */
1951da177e4SLinus Torvalds u32 thru_bits; /* thru 1=on, 0=off channel 1=Bit1... channel 26= Bit26 */
1961da177e4SLinus Torvalds
1971da177e4SLinus Torvalds u32 creg_spdif;
1981da177e4SLinus Torvalds u32 creg_spdif_stream;
1991da177e4SLinus Torvalds
2001da177e4SLinus Torvalds char *card_name; /* hammerfall or hammerfall light names */
2011da177e4SLinus Torvalds
2021da177e4SLinus Torvalds size_t hw_offsetmask; /* &-with status register to get real hw_offset */
2031da177e4SLinus Torvalds size_t prev_hw_offset; /* previous hw offset */
2041da177e4SLinus Torvalds size_t max_jitter; /* maximum jitter in frames for
2051da177e4SLinus Torvalds hw pointer */
2061da177e4SLinus Torvalds size_t period_bytes; /* guess what this is */
2071da177e4SLinus Torvalds
2081da177e4SLinus Torvalds unsigned char ds_channels;
2091da177e4SLinus Torvalds unsigned char ss_channels; /* different for hammerfall/hammerfall-light */
2101da177e4SLinus Torvalds
21143d35cccSTakashi Iwai /* DMA buffers; those are copied instances from the original snd_dma_buf
21243d35cccSTakashi Iwai * objects (which are managed via devres) for the address alignments
21343d35cccSTakashi Iwai */
21443d35cccSTakashi Iwai struct snd_dma_buffer playback_dma_buf;
21543d35cccSTakashi Iwai struct snd_dma_buffer capture_dma_buf;
2161da177e4SLinus Torvalds
2171da177e4SLinus Torvalds unsigned char *capture_buffer; /* suitably aligned address */
2181da177e4SLinus Torvalds unsigned char *playback_buffer; /* suitably aligned address */
2191da177e4SLinus Torvalds
2201da177e4SLinus Torvalds pid_t capture_pid;
2211da177e4SLinus Torvalds pid_t playback_pid;
2221da177e4SLinus Torvalds
223abfd67bdSTakashi Iwai struct snd_pcm_substream *capture_substream;
224abfd67bdSTakashi Iwai struct snd_pcm_substream *playback_substream;
2251da177e4SLinus Torvalds int running;
2261da177e4SLinus Torvalds
2271da177e4SLinus Torvalds int passthru; /* non-zero if doing pass-thru */
2281da177e4SLinus Torvalds int hw_rev; /* h/w rev * 10 (i.e. 1.5 has hw_rev = 15) */
2291da177e4SLinus Torvalds
2301da177e4SLinus Torvalds int last_spdif_sample_rate; /* so that we can catch externally ... */
2311da177e4SLinus Torvalds int last_adat_sample_rate; /* ... induced rate changes */
2321da177e4SLinus Torvalds
23350895a55SJason A. Donenfeld const signed char *channel_map;
2341da177e4SLinus Torvalds
235abfd67bdSTakashi Iwai struct snd_card *card;
236abfd67bdSTakashi Iwai struct snd_pcm *pcm;
2371da177e4SLinus Torvalds struct pci_dev *pci;
238abfd67bdSTakashi Iwai struct snd_kcontrol *spdif_ctl;
2391da177e4SLinus Torvalds
240abfd67bdSTakashi Iwai };
2411da177e4SLinus Torvalds
2421da177e4SLinus Torvalds /* These tables map the ALSA channels 1..N to the channels that we
2431da177e4SLinus Torvalds need to use in order to find the relevant channel buffer. RME
2441da177e4SLinus Torvalds refer to this kind of mapping as between "the ADAT channel and
2451da177e4SLinus Torvalds the DMA channel." We index it using the logical audio channel,
2461da177e4SLinus Torvalds and the value is the DMA channel (i.e. channel buffer number)
2471da177e4SLinus Torvalds where the data for that channel can be read/written from/to.
2481da177e4SLinus Torvalds */
2491da177e4SLinus Torvalds
25050895a55SJason A. Donenfeld static const signed char channel_map_9652_ss[26] = {
2511da177e4SLinus Torvalds 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
2521da177e4SLinus Torvalds 18, 19, 20, 21, 22, 23, 24, 25
2531da177e4SLinus Torvalds };
2541da177e4SLinus Torvalds
25550895a55SJason A. Donenfeld static const signed char channel_map_9636_ss[26] = {
2561da177e4SLinus Torvalds 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
2571da177e4SLinus Torvalds /* channels 16 and 17 are S/PDIF */
2581da177e4SLinus Torvalds 24, 25,
2591da177e4SLinus Torvalds /* channels 18-25 don't exist */
2601da177e4SLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1
2611da177e4SLinus Torvalds };
2621da177e4SLinus Torvalds
26350895a55SJason A. Donenfeld static const signed char channel_map_9652_ds[26] = {
2641da177e4SLinus Torvalds /* ADAT channels are remapped */
2651da177e4SLinus Torvalds 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23,
2661da177e4SLinus Torvalds /* channels 12 and 13 are S/PDIF */
2671da177e4SLinus Torvalds 24, 25,
2681da177e4SLinus Torvalds /* others don't exist */
2691da177e4SLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
2701da177e4SLinus Torvalds };
2711da177e4SLinus Torvalds
27250895a55SJason A. Donenfeld static const signed char channel_map_9636_ds[26] = {
2731da177e4SLinus Torvalds /* ADAT channels are remapped */
2741da177e4SLinus Torvalds 1, 3, 5, 7, 9, 11, 13, 15,
2751da177e4SLinus Torvalds /* channels 8 and 9 are S/PDIF */
276770bd4bfSTakashi Iwai 24, 25,
2771da177e4SLinus Torvalds /* others don't exist */
2781da177e4SLinus Torvalds -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
2791da177e4SLinus Torvalds };
2801da177e4SLinus Torvalds
281b1002b2dSTakashi Iwai static struct snd_dma_buffer *
snd_hammerfall_get_buffer(struct pci_dev * pci,size_t size)282b1002b2dSTakashi Iwai snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size)
2831da177e4SLinus Torvalds {
284b1002b2dSTakashi Iwai return snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, size);
2851da177e4SLinus Torvalds }
2861da177e4SLinus Torvalds
2879baa3c34SBenoit Taine static const struct pci_device_id snd_rme9652_ids[] = {
2881da177e4SLinus Torvalds {
2891da177e4SLinus Torvalds .vendor = 0x10ee,
2901da177e4SLinus Torvalds .device = 0x3fc4,
2911da177e4SLinus Torvalds .subvendor = PCI_ANY_ID,
2921da177e4SLinus Torvalds .subdevice = PCI_ANY_ID,
2931da177e4SLinus Torvalds }, /* RME Digi9652 */
2941da177e4SLinus Torvalds { 0, },
2951da177e4SLinus Torvalds };
2961da177e4SLinus Torvalds
2971da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, snd_rme9652_ids);
2981da177e4SLinus Torvalds
rme9652_write(struct snd_rme9652 * rme9652,int reg,int val)299abfd67bdSTakashi Iwai static inline void rme9652_write(struct snd_rme9652 *rme9652, int reg, int val)
3001da177e4SLinus Torvalds {
3011da177e4SLinus Torvalds writel(val, rme9652->iobase + reg);
3021da177e4SLinus Torvalds }
3031da177e4SLinus Torvalds
rme9652_read(struct snd_rme9652 * rme9652,int reg)304abfd67bdSTakashi Iwai static inline unsigned int rme9652_read(struct snd_rme9652 *rme9652, int reg)
3051da177e4SLinus Torvalds {
3061da177e4SLinus Torvalds return readl(rme9652->iobase + reg);
3071da177e4SLinus Torvalds }
3081da177e4SLinus Torvalds
snd_rme9652_use_is_exclusive(struct snd_rme9652 * rme9652)309abfd67bdSTakashi Iwai static inline int snd_rme9652_use_is_exclusive(struct snd_rme9652 *rme9652)
3101da177e4SLinus Torvalds {
3111da177e4SLinus Torvalds unsigned long flags;
3121da177e4SLinus Torvalds int ret = 1;
3131da177e4SLinus Torvalds
3141da177e4SLinus Torvalds spin_lock_irqsave(&rme9652->lock, flags);
3151da177e4SLinus Torvalds if ((rme9652->playback_pid != rme9652->capture_pid) &&
3161da177e4SLinus Torvalds (rme9652->playback_pid >= 0) && (rme9652->capture_pid >= 0)) {
3171da177e4SLinus Torvalds ret = 0;
3181da177e4SLinus Torvalds }
3191da177e4SLinus Torvalds spin_unlock_irqrestore(&rme9652->lock, flags);
3201da177e4SLinus Torvalds return ret;
3211da177e4SLinus Torvalds }
3221da177e4SLinus Torvalds
rme9652_adat_sample_rate(struct snd_rme9652 * rme9652)323abfd67bdSTakashi Iwai static inline int rme9652_adat_sample_rate(struct snd_rme9652 *rme9652)
3241da177e4SLinus Torvalds {
3251da177e4SLinus Torvalds if (rme9652_running_double_speed(rme9652)) {
3261da177e4SLinus Torvalds return (rme9652_read(rme9652, RME9652_status_register) &
3271da177e4SLinus Torvalds RME9652_fs48) ? 96000 : 88200;
3281da177e4SLinus Torvalds } else {
3291da177e4SLinus Torvalds return (rme9652_read(rme9652, RME9652_status_register) &
3301da177e4SLinus Torvalds RME9652_fs48) ? 48000 : 44100;
3311da177e4SLinus Torvalds }
3321da177e4SLinus Torvalds }
3331da177e4SLinus Torvalds
rme9652_compute_period_size(struct snd_rme9652 * rme9652)334abfd67bdSTakashi Iwai static inline void rme9652_compute_period_size(struct snd_rme9652 *rme9652)
3351da177e4SLinus Torvalds {
3361da177e4SLinus Torvalds unsigned int i;
3371da177e4SLinus Torvalds
3381da177e4SLinus Torvalds i = rme9652->control_register & RME9652_latency;
3391da177e4SLinus Torvalds rme9652->period_bytes = 1 << ((rme9652_decode_latency(i) + 8));
3401da177e4SLinus Torvalds rme9652->hw_offsetmask =
3411da177e4SLinus Torvalds (rme9652->period_bytes * 2 - 1) & RME9652_buf_pos;
3421da177e4SLinus Torvalds rme9652->max_jitter = 80;
3431da177e4SLinus Torvalds }
3441da177e4SLinus Torvalds
rme9652_hw_pointer(struct snd_rme9652 * rme9652)345abfd67bdSTakashi Iwai static snd_pcm_uframes_t rme9652_hw_pointer(struct snd_rme9652 *rme9652)
3461da177e4SLinus Torvalds {
3471da177e4SLinus Torvalds int status;
3481da177e4SLinus Torvalds unsigned int offset, frag;
3491da177e4SLinus Torvalds snd_pcm_uframes_t period_size = rme9652->period_bytes / 4;
3501da177e4SLinus Torvalds snd_pcm_sframes_t delta;
3511da177e4SLinus Torvalds
3521da177e4SLinus Torvalds status = rme9652_read(rme9652, RME9652_status_register);
3531da177e4SLinus Torvalds if (!rme9652->precise_ptr)
3541da177e4SLinus Torvalds return (status & RME9652_buffer_id) ? period_size : 0;
3551da177e4SLinus Torvalds offset = status & RME9652_buf_pos;
3561da177e4SLinus Torvalds
3571da177e4SLinus Torvalds /* The hardware may give a backward movement for up to 80 frames
3581da177e4SLinus Torvalds Martin Kirst <martin.kirst@freenet.de> knows the details.
3591da177e4SLinus Torvalds */
3601da177e4SLinus Torvalds
3611da177e4SLinus Torvalds delta = rme9652->prev_hw_offset - offset;
3621da177e4SLinus Torvalds delta &= 0xffff;
3631da177e4SLinus Torvalds if (delta <= (snd_pcm_sframes_t)rme9652->max_jitter * 4)
3641da177e4SLinus Torvalds offset = rme9652->prev_hw_offset;
3651da177e4SLinus Torvalds else
3661da177e4SLinus Torvalds rme9652->prev_hw_offset = offset;
3671da177e4SLinus Torvalds offset &= rme9652->hw_offsetmask;
3681da177e4SLinus Torvalds offset /= 4;
3691da177e4SLinus Torvalds frag = status & RME9652_buffer_id;
3701da177e4SLinus Torvalds
3711da177e4SLinus Torvalds if (offset < period_size) {
3721da177e4SLinus Torvalds if (offset > rme9652->max_jitter) {
3731da177e4SLinus Torvalds if (frag)
37409ae539eSTakashi Iwai dev_err(rme9652->card->dev,
37509ae539eSTakashi Iwai "Unexpected hw_pointer position (bufid == 0): status: %x offset: %d\n",
37609ae539eSTakashi Iwai status, offset);
3771da177e4SLinus Torvalds } else if (!frag)
3781da177e4SLinus Torvalds return 0;
3791da177e4SLinus Torvalds offset -= rme9652->max_jitter;
380304e3bb7STakashi Iwai if ((int)offset < 0)
3811da177e4SLinus Torvalds offset += period_size * 2;
3821da177e4SLinus Torvalds } else {
3831da177e4SLinus Torvalds if (offset > period_size + rme9652->max_jitter) {
3841da177e4SLinus Torvalds if (!frag)
38509ae539eSTakashi Iwai dev_err(rme9652->card->dev,
38609ae539eSTakashi Iwai "Unexpected hw_pointer position (bufid == 1): status: %x offset: %d\n",
38709ae539eSTakashi Iwai status, offset);
3881da177e4SLinus Torvalds } else if (frag)
3891da177e4SLinus Torvalds return period_size;
3901da177e4SLinus Torvalds offset -= rme9652->max_jitter;
3911da177e4SLinus Torvalds }
3921da177e4SLinus Torvalds
3931da177e4SLinus Torvalds return offset;
3941da177e4SLinus Torvalds }
3951da177e4SLinus Torvalds
rme9652_reset_hw_pointer(struct snd_rme9652 * rme9652)396abfd67bdSTakashi Iwai static inline void rme9652_reset_hw_pointer(struct snd_rme9652 *rme9652)
3971da177e4SLinus Torvalds {
3981da177e4SLinus Torvalds int i;
3991da177e4SLinus Torvalds
4001da177e4SLinus Torvalds /* reset the FIFO pointer to zero. We do this by writing to 8
4011da177e4SLinus Torvalds registers, each of which is a 32bit wide register, and set
4021da177e4SLinus Torvalds them all to zero. Note that s->iobase is a pointer to
4031da177e4SLinus Torvalds int32, not pointer to char.
4041da177e4SLinus Torvalds */
4051da177e4SLinus Torvalds
4061da177e4SLinus Torvalds for (i = 0; i < 8; i++) {
4071da177e4SLinus Torvalds rme9652_write(rme9652, i * 4, 0);
4081da177e4SLinus Torvalds udelay(10);
4091da177e4SLinus Torvalds }
4101da177e4SLinus Torvalds rme9652->prev_hw_offset = 0;
4111da177e4SLinus Torvalds }
4121da177e4SLinus Torvalds
rme9652_start(struct snd_rme9652 * s)413abfd67bdSTakashi Iwai static inline void rme9652_start(struct snd_rme9652 *s)
4141da177e4SLinus Torvalds {
4151da177e4SLinus Torvalds s->control_register |= (RME9652_IE | RME9652_start_bit);
4161da177e4SLinus Torvalds rme9652_write(s, RME9652_control_register, s->control_register);
4171da177e4SLinus Torvalds }
4181da177e4SLinus Torvalds
rme9652_stop(struct snd_rme9652 * s)419abfd67bdSTakashi Iwai static inline void rme9652_stop(struct snd_rme9652 *s)
4201da177e4SLinus Torvalds {
4211da177e4SLinus Torvalds s->control_register &= ~(RME9652_start_bit | RME9652_IE);
4221da177e4SLinus Torvalds rme9652_write(s, RME9652_control_register, s->control_register);
4231da177e4SLinus Torvalds }
4241da177e4SLinus Torvalds
rme9652_set_interrupt_interval(struct snd_rme9652 * s,unsigned int frames)425abfd67bdSTakashi Iwai static int rme9652_set_interrupt_interval(struct snd_rme9652 *s,
4261da177e4SLinus Torvalds unsigned int frames)
4271da177e4SLinus Torvalds {
4281da177e4SLinus Torvalds int restart = 0;
4291da177e4SLinus Torvalds int n;
4301da177e4SLinus Torvalds
4311da177e4SLinus Torvalds spin_lock_irq(&s->lock);
4321da177e4SLinus Torvalds
4339ebb3697STakashi Iwai restart = s->running;
4349ebb3697STakashi Iwai if (restart)
4351da177e4SLinus Torvalds rme9652_stop(s);
4361da177e4SLinus Torvalds
4371da177e4SLinus Torvalds frames >>= 7;
4381da177e4SLinus Torvalds n = 0;
4391da177e4SLinus Torvalds while (frames) {
4401da177e4SLinus Torvalds n++;
4411da177e4SLinus Torvalds frames >>= 1;
4421da177e4SLinus Torvalds }
4431da177e4SLinus Torvalds
4441da177e4SLinus Torvalds s->control_register &= ~RME9652_latency;
4451da177e4SLinus Torvalds s->control_register |= rme9652_encode_latency(n);
4461da177e4SLinus Torvalds
4471da177e4SLinus Torvalds rme9652_write(s, RME9652_control_register, s->control_register);
4481da177e4SLinus Torvalds
4491da177e4SLinus Torvalds rme9652_compute_period_size(s);
4501da177e4SLinus Torvalds
4511da177e4SLinus Torvalds if (restart)
4521da177e4SLinus Torvalds rme9652_start(s);
4531da177e4SLinus Torvalds
4541da177e4SLinus Torvalds spin_unlock_irq(&s->lock);
4551da177e4SLinus Torvalds
4561da177e4SLinus Torvalds return 0;
4571da177e4SLinus Torvalds }
4581da177e4SLinus Torvalds
rme9652_set_rate(struct snd_rme9652 * rme9652,int rate)459abfd67bdSTakashi Iwai static int rme9652_set_rate(struct snd_rme9652 *rme9652, int rate)
4601da177e4SLinus Torvalds {
4611da177e4SLinus Torvalds int restart;
4621da177e4SLinus Torvalds int reject_if_open = 0;
4631da177e4SLinus Torvalds int xrate;
4641da177e4SLinus Torvalds
4651da177e4SLinus Torvalds if (!snd_rme9652_use_is_exclusive (rme9652)) {
4661da177e4SLinus Torvalds return -EBUSY;
4671da177e4SLinus Torvalds }
4681da177e4SLinus Torvalds
4691da177e4SLinus Torvalds /* Changing from a "single speed" to a "double speed" rate is
4701da177e4SLinus Torvalds not allowed if any substreams are open. This is because
4711da177e4SLinus Torvalds such a change causes a shift in the location of
4721da177e4SLinus Torvalds the DMA buffers and a reduction in the number of available
4731da177e4SLinus Torvalds buffers.
4741da177e4SLinus Torvalds
4751da177e4SLinus Torvalds Note that a similar but essentially insoluble problem
4761da177e4SLinus Torvalds exists for externally-driven rate changes. All we can do
4771da177e4SLinus Torvalds is to flag rate changes in the read/write routines.
4781da177e4SLinus Torvalds */
4791da177e4SLinus Torvalds
4801da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
4811da177e4SLinus Torvalds xrate = rme9652_adat_sample_rate(rme9652);
4821da177e4SLinus Torvalds
4831da177e4SLinus Torvalds switch (rate) {
4841da177e4SLinus Torvalds case 44100:
4851da177e4SLinus Torvalds if (xrate > 48000) {
4861da177e4SLinus Torvalds reject_if_open = 1;
4871da177e4SLinus Torvalds }
4881da177e4SLinus Torvalds rate = 0;
4891da177e4SLinus Torvalds break;
4901da177e4SLinus Torvalds case 48000:
4911da177e4SLinus Torvalds if (xrate > 48000) {
4921da177e4SLinus Torvalds reject_if_open = 1;
4931da177e4SLinus Torvalds }
4941da177e4SLinus Torvalds rate = RME9652_freq;
4951da177e4SLinus Torvalds break;
4961da177e4SLinus Torvalds case 88200:
4971da177e4SLinus Torvalds if (xrate < 48000) {
4981da177e4SLinus Torvalds reject_if_open = 1;
4991da177e4SLinus Torvalds }
5001da177e4SLinus Torvalds rate = RME9652_DS;
5011da177e4SLinus Torvalds break;
5021da177e4SLinus Torvalds case 96000:
5031da177e4SLinus Torvalds if (xrate < 48000) {
5041da177e4SLinus Torvalds reject_if_open = 1;
5051da177e4SLinus Torvalds }
5061da177e4SLinus Torvalds rate = RME9652_DS | RME9652_freq;
5071da177e4SLinus Torvalds break;
5081da177e4SLinus Torvalds default:
5091da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
5101da177e4SLinus Torvalds return -EINVAL;
5111da177e4SLinus Torvalds }
5121da177e4SLinus Torvalds
5131da177e4SLinus Torvalds if (reject_if_open && (rme9652->capture_pid >= 0 || rme9652->playback_pid >= 0)) {
5141da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
5151da177e4SLinus Torvalds return -EBUSY;
5161da177e4SLinus Torvalds }
5171da177e4SLinus Torvalds
5189ebb3697STakashi Iwai restart = rme9652->running;
5199ebb3697STakashi Iwai if (restart)
5201da177e4SLinus Torvalds rme9652_stop(rme9652);
5211da177e4SLinus Torvalds rme9652->control_register &= ~(RME9652_freq | RME9652_DS);
5221da177e4SLinus Torvalds rme9652->control_register |= rate;
5231da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register, rme9652->control_register);
5241da177e4SLinus Torvalds
5259ebb3697STakashi Iwai if (restart)
5261da177e4SLinus Torvalds rme9652_start(rme9652);
5271da177e4SLinus Torvalds
5281da177e4SLinus Torvalds if (rate & RME9652_DS) {
5291da177e4SLinus Torvalds if (rme9652->ss_channels == RME9652_NCHANNELS) {
5301da177e4SLinus Torvalds rme9652->channel_map = channel_map_9652_ds;
5311da177e4SLinus Torvalds } else {
5321da177e4SLinus Torvalds rme9652->channel_map = channel_map_9636_ds;
5331da177e4SLinus Torvalds }
5341da177e4SLinus Torvalds } else {
5351da177e4SLinus Torvalds if (rme9652->ss_channels == RME9652_NCHANNELS) {
5361da177e4SLinus Torvalds rme9652->channel_map = channel_map_9652_ss;
5371da177e4SLinus Torvalds } else {
5381da177e4SLinus Torvalds rme9652->channel_map = channel_map_9636_ss;
5391da177e4SLinus Torvalds }
5401da177e4SLinus Torvalds }
5411da177e4SLinus Torvalds
5421da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
5431da177e4SLinus Torvalds return 0;
5441da177e4SLinus Torvalds }
5451da177e4SLinus Torvalds
rme9652_set_thru(struct snd_rme9652 * rme9652,int channel,int enable)546abfd67bdSTakashi Iwai static void rme9652_set_thru(struct snd_rme9652 *rme9652, int channel, int enable)
5471da177e4SLinus Torvalds {
5481da177e4SLinus Torvalds int i;
5491da177e4SLinus Torvalds
5501da177e4SLinus Torvalds rme9652->passthru = 0;
5511da177e4SLinus Torvalds
5521da177e4SLinus Torvalds if (channel < 0) {
5531da177e4SLinus Torvalds
5541da177e4SLinus Torvalds /* set thru for all channels */
5551da177e4SLinus Torvalds
5561da177e4SLinus Torvalds if (enable) {
5571da177e4SLinus Torvalds for (i = 0; i < RME9652_NCHANNELS; i++) {
5581da177e4SLinus Torvalds rme9652->thru_bits |= (1 << i);
5591da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_thru_base + i * 4, 1);
5601da177e4SLinus Torvalds }
5611da177e4SLinus Torvalds } else {
5621da177e4SLinus Torvalds for (i = 0; i < RME9652_NCHANNELS; i++) {
5631da177e4SLinus Torvalds rme9652->thru_bits &= ~(1 << i);
5641da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_thru_base + i * 4, 0);
5651da177e4SLinus Torvalds }
5661da177e4SLinus Torvalds }
5671da177e4SLinus Torvalds
5681da177e4SLinus Torvalds } else {
5691da177e4SLinus Torvalds int mapped_channel;
5701da177e4SLinus Torvalds
5711da177e4SLinus Torvalds mapped_channel = rme9652->channel_map[channel];
5721da177e4SLinus Torvalds
5731da177e4SLinus Torvalds if (enable) {
5741da177e4SLinus Torvalds rme9652->thru_bits |= (1 << mapped_channel);
5751da177e4SLinus Torvalds } else {
5761da177e4SLinus Torvalds rme9652->thru_bits &= ~(1 << mapped_channel);
5771da177e4SLinus Torvalds }
5781da177e4SLinus Torvalds
5791da177e4SLinus Torvalds rme9652_write(rme9652,
5801da177e4SLinus Torvalds RME9652_thru_base + mapped_channel * 4,
5811da177e4SLinus Torvalds enable ? 1 : 0);
5821da177e4SLinus Torvalds }
5831da177e4SLinus Torvalds }
5841da177e4SLinus Torvalds
rme9652_set_passthru(struct snd_rme9652 * rme9652,int onoff)585abfd67bdSTakashi Iwai static int rme9652_set_passthru(struct snd_rme9652 *rme9652, int onoff)
5861da177e4SLinus Torvalds {
5871da177e4SLinus Torvalds if (onoff) {
5881da177e4SLinus Torvalds rme9652_set_thru(rme9652, -1, 1);
5891da177e4SLinus Torvalds
5901da177e4SLinus Torvalds /* we don't want interrupts, so do a
5911da177e4SLinus Torvalds custom version of rme9652_start().
5921da177e4SLinus Torvalds */
5931da177e4SLinus Torvalds
5941da177e4SLinus Torvalds rme9652->control_register =
5951da177e4SLinus Torvalds RME9652_inp_0 |
5961da177e4SLinus Torvalds rme9652_encode_latency(7) |
5971da177e4SLinus Torvalds RME9652_start_bit;
5981da177e4SLinus Torvalds
5991da177e4SLinus Torvalds rme9652_reset_hw_pointer(rme9652);
6001da177e4SLinus Torvalds
6011da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register,
6021da177e4SLinus Torvalds rme9652->control_register);
6031da177e4SLinus Torvalds rme9652->passthru = 1;
6041da177e4SLinus Torvalds } else {
6051da177e4SLinus Torvalds rme9652_set_thru(rme9652, -1, 0);
6061da177e4SLinus Torvalds rme9652_stop(rme9652);
6071da177e4SLinus Torvalds rme9652->passthru = 0;
6081da177e4SLinus Torvalds }
6091da177e4SLinus Torvalds
6101da177e4SLinus Torvalds return 0;
6111da177e4SLinus Torvalds }
6121da177e4SLinus Torvalds
rme9652_spdif_set_bit(struct snd_rme9652 * rme9652,int mask,int onoff)613abfd67bdSTakashi Iwai static void rme9652_spdif_set_bit (struct snd_rme9652 *rme9652, int mask, int onoff)
6141da177e4SLinus Torvalds {
6151da177e4SLinus Torvalds if (onoff)
6161da177e4SLinus Torvalds rme9652->control_register |= mask;
6171da177e4SLinus Torvalds else
6181da177e4SLinus Torvalds rme9652->control_register &= ~mask;
6191da177e4SLinus Torvalds
6201da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register, rme9652->control_register);
6211da177e4SLinus Torvalds }
6221da177e4SLinus Torvalds
rme9652_spdif_write_byte(struct snd_rme9652 * rme9652,const int val)623abfd67bdSTakashi Iwai static void rme9652_spdif_write_byte (struct snd_rme9652 *rme9652, const int val)
6241da177e4SLinus Torvalds {
6251da177e4SLinus Torvalds long mask;
6261da177e4SLinus Torvalds long i;
6271da177e4SLinus Torvalds
6281da177e4SLinus Torvalds for (i = 0, mask = 0x80; i < 8; i++, mask >>= 1) {
6291da177e4SLinus Torvalds if (val & mask)
6301da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_WRITE, 1);
6311da177e4SLinus Torvalds else
6321da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_WRITE, 0);
6331da177e4SLinus Torvalds
6341da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 1);
6351da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 0);
6361da177e4SLinus Torvalds }
6371da177e4SLinus Torvalds }
6381da177e4SLinus Torvalds
rme9652_spdif_read_byte(struct snd_rme9652 * rme9652)639abfd67bdSTakashi Iwai static int rme9652_spdif_read_byte (struct snd_rme9652 *rme9652)
6401da177e4SLinus Torvalds {
6411da177e4SLinus Torvalds long mask;
6421da177e4SLinus Torvalds long val;
6431da177e4SLinus Torvalds long i;
6441da177e4SLinus Torvalds
6451da177e4SLinus Torvalds val = 0;
6461da177e4SLinus Torvalds
6471da177e4SLinus Torvalds for (i = 0, mask = 0x80; i < 8; i++, mask >>= 1) {
6481da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 1);
6491da177e4SLinus Torvalds if (rme9652_read (rme9652, RME9652_status_register) & RME9652_SPDIF_READ)
6501da177e4SLinus Torvalds val |= mask;
6511da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 0);
6521da177e4SLinus Torvalds }
6531da177e4SLinus Torvalds
6541da177e4SLinus Torvalds return val;
6551da177e4SLinus Torvalds }
6561da177e4SLinus Torvalds
rme9652_write_spdif_codec(struct snd_rme9652 * rme9652,const int address,const int data)657abfd67bdSTakashi Iwai static void rme9652_write_spdif_codec (struct snd_rme9652 *rme9652, const int address, const int data)
6581da177e4SLinus Torvalds {
6591da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 1);
6601da177e4SLinus Torvalds rme9652_spdif_write_byte (rme9652, 0x20);
6611da177e4SLinus Torvalds rme9652_spdif_write_byte (rme9652, address);
6621da177e4SLinus Torvalds rme9652_spdif_write_byte (rme9652, data);
6631da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 0);
6641da177e4SLinus Torvalds }
6651da177e4SLinus Torvalds
6661da177e4SLinus Torvalds
rme9652_spdif_read_codec(struct snd_rme9652 * rme9652,const int address)667abfd67bdSTakashi Iwai static int rme9652_spdif_read_codec (struct snd_rme9652 *rme9652, const int address)
6681da177e4SLinus Torvalds {
6691da177e4SLinus Torvalds int ret;
6701da177e4SLinus Torvalds
6711da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 1);
6721da177e4SLinus Torvalds rme9652_spdif_write_byte (rme9652, 0x20);
6731da177e4SLinus Torvalds rme9652_spdif_write_byte (rme9652, address);
6741da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 0);
6751da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 1);
6761da177e4SLinus Torvalds
6771da177e4SLinus Torvalds rme9652_spdif_write_byte (rme9652, 0x21);
6781da177e4SLinus Torvalds ret = rme9652_spdif_read_byte (rme9652);
6791da177e4SLinus Torvalds rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 0);
6801da177e4SLinus Torvalds
6811da177e4SLinus Torvalds return ret;
6821da177e4SLinus Torvalds }
6831da177e4SLinus Torvalds
rme9652_initialize_spdif_receiver(struct snd_rme9652 * rme9652)684abfd67bdSTakashi Iwai static void rme9652_initialize_spdif_receiver (struct snd_rme9652 *rme9652)
6851da177e4SLinus Torvalds {
6861da177e4SLinus Torvalds /* XXX what unsets this ? */
6871da177e4SLinus Torvalds
6881da177e4SLinus Torvalds rme9652->control_register |= RME9652_SPDIF_RESET;
6891da177e4SLinus Torvalds
6901da177e4SLinus Torvalds rme9652_write_spdif_codec (rme9652, 4, 0x40);
6911da177e4SLinus Torvalds rme9652_write_spdif_codec (rme9652, 17, 0x13);
6921da177e4SLinus Torvalds rme9652_write_spdif_codec (rme9652, 6, 0x02);
6931da177e4SLinus Torvalds }
6941da177e4SLinus Torvalds
rme9652_spdif_sample_rate(struct snd_rme9652 * s)695abfd67bdSTakashi Iwai static inline int rme9652_spdif_sample_rate(struct snd_rme9652 *s)
6961da177e4SLinus Torvalds {
6971da177e4SLinus Torvalds unsigned int rate_bits;
6981da177e4SLinus Torvalds
6991da177e4SLinus Torvalds if (rme9652_read(s, RME9652_status_register) & RME9652_ERF) {
7001da177e4SLinus Torvalds return -1; /* error condition */
7011da177e4SLinus Torvalds }
7021da177e4SLinus Torvalds
7031da177e4SLinus Torvalds if (s->hw_rev == 15) {
7041da177e4SLinus Torvalds
7051da177e4SLinus Torvalds int x, y, ret;
7061da177e4SLinus Torvalds
7071da177e4SLinus Torvalds x = rme9652_spdif_read_codec (s, 30);
7081da177e4SLinus Torvalds
7091da177e4SLinus Torvalds if (x != 0)
7101da177e4SLinus Torvalds y = 48000 * 64 / x;
7111da177e4SLinus Torvalds else
7121da177e4SLinus Torvalds y = 0;
7131da177e4SLinus Torvalds
7141da177e4SLinus Torvalds if (y > 30400 && y < 33600) ret = 32000;
7151da177e4SLinus Torvalds else if (y > 41900 && y < 46000) ret = 44100;
7161da177e4SLinus Torvalds else if (y > 46000 && y < 50400) ret = 48000;
7171da177e4SLinus Torvalds else if (y > 60800 && y < 67200) ret = 64000;
7181da177e4SLinus Torvalds else if (y > 83700 && y < 92000) ret = 88200;
7191da177e4SLinus Torvalds else if (y > 92000 && y < 100000) ret = 96000;
7201da177e4SLinus Torvalds else ret = 0;
7211da177e4SLinus Torvalds return ret;
7221da177e4SLinus Torvalds }
7231da177e4SLinus Torvalds
7241da177e4SLinus Torvalds rate_bits = rme9652_read(s, RME9652_status_register) & RME9652_F;
7251da177e4SLinus Torvalds
7261da177e4SLinus Torvalds switch (rme9652_decode_spdif_rate(rate_bits)) {
7271da177e4SLinus Torvalds case 0x7:
7281da177e4SLinus Torvalds return 32000;
7291da177e4SLinus Torvalds
7301da177e4SLinus Torvalds case 0x6:
7311da177e4SLinus Torvalds return 44100;
7321da177e4SLinus Torvalds
7331da177e4SLinus Torvalds case 0x5:
7341da177e4SLinus Torvalds return 48000;
7351da177e4SLinus Torvalds
7361da177e4SLinus Torvalds case 0x4:
7371da177e4SLinus Torvalds return 88200;
7381da177e4SLinus Torvalds
7391da177e4SLinus Torvalds case 0x3:
7401da177e4SLinus Torvalds return 96000;
7411da177e4SLinus Torvalds
7421da177e4SLinus Torvalds case 0x0:
7431da177e4SLinus Torvalds return 64000;
7441da177e4SLinus Torvalds
7451da177e4SLinus Torvalds default:
74609ae539eSTakashi Iwai dev_err(s->card->dev,
74709ae539eSTakashi Iwai "%s: unknown S/PDIF input rate (bits = 0x%x)\n",
7481da177e4SLinus Torvalds s->card_name, rate_bits);
7491da177e4SLinus Torvalds return 0;
7501da177e4SLinus Torvalds }
7511da177e4SLinus Torvalds }
7521da177e4SLinus Torvalds
7531da177e4SLinus Torvalds /*-----------------------------------------------------------------------------
7541da177e4SLinus Torvalds Control Interface
7551da177e4SLinus Torvalds ----------------------------------------------------------------------------*/
7561da177e4SLinus Torvalds
snd_rme9652_convert_from_aes(struct snd_aes_iec958 * aes)757abfd67bdSTakashi Iwai static u32 snd_rme9652_convert_from_aes(struct snd_aes_iec958 *aes)
7581da177e4SLinus Torvalds {
7591da177e4SLinus Torvalds u32 val = 0;
7601da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME9652_PRO : 0;
7611da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? RME9652_Dolby : 0;
7621da177e4SLinus Torvalds if (val & RME9652_PRO)
7631da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? RME9652_EMP : 0;
7641da177e4SLinus Torvalds else
7651da177e4SLinus Torvalds val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? RME9652_EMP : 0;
7661da177e4SLinus Torvalds return val;
7671da177e4SLinus Torvalds }
7681da177e4SLinus Torvalds
snd_rme9652_convert_to_aes(struct snd_aes_iec958 * aes,u32 val)769abfd67bdSTakashi Iwai static void snd_rme9652_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
7701da177e4SLinus Torvalds {
7711da177e4SLinus Torvalds aes->status[0] = ((val & RME9652_PRO) ? IEC958_AES0_PROFESSIONAL : 0) |
7721da177e4SLinus Torvalds ((val & RME9652_Dolby) ? IEC958_AES0_NONAUDIO : 0);
7731da177e4SLinus Torvalds if (val & RME9652_PRO)
7741da177e4SLinus Torvalds aes->status[0] |= (val & RME9652_EMP) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0;
7751da177e4SLinus Torvalds else
7761da177e4SLinus Torvalds aes->status[0] |= (val & RME9652_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
7771da177e4SLinus Torvalds }
7781da177e4SLinus Torvalds
snd_rme9652_control_spdif_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)779abfd67bdSTakashi Iwai static int snd_rme9652_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
7801da177e4SLinus Torvalds {
7811da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
7821da177e4SLinus Torvalds uinfo->count = 1;
7831da177e4SLinus Torvalds return 0;
7841da177e4SLinus Torvalds }
7851da177e4SLinus Torvalds
snd_rme9652_control_spdif_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)786abfd67bdSTakashi Iwai static int snd_rme9652_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7871da177e4SLinus Torvalds {
788abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
7891da177e4SLinus Torvalds
7901da177e4SLinus Torvalds snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif);
7911da177e4SLinus Torvalds return 0;
7921da177e4SLinus Torvalds }
7931da177e4SLinus Torvalds
snd_rme9652_control_spdif_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)794abfd67bdSTakashi Iwai static int snd_rme9652_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7951da177e4SLinus Torvalds {
796abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
7971da177e4SLinus Torvalds int change;
7981da177e4SLinus Torvalds u32 val;
7991da177e4SLinus Torvalds
8001da177e4SLinus Torvalds val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958);
8011da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
8021da177e4SLinus Torvalds change = val != rme9652->creg_spdif;
8031da177e4SLinus Torvalds rme9652->creg_spdif = val;
8041da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
8051da177e4SLinus Torvalds return change;
8061da177e4SLinus Torvalds }
8071da177e4SLinus Torvalds
snd_rme9652_control_spdif_stream_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)808abfd67bdSTakashi Iwai static int snd_rme9652_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
8091da177e4SLinus Torvalds {
8101da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
8111da177e4SLinus Torvalds uinfo->count = 1;
8121da177e4SLinus Torvalds return 0;
8131da177e4SLinus Torvalds }
8141da177e4SLinus Torvalds
snd_rme9652_control_spdif_stream_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)815abfd67bdSTakashi Iwai static int snd_rme9652_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8161da177e4SLinus Torvalds {
817abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
8181da177e4SLinus Torvalds
8191da177e4SLinus Torvalds snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif_stream);
8201da177e4SLinus Torvalds return 0;
8211da177e4SLinus Torvalds }
8221da177e4SLinus Torvalds
snd_rme9652_control_spdif_stream_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)823abfd67bdSTakashi Iwai static int snd_rme9652_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8241da177e4SLinus Torvalds {
825abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
8261da177e4SLinus Torvalds int change;
8271da177e4SLinus Torvalds u32 val;
8281da177e4SLinus Torvalds
8291da177e4SLinus Torvalds val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958);
8301da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
8311da177e4SLinus Torvalds change = val != rme9652->creg_spdif_stream;
8321da177e4SLinus Torvalds rme9652->creg_spdif_stream = val;
8331da177e4SLinus Torvalds rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP);
8341da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= val);
8351da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
8361da177e4SLinus Torvalds return change;
8371da177e4SLinus Torvalds }
8381da177e4SLinus Torvalds
snd_rme9652_control_spdif_mask_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)839abfd67bdSTakashi Iwai static int snd_rme9652_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
8401da177e4SLinus Torvalds {
8411da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
8421da177e4SLinus Torvalds uinfo->count = 1;
8431da177e4SLinus Torvalds return 0;
8441da177e4SLinus Torvalds }
8451da177e4SLinus Torvalds
snd_rme9652_control_spdif_mask_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)846abfd67bdSTakashi Iwai static int snd_rme9652_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8471da177e4SLinus Torvalds {
8481da177e4SLinus Torvalds ucontrol->value.iec958.status[0] = kcontrol->private_value;
8491da177e4SLinus Torvalds return 0;
8501da177e4SLinus Torvalds }
8511da177e4SLinus Torvalds
8521da177e4SLinus Torvalds #define RME9652_ADAT1_IN(xname, xindex) \
85367ed4161SClemens Ladisch { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
8541da177e4SLinus Torvalds .info = snd_rme9652_info_adat1_in, \
8551da177e4SLinus Torvalds .get = snd_rme9652_get_adat1_in, \
8561da177e4SLinus Torvalds .put = snd_rme9652_put_adat1_in }
8571da177e4SLinus Torvalds
rme9652_adat1_in(struct snd_rme9652 * rme9652)858abfd67bdSTakashi Iwai static unsigned int rme9652_adat1_in(struct snd_rme9652 *rme9652)
8591da177e4SLinus Torvalds {
8601da177e4SLinus Torvalds if (rme9652->control_register & RME9652_ADAT1_INTERNAL)
8611da177e4SLinus Torvalds return 1;
8621da177e4SLinus Torvalds return 0;
8631da177e4SLinus Torvalds }
8641da177e4SLinus Torvalds
rme9652_set_adat1_input(struct snd_rme9652 * rme9652,int internal)865abfd67bdSTakashi Iwai static int rme9652_set_adat1_input(struct snd_rme9652 *rme9652, int internal)
8661da177e4SLinus Torvalds {
8671da177e4SLinus Torvalds int restart = 0;
8681da177e4SLinus Torvalds
8691da177e4SLinus Torvalds if (internal) {
8701da177e4SLinus Torvalds rme9652->control_register |= RME9652_ADAT1_INTERNAL;
8711da177e4SLinus Torvalds } else {
8721da177e4SLinus Torvalds rme9652->control_register &= ~RME9652_ADAT1_INTERNAL;
8731da177e4SLinus Torvalds }
8741da177e4SLinus Torvalds
8751da177e4SLinus Torvalds /* XXX do we actually need to stop the card when we do this ? */
8761da177e4SLinus Torvalds
8779ebb3697STakashi Iwai restart = rme9652->running;
8789ebb3697STakashi Iwai if (restart)
8791da177e4SLinus Torvalds rme9652_stop(rme9652);
8801da177e4SLinus Torvalds
8811da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register, rme9652->control_register);
8821da177e4SLinus Torvalds
8839ebb3697STakashi Iwai if (restart)
8841da177e4SLinus Torvalds rme9652_start(rme9652);
8851da177e4SLinus Torvalds
8861da177e4SLinus Torvalds return 0;
8871da177e4SLinus Torvalds }
8881da177e4SLinus Torvalds
snd_rme9652_info_adat1_in(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)889abfd67bdSTakashi Iwai static int snd_rme9652_info_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
8901da177e4SLinus Torvalds {
8917298ece7STakashi Iwai static const char * const texts[2] = {"ADAT1", "Internal"};
8921da177e4SLinus Torvalds
8937298ece7STakashi Iwai return snd_ctl_enum_info(uinfo, 1, 2, texts);
8941da177e4SLinus Torvalds }
8951da177e4SLinus Torvalds
snd_rme9652_get_adat1_in(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)896abfd67bdSTakashi Iwai static int snd_rme9652_get_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8971da177e4SLinus Torvalds {
898abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
8991da177e4SLinus Torvalds
9001da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
9011da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = rme9652_adat1_in(rme9652);
9021da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
9031da177e4SLinus Torvalds return 0;
9041da177e4SLinus Torvalds }
9051da177e4SLinus Torvalds
snd_rme9652_put_adat1_in(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)906abfd67bdSTakashi Iwai static int snd_rme9652_put_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
9071da177e4SLinus Torvalds {
908abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
9091da177e4SLinus Torvalds int change;
9101da177e4SLinus Torvalds unsigned int val;
9111da177e4SLinus Torvalds
9121da177e4SLinus Torvalds if (!snd_rme9652_use_is_exclusive(rme9652))
9131da177e4SLinus Torvalds return -EBUSY;
9141da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % 2;
9151da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
9161da177e4SLinus Torvalds change = val != rme9652_adat1_in(rme9652);
9171da177e4SLinus Torvalds if (change)
9181da177e4SLinus Torvalds rme9652_set_adat1_input(rme9652, val);
9191da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
9201da177e4SLinus Torvalds return change;
9211da177e4SLinus Torvalds }
9221da177e4SLinus Torvalds
9231da177e4SLinus Torvalds #define RME9652_SPDIF_IN(xname, xindex) \
92467ed4161SClemens Ladisch { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
9251da177e4SLinus Torvalds .info = snd_rme9652_info_spdif_in, \
9261da177e4SLinus Torvalds .get = snd_rme9652_get_spdif_in, .put = snd_rme9652_put_spdif_in }
9271da177e4SLinus Torvalds
rme9652_spdif_in(struct snd_rme9652 * rme9652)928abfd67bdSTakashi Iwai static unsigned int rme9652_spdif_in(struct snd_rme9652 *rme9652)
9291da177e4SLinus Torvalds {
9301da177e4SLinus Torvalds return rme9652_decode_spdif_in(rme9652->control_register &
9311da177e4SLinus Torvalds RME9652_inp);
9321da177e4SLinus Torvalds }
9331da177e4SLinus Torvalds
rme9652_set_spdif_input(struct snd_rme9652 * rme9652,int in)934abfd67bdSTakashi Iwai static int rme9652_set_spdif_input(struct snd_rme9652 *rme9652, int in)
9351da177e4SLinus Torvalds {
9361da177e4SLinus Torvalds int restart = 0;
9371da177e4SLinus Torvalds
9381da177e4SLinus Torvalds rme9652->control_register &= ~RME9652_inp;
9391da177e4SLinus Torvalds rme9652->control_register |= rme9652_encode_spdif_in(in);
9401da177e4SLinus Torvalds
9419ebb3697STakashi Iwai restart = rme9652->running;
9429ebb3697STakashi Iwai if (restart)
9431da177e4SLinus Torvalds rme9652_stop(rme9652);
9441da177e4SLinus Torvalds
9451da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register, rme9652->control_register);
9461da177e4SLinus Torvalds
9479ebb3697STakashi Iwai if (restart)
9481da177e4SLinus Torvalds rme9652_start(rme9652);
9491da177e4SLinus Torvalds
9501da177e4SLinus Torvalds return 0;
9511da177e4SLinus Torvalds }
9521da177e4SLinus Torvalds
snd_rme9652_info_spdif_in(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)953abfd67bdSTakashi Iwai static int snd_rme9652_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
9541da177e4SLinus Torvalds {
9557298ece7STakashi Iwai static const char * const texts[3] = {"ADAT1", "Coaxial", "Internal"};
9561da177e4SLinus Torvalds
9577298ece7STakashi Iwai return snd_ctl_enum_info(uinfo, 1, 3, texts);
9581da177e4SLinus Torvalds }
9591da177e4SLinus Torvalds
snd_rme9652_get_spdif_in(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)960abfd67bdSTakashi Iwai static int snd_rme9652_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
9611da177e4SLinus Torvalds {
962abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
9631da177e4SLinus Torvalds
9641da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
9651da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = rme9652_spdif_in(rme9652);
9661da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
9671da177e4SLinus Torvalds return 0;
9681da177e4SLinus Torvalds }
9691da177e4SLinus Torvalds
snd_rme9652_put_spdif_in(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)970abfd67bdSTakashi Iwai static int snd_rme9652_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
9711da177e4SLinus Torvalds {
972abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
9731da177e4SLinus Torvalds int change;
9741da177e4SLinus Torvalds unsigned int val;
9751da177e4SLinus Torvalds
9761da177e4SLinus Torvalds if (!snd_rme9652_use_is_exclusive(rme9652))
9771da177e4SLinus Torvalds return -EBUSY;
9781da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % 3;
9791da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
9801da177e4SLinus Torvalds change = val != rme9652_spdif_in(rme9652);
9811da177e4SLinus Torvalds if (change)
9821da177e4SLinus Torvalds rme9652_set_spdif_input(rme9652, val);
9831da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
9841da177e4SLinus Torvalds return change;
9851da177e4SLinus Torvalds }
9861da177e4SLinus Torvalds
9871da177e4SLinus Torvalds #define RME9652_SPDIF_OUT(xname, xindex) \
98867ed4161SClemens Ladisch { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
9891da177e4SLinus Torvalds .info = snd_rme9652_info_spdif_out, \
9901da177e4SLinus Torvalds .get = snd_rme9652_get_spdif_out, .put = snd_rme9652_put_spdif_out }
9911da177e4SLinus Torvalds
rme9652_spdif_out(struct snd_rme9652 * rme9652)992abfd67bdSTakashi Iwai static int rme9652_spdif_out(struct snd_rme9652 *rme9652)
9931da177e4SLinus Torvalds {
9941da177e4SLinus Torvalds return (rme9652->control_register & RME9652_opt_out) ? 1 : 0;
9951da177e4SLinus Torvalds }
9961da177e4SLinus Torvalds
rme9652_set_spdif_output(struct snd_rme9652 * rme9652,int out)997abfd67bdSTakashi Iwai static int rme9652_set_spdif_output(struct snd_rme9652 *rme9652, int out)
9981da177e4SLinus Torvalds {
9991da177e4SLinus Torvalds int restart = 0;
10001da177e4SLinus Torvalds
10011da177e4SLinus Torvalds if (out) {
10021da177e4SLinus Torvalds rme9652->control_register |= RME9652_opt_out;
10031da177e4SLinus Torvalds } else {
10041da177e4SLinus Torvalds rme9652->control_register &= ~RME9652_opt_out;
10051da177e4SLinus Torvalds }
10061da177e4SLinus Torvalds
10079ebb3697STakashi Iwai restart = rme9652->running;
10089ebb3697STakashi Iwai if (restart)
10091da177e4SLinus Torvalds rme9652_stop(rme9652);
10101da177e4SLinus Torvalds
10111da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register, rme9652->control_register);
10121da177e4SLinus Torvalds
10139ebb3697STakashi Iwai if (restart)
10141da177e4SLinus Torvalds rme9652_start(rme9652);
10151da177e4SLinus Torvalds
10161da177e4SLinus Torvalds return 0;
10171da177e4SLinus Torvalds }
10181da177e4SLinus Torvalds
1019a5ce8890STakashi Iwai #define snd_rme9652_info_spdif_out snd_ctl_boolean_mono_info
10201da177e4SLinus Torvalds
snd_rme9652_get_spdif_out(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1021abfd67bdSTakashi Iwai static int snd_rme9652_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
10221da177e4SLinus Torvalds {
1023abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
10241da177e4SLinus Torvalds
10251da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
10261da177e4SLinus Torvalds ucontrol->value.integer.value[0] = rme9652_spdif_out(rme9652);
10271da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
10281da177e4SLinus Torvalds return 0;
10291da177e4SLinus Torvalds }
10301da177e4SLinus Torvalds
snd_rme9652_put_spdif_out(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1031abfd67bdSTakashi Iwai static int snd_rme9652_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
10321da177e4SLinus Torvalds {
1033abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
10341da177e4SLinus Torvalds int change;
10351da177e4SLinus Torvalds unsigned int val;
10361da177e4SLinus Torvalds
10371da177e4SLinus Torvalds if (!snd_rme9652_use_is_exclusive(rme9652))
10381da177e4SLinus Torvalds return -EBUSY;
10391da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1;
10401da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
10411da177e4SLinus Torvalds change = (int)val != rme9652_spdif_out(rme9652);
10421da177e4SLinus Torvalds rme9652_set_spdif_output(rme9652, val);
10431da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
10441da177e4SLinus Torvalds return change;
10451da177e4SLinus Torvalds }
10461da177e4SLinus Torvalds
10471da177e4SLinus Torvalds #define RME9652_SYNC_MODE(xname, xindex) \
104867ed4161SClemens Ladisch { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
10491da177e4SLinus Torvalds .info = snd_rme9652_info_sync_mode, \
10501da177e4SLinus Torvalds .get = snd_rme9652_get_sync_mode, .put = snd_rme9652_put_sync_mode }
10511da177e4SLinus Torvalds
rme9652_sync_mode(struct snd_rme9652 * rme9652)1052abfd67bdSTakashi Iwai static int rme9652_sync_mode(struct snd_rme9652 *rme9652)
10531da177e4SLinus Torvalds {
10541da177e4SLinus Torvalds if (rme9652->control_register & RME9652_wsel) {
10551da177e4SLinus Torvalds return 2;
10561da177e4SLinus Torvalds } else if (rme9652->control_register & RME9652_Master) {
10571da177e4SLinus Torvalds return 1;
10581da177e4SLinus Torvalds } else {
10591da177e4SLinus Torvalds return 0;
10601da177e4SLinus Torvalds }
10611da177e4SLinus Torvalds }
10621da177e4SLinus Torvalds
rme9652_set_sync_mode(struct snd_rme9652 * rme9652,int mode)1063abfd67bdSTakashi Iwai static int rme9652_set_sync_mode(struct snd_rme9652 *rme9652, int mode)
10641da177e4SLinus Torvalds {
10651da177e4SLinus Torvalds int restart = 0;
10661da177e4SLinus Torvalds
10671da177e4SLinus Torvalds switch (mode) {
10681da177e4SLinus Torvalds case 0:
10691da177e4SLinus Torvalds rme9652->control_register &=
10701da177e4SLinus Torvalds ~(RME9652_Master | RME9652_wsel);
10711da177e4SLinus Torvalds break;
10721da177e4SLinus Torvalds case 1:
10731da177e4SLinus Torvalds rme9652->control_register =
10741da177e4SLinus Torvalds (rme9652->control_register & ~RME9652_wsel) | RME9652_Master;
10751da177e4SLinus Torvalds break;
10761da177e4SLinus Torvalds case 2:
10771da177e4SLinus Torvalds rme9652->control_register |=
10781da177e4SLinus Torvalds (RME9652_Master | RME9652_wsel);
10791da177e4SLinus Torvalds break;
10801da177e4SLinus Torvalds }
10811da177e4SLinus Torvalds
10829ebb3697STakashi Iwai restart = rme9652->running;
10839ebb3697STakashi Iwai if (restart)
10841da177e4SLinus Torvalds rme9652_stop(rme9652);
10851da177e4SLinus Torvalds
10861da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register, rme9652->control_register);
10871da177e4SLinus Torvalds
10889ebb3697STakashi Iwai if (restart)
10891da177e4SLinus Torvalds rme9652_start(rme9652);
10901da177e4SLinus Torvalds
10911da177e4SLinus Torvalds return 0;
10921da177e4SLinus Torvalds }
10931da177e4SLinus Torvalds
snd_rme9652_info_sync_mode(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1094abfd67bdSTakashi Iwai static int snd_rme9652_info_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
10951da177e4SLinus Torvalds {
10967298ece7STakashi Iwai static const char * const texts[3] = {
10977298ece7STakashi Iwai "AutoSync", "Master", "Word Clock"
10987298ece7STakashi Iwai };
10991da177e4SLinus Torvalds
11007298ece7STakashi Iwai return snd_ctl_enum_info(uinfo, 1, 3, texts);
11011da177e4SLinus Torvalds }
11021da177e4SLinus Torvalds
snd_rme9652_get_sync_mode(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1103abfd67bdSTakashi Iwai static int snd_rme9652_get_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
11041da177e4SLinus Torvalds {
1105abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
11061da177e4SLinus Torvalds
11071da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
11081da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = rme9652_sync_mode(rme9652);
11091da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
11101da177e4SLinus Torvalds return 0;
11111da177e4SLinus Torvalds }
11121da177e4SLinus Torvalds
snd_rme9652_put_sync_mode(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1113abfd67bdSTakashi Iwai static int snd_rme9652_put_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
11141da177e4SLinus Torvalds {
1115abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
11161da177e4SLinus Torvalds int change;
11171da177e4SLinus Torvalds unsigned int val;
11181da177e4SLinus Torvalds
11191da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % 3;
11201da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
11211da177e4SLinus Torvalds change = (int)val != rme9652_sync_mode(rme9652);
11221da177e4SLinus Torvalds rme9652_set_sync_mode(rme9652, val);
11231da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
11241da177e4SLinus Torvalds return change;
11251da177e4SLinus Torvalds }
11261da177e4SLinus Torvalds
11271da177e4SLinus Torvalds #define RME9652_SYNC_PREF(xname, xindex) \
112867ed4161SClemens Ladisch { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
11291da177e4SLinus Torvalds .info = snd_rme9652_info_sync_pref, \
11301da177e4SLinus Torvalds .get = snd_rme9652_get_sync_pref, .put = snd_rme9652_put_sync_pref }
11311da177e4SLinus Torvalds
rme9652_sync_pref(struct snd_rme9652 * rme9652)1132abfd67bdSTakashi Iwai static int rme9652_sync_pref(struct snd_rme9652 *rme9652)
11331da177e4SLinus Torvalds {
11341da177e4SLinus Torvalds switch (rme9652->control_register & RME9652_SyncPref_Mask) {
11351da177e4SLinus Torvalds case RME9652_SyncPref_ADAT1:
11361da177e4SLinus Torvalds return RME9652_SYNC_FROM_ADAT1;
11371da177e4SLinus Torvalds case RME9652_SyncPref_ADAT2:
11381da177e4SLinus Torvalds return RME9652_SYNC_FROM_ADAT2;
11391da177e4SLinus Torvalds case RME9652_SyncPref_ADAT3:
11401da177e4SLinus Torvalds return RME9652_SYNC_FROM_ADAT3;
11411da177e4SLinus Torvalds case RME9652_SyncPref_SPDIF:
11421da177e4SLinus Torvalds return RME9652_SYNC_FROM_SPDIF;
11431da177e4SLinus Torvalds }
11441da177e4SLinus Torvalds /* Not reachable */
11451da177e4SLinus Torvalds return 0;
11461da177e4SLinus Torvalds }
11471da177e4SLinus Torvalds
rme9652_set_sync_pref(struct snd_rme9652 * rme9652,int pref)1148abfd67bdSTakashi Iwai static int rme9652_set_sync_pref(struct snd_rme9652 *rme9652, int pref)
11491da177e4SLinus Torvalds {
11501da177e4SLinus Torvalds int restart;
11511da177e4SLinus Torvalds
11521da177e4SLinus Torvalds rme9652->control_register &= ~RME9652_SyncPref_Mask;
11531da177e4SLinus Torvalds switch (pref) {
11541da177e4SLinus Torvalds case RME9652_SYNC_FROM_ADAT1:
11551da177e4SLinus Torvalds rme9652->control_register |= RME9652_SyncPref_ADAT1;
11561da177e4SLinus Torvalds break;
11571da177e4SLinus Torvalds case RME9652_SYNC_FROM_ADAT2:
11581da177e4SLinus Torvalds rme9652->control_register |= RME9652_SyncPref_ADAT2;
11591da177e4SLinus Torvalds break;
11601da177e4SLinus Torvalds case RME9652_SYNC_FROM_ADAT3:
11611da177e4SLinus Torvalds rme9652->control_register |= RME9652_SyncPref_ADAT3;
11621da177e4SLinus Torvalds break;
11631da177e4SLinus Torvalds case RME9652_SYNC_FROM_SPDIF:
11641da177e4SLinus Torvalds rme9652->control_register |= RME9652_SyncPref_SPDIF;
11651da177e4SLinus Torvalds break;
11661da177e4SLinus Torvalds }
11671da177e4SLinus Torvalds
11689ebb3697STakashi Iwai restart = rme9652->running;
11699ebb3697STakashi Iwai if (restart)
11701da177e4SLinus Torvalds rme9652_stop(rme9652);
11711da177e4SLinus Torvalds
11721da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register, rme9652->control_register);
11731da177e4SLinus Torvalds
11749ebb3697STakashi Iwai if (restart)
11751da177e4SLinus Torvalds rme9652_start(rme9652);
11761da177e4SLinus Torvalds
11771da177e4SLinus Torvalds return 0;
11781da177e4SLinus Torvalds }
11791da177e4SLinus Torvalds
snd_rme9652_info_sync_pref(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1180abfd67bdSTakashi Iwai static int snd_rme9652_info_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
11811da177e4SLinus Torvalds {
11827298ece7STakashi Iwai static const char * const texts[4] = {
11837298ece7STakashi Iwai "IEC958 In", "ADAT1 In", "ADAT2 In", "ADAT3 In"
11847298ece7STakashi Iwai };
1185abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
11861da177e4SLinus Torvalds
11877298ece7STakashi Iwai return snd_ctl_enum_info(uinfo, 1,
11887298ece7STakashi Iwai rme9652->ss_channels == RME9652_NCHANNELS ? 4 : 3,
11897298ece7STakashi Iwai texts);
11901da177e4SLinus Torvalds }
11911da177e4SLinus Torvalds
snd_rme9652_get_sync_pref(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1192abfd67bdSTakashi Iwai static int snd_rme9652_get_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
11931da177e4SLinus Torvalds {
1194abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
11951da177e4SLinus Torvalds
11961da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
11971da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = rme9652_sync_pref(rme9652);
11981da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
11991da177e4SLinus Torvalds return 0;
12001da177e4SLinus Torvalds }
12011da177e4SLinus Torvalds
snd_rme9652_put_sync_pref(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1202abfd67bdSTakashi Iwai static int snd_rme9652_put_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
12031da177e4SLinus Torvalds {
1204abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
12051da177e4SLinus Torvalds int change, max;
12061da177e4SLinus Torvalds unsigned int val;
12071da177e4SLinus Torvalds
12081da177e4SLinus Torvalds if (!snd_rme9652_use_is_exclusive(rme9652))
12091da177e4SLinus Torvalds return -EBUSY;
12101da177e4SLinus Torvalds max = rme9652->ss_channels == RME9652_NCHANNELS ? 4 : 3;
12111da177e4SLinus Torvalds val = ucontrol->value.enumerated.item[0] % max;
12121da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
12131da177e4SLinus Torvalds change = (int)val != rme9652_sync_pref(rme9652);
12141da177e4SLinus Torvalds rme9652_set_sync_pref(rme9652, val);
12151da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
12161da177e4SLinus Torvalds return change;
12171da177e4SLinus Torvalds }
12181da177e4SLinus Torvalds
snd_rme9652_info_thru(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1219abfd67bdSTakashi Iwai static int snd_rme9652_info_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
12201da177e4SLinus Torvalds {
1221abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
12221da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
12231da177e4SLinus Torvalds uinfo->count = rme9652->ss_channels;
12241da177e4SLinus Torvalds uinfo->value.integer.min = 0;
12251da177e4SLinus Torvalds uinfo->value.integer.max = 1;
12261da177e4SLinus Torvalds return 0;
12271da177e4SLinus Torvalds }
12281da177e4SLinus Torvalds
snd_rme9652_get_thru(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1229abfd67bdSTakashi Iwai static int snd_rme9652_get_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
12301da177e4SLinus Torvalds {
1231abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
12321da177e4SLinus Torvalds unsigned int k;
12331da177e4SLinus Torvalds u32 thru_bits = rme9652->thru_bits;
12341da177e4SLinus Torvalds
12351da177e4SLinus Torvalds for (k = 0; k < rme9652->ss_channels; ++k) {
12361da177e4SLinus Torvalds ucontrol->value.integer.value[k] = !!(thru_bits & (1 << k));
12371da177e4SLinus Torvalds }
12381da177e4SLinus Torvalds return 0;
12391da177e4SLinus Torvalds }
12401da177e4SLinus Torvalds
snd_rme9652_put_thru(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1241abfd67bdSTakashi Iwai static int snd_rme9652_put_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
12421da177e4SLinus Torvalds {
1243abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
12441da177e4SLinus Torvalds int change;
12451da177e4SLinus Torvalds unsigned int chn;
12461da177e4SLinus Torvalds u32 thru_bits = 0;
12471da177e4SLinus Torvalds
12481da177e4SLinus Torvalds if (!snd_rme9652_use_is_exclusive(rme9652))
12491da177e4SLinus Torvalds return -EBUSY;
12501da177e4SLinus Torvalds
12511da177e4SLinus Torvalds for (chn = 0; chn < rme9652->ss_channels; ++chn) {
12521da177e4SLinus Torvalds if (ucontrol->value.integer.value[chn])
12531da177e4SLinus Torvalds thru_bits |= 1 << chn;
12541da177e4SLinus Torvalds }
12551da177e4SLinus Torvalds
12561da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
12571da177e4SLinus Torvalds change = thru_bits ^ rme9652->thru_bits;
12581da177e4SLinus Torvalds if (change) {
12591da177e4SLinus Torvalds for (chn = 0; chn < rme9652->ss_channels; ++chn) {
12601da177e4SLinus Torvalds if (!(change & (1 << chn)))
12611da177e4SLinus Torvalds continue;
12621da177e4SLinus Torvalds rme9652_set_thru(rme9652,chn,thru_bits&(1<<chn));
12631da177e4SLinus Torvalds }
12641da177e4SLinus Torvalds }
12651da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
12661da177e4SLinus Torvalds return !!change;
12671da177e4SLinus Torvalds }
12681da177e4SLinus Torvalds
12691da177e4SLinus Torvalds #define RME9652_PASSTHRU(xname, xindex) \
127067ed4161SClemens Ladisch { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
12711da177e4SLinus Torvalds .info = snd_rme9652_info_passthru, \
12721da177e4SLinus Torvalds .put = snd_rme9652_put_passthru, \
12731da177e4SLinus Torvalds .get = snd_rme9652_get_passthru }
12741da177e4SLinus Torvalds
1275a5ce8890STakashi Iwai #define snd_rme9652_info_passthru snd_ctl_boolean_mono_info
12761da177e4SLinus Torvalds
snd_rme9652_get_passthru(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1277abfd67bdSTakashi Iwai static int snd_rme9652_get_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
12781da177e4SLinus Torvalds {
1279abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
12801da177e4SLinus Torvalds
12811da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
12821da177e4SLinus Torvalds ucontrol->value.integer.value[0] = rme9652->passthru;
12831da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
12841da177e4SLinus Torvalds return 0;
12851da177e4SLinus Torvalds }
12861da177e4SLinus Torvalds
snd_rme9652_put_passthru(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1287abfd67bdSTakashi Iwai static int snd_rme9652_put_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
12881da177e4SLinus Torvalds {
1289abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
12901da177e4SLinus Torvalds int change;
12911da177e4SLinus Torvalds unsigned int val;
12921da177e4SLinus Torvalds int err = 0;
12931da177e4SLinus Torvalds
12941da177e4SLinus Torvalds if (!snd_rme9652_use_is_exclusive(rme9652))
12951da177e4SLinus Torvalds return -EBUSY;
12961da177e4SLinus Torvalds
12971da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 1;
12981da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
12991da177e4SLinus Torvalds change = (ucontrol->value.integer.value[0] != rme9652->passthru);
13001da177e4SLinus Torvalds if (change)
13011da177e4SLinus Torvalds err = rme9652_set_passthru(rme9652, val);
13021da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
13031da177e4SLinus Torvalds return err ? err : change;
13041da177e4SLinus Torvalds }
13051da177e4SLinus Torvalds
13061da177e4SLinus Torvalds /* Read-only switches */
13071da177e4SLinus Torvalds
13081da177e4SLinus Torvalds #define RME9652_SPDIF_RATE(xname, xindex) \
130967ed4161SClemens Ladisch { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
13101da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
13111da177e4SLinus Torvalds .info = snd_rme9652_info_spdif_rate, \
13121da177e4SLinus Torvalds .get = snd_rme9652_get_spdif_rate }
13131da177e4SLinus Torvalds
snd_rme9652_info_spdif_rate(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1314abfd67bdSTakashi Iwai static int snd_rme9652_info_spdif_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
13151da177e4SLinus Torvalds {
13161da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
13171da177e4SLinus Torvalds uinfo->count = 1;
13181da177e4SLinus Torvalds uinfo->value.integer.min = 0;
13191da177e4SLinus Torvalds uinfo->value.integer.max = 96000;
13201da177e4SLinus Torvalds return 0;
13211da177e4SLinus Torvalds }
13221da177e4SLinus Torvalds
snd_rme9652_get_spdif_rate(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1323abfd67bdSTakashi Iwai static int snd_rme9652_get_spdif_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
13241da177e4SLinus Torvalds {
1325abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
13261da177e4SLinus Torvalds
13271da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
13281da177e4SLinus Torvalds ucontrol->value.integer.value[0] = rme9652_spdif_sample_rate(rme9652);
13291da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
13301da177e4SLinus Torvalds return 0;
13311da177e4SLinus Torvalds }
13321da177e4SLinus Torvalds
13331da177e4SLinus Torvalds #define RME9652_ADAT_SYNC(xname, xindex, xidx) \
133467ed4161SClemens Ladisch { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
13351da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
13361da177e4SLinus Torvalds .info = snd_rme9652_info_adat_sync, \
13371da177e4SLinus Torvalds .get = snd_rme9652_get_adat_sync, .private_value = xidx }
13381da177e4SLinus Torvalds
snd_rme9652_info_adat_sync(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1339abfd67bdSTakashi Iwai static int snd_rme9652_info_adat_sync(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
13401da177e4SLinus Torvalds {
13417298ece7STakashi Iwai static const char * const texts[4] = {
13427298ece7STakashi Iwai "No Lock", "Lock", "No Lock Sync", "Lock Sync"
13437298ece7STakashi Iwai };
13441da177e4SLinus Torvalds
13457298ece7STakashi Iwai return snd_ctl_enum_info(uinfo, 1, 4, texts);
13461da177e4SLinus Torvalds }
13471da177e4SLinus Torvalds
snd_rme9652_get_adat_sync(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1348abfd67bdSTakashi Iwai static int snd_rme9652_get_adat_sync(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
13491da177e4SLinus Torvalds {
1350abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
13511da177e4SLinus Torvalds unsigned int mask1, mask2, val;
13521da177e4SLinus Torvalds
13531da177e4SLinus Torvalds switch (kcontrol->private_value) {
13541da177e4SLinus Torvalds case 0: mask1 = RME9652_lock_0; mask2 = RME9652_sync_0; break;
13551da177e4SLinus Torvalds case 1: mask1 = RME9652_lock_1; mask2 = RME9652_sync_1; break;
13561da177e4SLinus Torvalds case 2: mask1 = RME9652_lock_2; mask2 = RME9652_sync_2; break;
13571da177e4SLinus Torvalds default: return -EINVAL;
13581da177e4SLinus Torvalds }
13591da177e4SLinus Torvalds val = rme9652_read(rme9652, RME9652_status_register);
13601da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = (val & mask1) ? 1 : 0;
13611da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] |= (val & mask2) ? 2 : 0;
13621da177e4SLinus Torvalds return 0;
13631da177e4SLinus Torvalds }
13641da177e4SLinus Torvalds
13651da177e4SLinus Torvalds #define RME9652_TC_VALID(xname, xindex) \
136667ed4161SClemens Ladisch { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
13671da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
13681da177e4SLinus Torvalds .info = snd_rme9652_info_tc_valid, \
13691da177e4SLinus Torvalds .get = snd_rme9652_get_tc_valid }
13701da177e4SLinus Torvalds
1371a5ce8890STakashi Iwai #define snd_rme9652_info_tc_valid snd_ctl_boolean_mono_info
13721da177e4SLinus Torvalds
snd_rme9652_get_tc_valid(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1373abfd67bdSTakashi Iwai static int snd_rme9652_get_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
13741da177e4SLinus Torvalds {
1375abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
13761da177e4SLinus Torvalds
13771da177e4SLinus Torvalds ucontrol->value.integer.value[0] =
13781da177e4SLinus Torvalds (rme9652_read(rme9652, RME9652_status_register) & RME9652_tc_valid) ? 1 : 0;
13791da177e4SLinus Torvalds return 0;
13801da177e4SLinus Torvalds }
13811da177e4SLinus Torvalds
138244456d37SOlaf Hering #ifdef ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE
13831da177e4SLinus Torvalds
13841da177e4SLinus Torvalds /* FIXME: this routine needs a port to the new control API --jk */
13851da177e4SLinus Torvalds
snd_rme9652_get_tc_value(void * private_data,snd_kswitch_t * kswitch,snd_switch_t * uswitch)13861da177e4SLinus Torvalds static int snd_rme9652_get_tc_value(void *private_data,
13871da177e4SLinus Torvalds snd_kswitch_t *kswitch,
13881da177e4SLinus Torvalds snd_switch_t *uswitch)
13891da177e4SLinus Torvalds {
1390abfd67bdSTakashi Iwai struct snd_rme9652 *s = (struct snd_rme9652 *) private_data;
13911da177e4SLinus Torvalds u32 value;
13921da177e4SLinus Torvalds int i;
13931da177e4SLinus Torvalds
13941da177e4SLinus Torvalds uswitch->type = SNDRV_SW_TYPE_DWORD;
13951da177e4SLinus Torvalds
13961da177e4SLinus Torvalds if ((rme9652_read(s, RME9652_status_register) &
13971da177e4SLinus Torvalds RME9652_tc_valid) == 0) {
13981da177e4SLinus Torvalds uswitch->value.data32[0] = 0;
13991da177e4SLinus Torvalds return 0;
14001da177e4SLinus Torvalds }
14011da177e4SLinus Torvalds
14021da177e4SLinus Torvalds /* timecode request */
14031da177e4SLinus Torvalds
14041da177e4SLinus Torvalds rme9652_write(s, RME9652_time_code, 0);
14051da177e4SLinus Torvalds
14061da177e4SLinus Torvalds /* XXX bug alert: loop-based timing !!!! */
14071da177e4SLinus Torvalds
14081da177e4SLinus Torvalds for (i = 0; i < 50; i++) {
14091da177e4SLinus Torvalds if (!(rme9652_read(s, i * 4) & RME9652_tc_busy))
14101da177e4SLinus Torvalds break;
14111da177e4SLinus Torvalds }
14121da177e4SLinus Torvalds
14131da177e4SLinus Torvalds if (!(rme9652_read(s, i * 4) & RME9652_tc_busy)) {
14141da177e4SLinus Torvalds return -EIO;
14151da177e4SLinus Torvalds }
14161da177e4SLinus Torvalds
14171da177e4SLinus Torvalds value = 0;
14181da177e4SLinus Torvalds
14191da177e4SLinus Torvalds for (i = 0; i < 32; i++) {
14201da177e4SLinus Torvalds value >>= 1;
14211da177e4SLinus Torvalds
14221da177e4SLinus Torvalds if (rme9652_read(s, i * 4) & RME9652_tc_out)
14231da177e4SLinus Torvalds value |= 0x80000000;
14241da177e4SLinus Torvalds }
14251da177e4SLinus Torvalds
14261da177e4SLinus Torvalds if (value > 2 * 60 * 48000) {
14271da177e4SLinus Torvalds value -= 2 * 60 * 48000;
14281da177e4SLinus Torvalds } else {
14291da177e4SLinus Torvalds value = 0;
14301da177e4SLinus Torvalds }
14311da177e4SLinus Torvalds
14321da177e4SLinus Torvalds uswitch->value.data32[0] = value;
14331da177e4SLinus Torvalds
14341da177e4SLinus Torvalds return 0;
14351da177e4SLinus Torvalds }
14361da177e4SLinus Torvalds
14371da177e4SLinus Torvalds #endif /* ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE */
14381da177e4SLinus Torvalds
1439b4e5e707STakashi Iwai static const struct snd_kcontrol_new snd_rme9652_controls[] = {
14401da177e4SLinus Torvalds {
14415549d549SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM,
14421da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
14431da177e4SLinus Torvalds .info = snd_rme9652_control_spdif_info,
14441da177e4SLinus Torvalds .get = snd_rme9652_control_spdif_get,
14451da177e4SLinus Torvalds .put = snd_rme9652_control_spdif_put,
14461da177e4SLinus Torvalds },
14471da177e4SLinus Torvalds {
14481da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
14495549d549SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM,
14501da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
14511da177e4SLinus Torvalds .info = snd_rme9652_control_spdif_stream_info,
14521da177e4SLinus Torvalds .get = snd_rme9652_control_spdif_stream_get,
14531da177e4SLinus Torvalds .put = snd_rme9652_control_spdif_stream_put,
14541da177e4SLinus Torvalds },
14551da177e4SLinus Torvalds {
14561da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ,
14575549d549SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM,
14581da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
14591da177e4SLinus Torvalds .info = snd_rme9652_control_spdif_mask_info,
14601da177e4SLinus Torvalds .get = snd_rme9652_control_spdif_mask_get,
14611da177e4SLinus Torvalds .private_value = IEC958_AES0_NONAUDIO |
14621da177e4SLinus Torvalds IEC958_AES0_PROFESSIONAL |
14631da177e4SLinus Torvalds IEC958_AES0_CON_EMPHASIS,
14641da177e4SLinus Torvalds },
14651da177e4SLinus Torvalds {
14661da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ,
14675549d549SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM,
14681da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
14691da177e4SLinus Torvalds .info = snd_rme9652_control_spdif_mask_info,
14701da177e4SLinus Torvalds .get = snd_rme9652_control_spdif_mask_get,
14711da177e4SLinus Torvalds .private_value = IEC958_AES0_NONAUDIO |
14721da177e4SLinus Torvalds IEC958_AES0_PROFESSIONAL |
14731da177e4SLinus Torvalds IEC958_AES0_PRO_EMPHASIS,
14741da177e4SLinus Torvalds },
14751da177e4SLinus Torvalds RME9652_SPDIF_IN("IEC958 Input Connector", 0),
14761da177e4SLinus Torvalds RME9652_SPDIF_OUT("IEC958 Output also on ADAT1", 0),
14771da177e4SLinus Torvalds RME9652_SYNC_MODE("Sync Mode", 0),
14781da177e4SLinus Torvalds RME9652_SYNC_PREF("Preferred Sync Source", 0),
14791da177e4SLinus Torvalds {
148067ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
14811da177e4SLinus Torvalds .name = "Channels Thru",
14821da177e4SLinus Torvalds .index = 0,
14831da177e4SLinus Torvalds .info = snd_rme9652_info_thru,
14841da177e4SLinus Torvalds .get = snd_rme9652_get_thru,
14851da177e4SLinus Torvalds .put = snd_rme9652_put_thru,
14861da177e4SLinus Torvalds },
14871da177e4SLinus Torvalds RME9652_SPDIF_RATE("IEC958 Sample Rate", 0),
14881da177e4SLinus Torvalds RME9652_ADAT_SYNC("ADAT1 Sync Check", 0, 0),
14891da177e4SLinus Torvalds RME9652_ADAT_SYNC("ADAT2 Sync Check", 0, 1),
14901da177e4SLinus Torvalds RME9652_TC_VALID("Timecode Valid", 0),
14911da177e4SLinus Torvalds RME9652_PASSTHRU("Passthru", 0)
14921da177e4SLinus Torvalds };
14931da177e4SLinus Torvalds
1494b4e5e707STakashi Iwai static const struct snd_kcontrol_new snd_rme9652_adat3_check =
14951da177e4SLinus Torvalds RME9652_ADAT_SYNC("ADAT3 Sync Check", 0, 2);
14961da177e4SLinus Torvalds
1497b4e5e707STakashi Iwai static const struct snd_kcontrol_new snd_rme9652_adat1_input =
14981da177e4SLinus Torvalds RME9652_ADAT1_IN("ADAT1 Input Source", 0);
14991da177e4SLinus Torvalds
snd_rme9652_create_controls(struct snd_card * card,struct snd_rme9652 * rme9652)1500abfd67bdSTakashi Iwai static int snd_rme9652_create_controls(struct snd_card *card, struct snd_rme9652 *rme9652)
15011da177e4SLinus Torvalds {
15021da177e4SLinus Torvalds unsigned int idx;
15031da177e4SLinus Torvalds int err;
1504abfd67bdSTakashi Iwai struct snd_kcontrol *kctl;
15051da177e4SLinus Torvalds
15061da177e4SLinus Torvalds for (idx = 0; idx < ARRAY_SIZE(snd_rme9652_controls); idx++) {
15079ebb3697STakashi Iwai kctl = snd_ctl_new1(&snd_rme9652_controls[idx], rme9652);
15089ebb3697STakashi Iwai err = snd_ctl_add(card, kctl);
15099ebb3697STakashi Iwai if (err < 0)
15101da177e4SLinus Torvalds return err;
15111da177e4SLinus Torvalds if (idx == 1) /* IEC958 (S/PDIF) Stream */
15121da177e4SLinus Torvalds rme9652->spdif_ctl = kctl;
15131da177e4SLinus Torvalds }
15141da177e4SLinus Torvalds
15159ebb3697STakashi Iwai if (rme9652->ss_channels == RME9652_NCHANNELS) {
15169ebb3697STakashi Iwai kctl = snd_ctl_new1(&snd_rme9652_adat3_check, rme9652);
15179ebb3697STakashi Iwai err = snd_ctl_add(card, kctl);
15189ebb3697STakashi Iwai if (err < 0)
15191da177e4SLinus Torvalds return err;
15209ebb3697STakashi Iwai }
15211da177e4SLinus Torvalds
15229ebb3697STakashi Iwai if (rme9652->hw_rev >= 15) {
15239ebb3697STakashi Iwai kctl = snd_ctl_new1(&snd_rme9652_adat1_input, rme9652);
15249ebb3697STakashi Iwai err = snd_ctl_add(card, kctl);
15259ebb3697STakashi Iwai if (err < 0)
15261da177e4SLinus Torvalds return err;
15279ebb3697STakashi Iwai }
15281da177e4SLinus Torvalds
15291da177e4SLinus Torvalds return 0;
15301da177e4SLinus Torvalds }
15311da177e4SLinus Torvalds
15321da177e4SLinus Torvalds /*------------------------------------------------------------
15331da177e4SLinus Torvalds /proc interface
15341da177e4SLinus Torvalds ------------------------------------------------------------*/
15351da177e4SLinus Torvalds
15361da177e4SLinus Torvalds static void
snd_rme9652_proc_read(struct snd_info_entry * entry,struct snd_info_buffer * buffer)1537abfd67bdSTakashi Iwai snd_rme9652_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
15381da177e4SLinus Torvalds {
1539abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) entry->private_data;
15401da177e4SLinus Torvalds u32 thru_bits = rme9652->thru_bits;
15411da177e4SLinus Torvalds int show_auto_sync_source = 0;
15421da177e4SLinus Torvalds int i;
15431da177e4SLinus Torvalds unsigned int status;
15441da177e4SLinus Torvalds int x;
15451da177e4SLinus Torvalds
15461da177e4SLinus Torvalds status = rme9652_read(rme9652, RME9652_status_register);
15471da177e4SLinus Torvalds
15481da177e4SLinus Torvalds snd_iprintf(buffer, "%s (Card #%d)\n", rme9652->card_name, rme9652->card->number + 1);
15491da177e4SLinus Torvalds snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
15501da177e4SLinus Torvalds rme9652->capture_buffer, rme9652->playback_buffer);
15511da177e4SLinus Torvalds snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
15521da177e4SLinus Torvalds rme9652->irq, rme9652->port, (unsigned long)rme9652->iobase);
15531da177e4SLinus Torvalds snd_iprintf(buffer, "Control register: %x\n", rme9652->control_register);
15541da177e4SLinus Torvalds
15551da177e4SLinus Torvalds snd_iprintf(buffer, "\n");
15561da177e4SLinus Torvalds
15571da177e4SLinus Torvalds x = 1 << (6 + rme9652_decode_latency(rme9652->control_register &
15581da177e4SLinus Torvalds RME9652_latency));
15591da177e4SLinus Torvalds
15601da177e4SLinus Torvalds snd_iprintf(buffer, "Latency: %d samples (2 periods of %lu bytes)\n",
15611da177e4SLinus Torvalds x, (unsigned long) rme9652->period_bytes);
15621da177e4SLinus Torvalds snd_iprintf(buffer, "Hardware pointer (frames): %ld\n",
15631da177e4SLinus Torvalds rme9652_hw_pointer(rme9652));
1564b48f2f75STakashi Iwai snd_iprintf(buffer, "Passthru: %s\n", str_yes_no(rme9652->passthru));
15651da177e4SLinus Torvalds
15661da177e4SLinus Torvalds if ((rme9652->control_register & (RME9652_Master | RME9652_wsel)) == 0) {
15671da177e4SLinus Torvalds snd_iprintf(buffer, "Clock mode: autosync\n");
15681da177e4SLinus Torvalds show_auto_sync_source = 1;
15691da177e4SLinus Torvalds } else if (rme9652->control_register & RME9652_wsel) {
15701da177e4SLinus Torvalds if (status & RME9652_wsel_rd) {
15711da177e4SLinus Torvalds snd_iprintf(buffer, "Clock mode: word clock\n");
15721da177e4SLinus Torvalds } else {
15731da177e4SLinus Torvalds snd_iprintf(buffer, "Clock mode: word clock (no signal)\n");
15741da177e4SLinus Torvalds }
15751da177e4SLinus Torvalds } else {
15761da177e4SLinus Torvalds snd_iprintf(buffer, "Clock mode: master\n");
15771da177e4SLinus Torvalds }
15781da177e4SLinus Torvalds
15791da177e4SLinus Torvalds if (show_auto_sync_source) {
15801da177e4SLinus Torvalds switch (rme9652->control_register & RME9652_SyncPref_Mask) {
15811da177e4SLinus Torvalds case RME9652_SyncPref_ADAT1:
15821da177e4SLinus Torvalds snd_iprintf(buffer, "Pref. sync source: ADAT1\n");
15831da177e4SLinus Torvalds break;
15841da177e4SLinus Torvalds case RME9652_SyncPref_ADAT2:
15851da177e4SLinus Torvalds snd_iprintf(buffer, "Pref. sync source: ADAT2\n");
15861da177e4SLinus Torvalds break;
15871da177e4SLinus Torvalds case RME9652_SyncPref_ADAT3:
15881da177e4SLinus Torvalds snd_iprintf(buffer, "Pref. sync source: ADAT3\n");
15891da177e4SLinus Torvalds break;
15901da177e4SLinus Torvalds case RME9652_SyncPref_SPDIF:
15911da177e4SLinus Torvalds snd_iprintf(buffer, "Pref. sync source: IEC958\n");
15921da177e4SLinus Torvalds break;
15931da177e4SLinus Torvalds default:
15941da177e4SLinus Torvalds snd_iprintf(buffer, "Pref. sync source: ???\n");
15951da177e4SLinus Torvalds }
15961da177e4SLinus Torvalds }
15971da177e4SLinus Torvalds
15981da177e4SLinus Torvalds if (rme9652->hw_rev >= 15)
15991da177e4SLinus Torvalds snd_iprintf(buffer, "\nADAT1 Input source: %s\n",
16001da177e4SLinus Torvalds (rme9652->control_register & RME9652_ADAT1_INTERNAL) ?
16011da177e4SLinus Torvalds "Internal" : "ADAT1 optical");
16021da177e4SLinus Torvalds
16031da177e4SLinus Torvalds snd_iprintf(buffer, "\n");
16041da177e4SLinus Torvalds
16051da177e4SLinus Torvalds switch (rme9652_decode_spdif_in(rme9652->control_register &
16061da177e4SLinus Torvalds RME9652_inp)) {
16071da177e4SLinus Torvalds case RME9652_SPDIFIN_OPTICAL:
16081da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 input: ADAT1\n");
16091da177e4SLinus Torvalds break;
16101da177e4SLinus Torvalds case RME9652_SPDIFIN_COAXIAL:
16111da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 input: Coaxial\n");
16121da177e4SLinus Torvalds break;
16131da177e4SLinus Torvalds case RME9652_SPDIFIN_INTERN:
16141da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 input: Internal\n");
16151da177e4SLinus Torvalds break;
16161da177e4SLinus Torvalds default:
16171da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 input: ???\n");
16181da177e4SLinus Torvalds break;
16191da177e4SLinus Torvalds }
16201da177e4SLinus Torvalds
16211da177e4SLinus Torvalds if (rme9652->control_register & RME9652_opt_out) {
16221da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n");
16231da177e4SLinus Torvalds } else {
16241da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 output: Coaxial only\n");
16251da177e4SLinus Torvalds }
16261da177e4SLinus Torvalds
16271da177e4SLinus Torvalds if (rme9652->control_register & RME9652_PRO) {
16281da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 quality: Professional\n");
16291da177e4SLinus Torvalds } else {
16301da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 quality: Consumer\n");
16311da177e4SLinus Torvalds }
16321da177e4SLinus Torvalds
16331da177e4SLinus Torvalds if (rme9652->control_register & RME9652_EMP) {
16341da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 emphasis: on\n");
16351da177e4SLinus Torvalds } else {
16361da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 emphasis: off\n");
16371da177e4SLinus Torvalds }
16381da177e4SLinus Torvalds
16391da177e4SLinus Torvalds if (rme9652->control_register & RME9652_Dolby) {
16401da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 Dolby: on\n");
16411da177e4SLinus Torvalds } else {
16421da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 Dolby: off\n");
16431da177e4SLinus Torvalds }
16441da177e4SLinus Torvalds
16451da177e4SLinus Torvalds i = rme9652_spdif_sample_rate(rme9652);
16461da177e4SLinus Torvalds
16471da177e4SLinus Torvalds if (i < 0) {
16481da177e4SLinus Torvalds snd_iprintf(buffer,
16491da177e4SLinus Torvalds "IEC958 sample rate: error flag set\n");
16501da177e4SLinus Torvalds } else if (i == 0) {
16511da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 sample rate: undetermined\n");
16521da177e4SLinus Torvalds } else {
16531da177e4SLinus Torvalds snd_iprintf(buffer, "IEC958 sample rate: %d\n", i);
16541da177e4SLinus Torvalds }
16551da177e4SLinus Torvalds
16561da177e4SLinus Torvalds snd_iprintf(buffer, "\n");
16571da177e4SLinus Torvalds
16581da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT Sample rate: %dHz\n",
16591da177e4SLinus Torvalds rme9652_adat_sample_rate(rme9652));
16601da177e4SLinus Torvalds
16611da177e4SLinus Torvalds /* Sync Check */
16621da177e4SLinus Torvalds
16631da177e4SLinus Torvalds x = status & RME9652_sync_0;
16641da177e4SLinus Torvalds if (status & RME9652_lock_0) {
16651da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock");
16661da177e4SLinus Torvalds } else {
16671da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT1: No Lock\n");
16681da177e4SLinus Torvalds }
16691da177e4SLinus Torvalds
16701da177e4SLinus Torvalds x = status & RME9652_sync_1;
16711da177e4SLinus Torvalds if (status & RME9652_lock_1) {
16721da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock");
16731da177e4SLinus Torvalds } else {
16741da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT2: No Lock\n");
16751da177e4SLinus Torvalds }
16761da177e4SLinus Torvalds
16771da177e4SLinus Torvalds x = status & RME9652_sync_2;
16781da177e4SLinus Torvalds if (status & RME9652_lock_2) {
16791da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock");
16801da177e4SLinus Torvalds } else {
16811da177e4SLinus Torvalds snd_iprintf(buffer, "ADAT3: No Lock\n");
16821da177e4SLinus Torvalds }
16831da177e4SLinus Torvalds
16841da177e4SLinus Torvalds snd_iprintf(buffer, "\n");
16851da177e4SLinus Torvalds
16861da177e4SLinus Torvalds snd_iprintf(buffer, "Timecode signal: %s\n",
1687b48f2f75STakashi Iwai str_yes_no(status & RME9652_tc_valid));
16881da177e4SLinus Torvalds
16891da177e4SLinus Torvalds /* thru modes */
16901da177e4SLinus Torvalds
16911da177e4SLinus Torvalds snd_iprintf(buffer, "Punch Status:\n\n");
16921da177e4SLinus Torvalds
16931da177e4SLinus Torvalds for (i = 0; i < rme9652->ss_channels; i++) {
16941da177e4SLinus Torvalds if (thru_bits & (1 << i)) {
16951da177e4SLinus Torvalds snd_iprintf(buffer, "%2d: on ", i + 1);
16961da177e4SLinus Torvalds } else {
16971da177e4SLinus Torvalds snd_iprintf(buffer, "%2d: off ", i + 1);
16981da177e4SLinus Torvalds }
16991da177e4SLinus Torvalds
17001da177e4SLinus Torvalds if (((i + 1) % 8) == 0) {
17011da177e4SLinus Torvalds snd_iprintf(buffer, "\n");
17021da177e4SLinus Torvalds }
17031da177e4SLinus Torvalds }
17041da177e4SLinus Torvalds
17051da177e4SLinus Torvalds snd_iprintf(buffer, "\n");
17061da177e4SLinus Torvalds }
17071da177e4SLinus Torvalds
snd_rme9652_proc_init(struct snd_rme9652 * rme9652)1708e23e7a14SBill Pemberton static void snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
17091da177e4SLinus Torvalds {
171047f2769bSTakashi Iwai snd_card_ro_proc_new(rme9652->card, "rme9652", rme9652,
171147f2769bSTakashi Iwai snd_rme9652_proc_read);
17121da177e4SLinus Torvalds }
17131da177e4SLinus Torvalds
snd_rme9652_card_free(struct snd_card * card)1714b1002b2dSTakashi Iwai static void snd_rme9652_card_free(struct snd_card *card)
17151da177e4SLinus Torvalds {
1716b1002b2dSTakashi Iwai struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) card->private_data;
17171da177e4SLinus Torvalds
17181da177e4SLinus Torvalds if (rme9652->irq >= 0)
17191da177e4SLinus Torvalds rme9652_stop(rme9652);
17201da177e4SLinus Torvalds }
17211da177e4SLinus Torvalds
snd_rme9652_initialize_memory(struct snd_rme9652 * rme9652)1722e23e7a14SBill Pemberton static int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
17231da177e4SLinus Torvalds {
172443d35cccSTakashi Iwai struct snd_dma_buffer *capture_dma, *playback_dma;
17251da177e4SLinus Torvalds
172643d35cccSTakashi Iwai capture_dma = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES);
172743d35cccSTakashi Iwai playback_dma = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES);
172843d35cccSTakashi Iwai if (!capture_dma || !playback_dma) {
172909ae539eSTakashi Iwai dev_err(rme9652->card->dev,
173009ae539eSTakashi Iwai "%s: no buffers available\n", rme9652->card_name);
17311da177e4SLinus Torvalds return -ENOMEM;
17321da177e4SLinus Torvalds }
17331da177e4SLinus Torvalds
173443d35cccSTakashi Iwai /* copy to the own data for alignment */
173543d35cccSTakashi Iwai rme9652->capture_dma_buf = *capture_dma;
173643d35cccSTakashi Iwai rme9652->playback_dma_buf = *playback_dma;
17371da177e4SLinus Torvalds
173843d35cccSTakashi Iwai /* Align to bus-space 64K boundary */
173943d35cccSTakashi Iwai rme9652->capture_dma_buf.addr = ALIGN(capture_dma->addr, 0x10000ul);
174043d35cccSTakashi Iwai rme9652->playback_dma_buf.addr = ALIGN(playback_dma->addr, 0x10000ul);
17411da177e4SLinus Torvalds
17421da177e4SLinus Torvalds /* Tell the card where it is */
174343d35cccSTakashi Iwai rme9652_write(rme9652, RME9652_rec_buffer, rme9652->capture_dma_buf.addr);
174443d35cccSTakashi Iwai rme9652_write(rme9652, RME9652_play_buffer, rme9652->playback_dma_buf.addr);
17451da177e4SLinus Torvalds
174643d35cccSTakashi Iwai rme9652->capture_dma_buf.area += rme9652->capture_dma_buf.addr - capture_dma->addr;
174743d35cccSTakashi Iwai rme9652->playback_dma_buf.area += rme9652->playback_dma_buf.addr - playback_dma->addr;
174843d35cccSTakashi Iwai rme9652->capture_buffer = rme9652->capture_dma_buf.area;
174943d35cccSTakashi Iwai rme9652->playback_buffer = rme9652->playback_dma_buf.area;
17501da177e4SLinus Torvalds
17511da177e4SLinus Torvalds return 0;
17521da177e4SLinus Torvalds }
17531da177e4SLinus Torvalds
snd_rme9652_set_defaults(struct snd_rme9652 * rme9652)1754abfd67bdSTakashi Iwai static void snd_rme9652_set_defaults(struct snd_rme9652 *rme9652)
17551da177e4SLinus Torvalds {
17561da177e4SLinus Torvalds unsigned int k;
17571da177e4SLinus Torvalds
17581da177e4SLinus Torvalds /* ASSUMPTION: rme9652->lock is either held, or
17591da177e4SLinus Torvalds there is no need to hold it (e.g. during module
1760561de31aSJoe Perches initialization).
17611da177e4SLinus Torvalds */
17621da177e4SLinus Torvalds
17631da177e4SLinus Torvalds /* set defaults:
17641da177e4SLinus Torvalds
17651da177e4SLinus Torvalds SPDIF Input via Coax
17661da177e4SLinus Torvalds autosync clock mode
17671da177e4SLinus Torvalds maximum latency (7 = 8192 samples, 64Kbyte buffer,
17681da177e4SLinus Torvalds which implies 2 4096 sample, 32Kbyte periods).
17691da177e4SLinus Torvalds
17701da177e4SLinus Torvalds if rev 1.5, initialize the S/PDIF receiver.
17711da177e4SLinus Torvalds
17721da177e4SLinus Torvalds */
17731da177e4SLinus Torvalds
17741da177e4SLinus Torvalds rme9652->control_register =
17751da177e4SLinus Torvalds RME9652_inp_0 | rme9652_encode_latency(7);
17761da177e4SLinus Torvalds
17771da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register, rme9652->control_register);
17781da177e4SLinus Torvalds
17791da177e4SLinus Torvalds rme9652_reset_hw_pointer(rme9652);
17801da177e4SLinus Torvalds rme9652_compute_period_size(rme9652);
17811da177e4SLinus Torvalds
17821da177e4SLinus Torvalds /* default: thru off for all channels */
17831da177e4SLinus Torvalds
17841da177e4SLinus Torvalds for (k = 0; k < RME9652_NCHANNELS; ++k)
17851da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_thru_base + k * 4, 0);
17861da177e4SLinus Torvalds
17871da177e4SLinus Torvalds rme9652->thru_bits = 0;
17881da177e4SLinus Torvalds rme9652->passthru = 0;
17891da177e4SLinus Torvalds
17901da177e4SLinus Torvalds /* set a default rate so that the channel map is set up */
17911da177e4SLinus Torvalds
17921da177e4SLinus Torvalds rme9652_set_rate(rme9652, 48000);
17931da177e4SLinus Torvalds }
17941da177e4SLinus Torvalds
snd_rme9652_interrupt(int irq,void * dev_id)17957d12e780SDavid Howells static irqreturn_t snd_rme9652_interrupt(int irq, void *dev_id)
17961da177e4SLinus Torvalds {
1797abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) dev_id;
17981da177e4SLinus Torvalds
17991da177e4SLinus Torvalds if (!(rme9652_read(rme9652, RME9652_status_register) & RME9652_IRQ)) {
18001da177e4SLinus Torvalds return IRQ_NONE;
18011da177e4SLinus Torvalds }
18021da177e4SLinus Torvalds
18031da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_irq_clear, 0);
18041da177e4SLinus Torvalds
18051da177e4SLinus Torvalds if (rme9652->capture_substream) {
18061da177e4SLinus Torvalds snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
18071da177e4SLinus Torvalds }
18081da177e4SLinus Torvalds
18091da177e4SLinus Torvalds if (rme9652->playback_substream) {
18101da177e4SLinus Torvalds snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
18111da177e4SLinus Torvalds }
18121da177e4SLinus Torvalds return IRQ_HANDLED;
18131da177e4SLinus Torvalds }
18141da177e4SLinus Torvalds
snd_rme9652_hw_pointer(struct snd_pcm_substream * substream)1815abfd67bdSTakashi Iwai static snd_pcm_uframes_t snd_rme9652_hw_pointer(struct snd_pcm_substream *substream)
18161da177e4SLinus Torvalds {
1817abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
18181da177e4SLinus Torvalds return rme9652_hw_pointer(rme9652);
18191da177e4SLinus Torvalds }
18201da177e4SLinus Torvalds
rme9652_channel_buffer_location(struct snd_rme9652 * rme9652,int stream,int channel)182150895a55SJason A. Donenfeld static signed char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652,
18221da177e4SLinus Torvalds int stream,
18231da177e4SLinus Torvalds int channel)
18241da177e4SLinus Torvalds
18251da177e4SLinus Torvalds {
18261da177e4SLinus Torvalds int mapped_channel;
18271da177e4SLinus Torvalds
1828da3cec35STakashi Iwai if (snd_BUG_ON(channel < 0 || channel >= RME9652_NCHANNELS))
1829da3cec35STakashi Iwai return NULL;
18301da177e4SLinus Torvalds
18319ebb3697STakashi Iwai mapped_channel = rme9652->channel_map[channel];
18329ebb3697STakashi Iwai if (mapped_channel < 0)
18331da177e4SLinus Torvalds return NULL;
18341da177e4SLinus Torvalds
18351da177e4SLinus Torvalds if (stream == SNDRV_PCM_STREAM_CAPTURE) {
18361da177e4SLinus Torvalds return rme9652->capture_buffer +
18371da177e4SLinus Torvalds (mapped_channel * RME9652_CHANNEL_BUFFER_BYTES);
18381da177e4SLinus Torvalds } else {
18391da177e4SLinus Torvalds return rme9652->playback_buffer +
18401da177e4SLinus Torvalds (mapped_channel * RME9652_CHANNEL_BUFFER_BYTES);
18411da177e4SLinus Torvalds }
18421da177e4SLinus Torvalds }
18431da177e4SLinus Torvalds
snd_rme9652_playback_copy(struct snd_pcm_substream * substream,int channel,unsigned long pos,struct iov_iter * src,unsigned long count)18447b6ae34dSTakashi Iwai static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream,
18457b6ae34dSTakashi Iwai int channel, unsigned long pos,
18462098765eSTakashi Iwai struct iov_iter *src, unsigned long count)
18471da177e4SLinus Torvalds {
1848abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
184950895a55SJason A. Donenfeld signed char *channel_buf;
18501da177e4SLinus Torvalds
18517b6ae34dSTakashi Iwai if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES))
1852da3cec35STakashi Iwai return -EINVAL;
18531da177e4SLinus Torvalds
18541da177e4SLinus Torvalds channel_buf = rme9652_channel_buffer_location (rme9652,
18551da177e4SLinus Torvalds substream->pstr->stream,
18561da177e4SLinus Torvalds channel);
1857da3cec35STakashi Iwai if (snd_BUG_ON(!channel_buf))
1858da3cec35STakashi Iwai return -EIO;
18592098765eSTakashi Iwai if (copy_from_iter(channel_buf + pos, count, src) != count)
18601da177e4SLinus Torvalds return -EFAULT;
18617b6ae34dSTakashi Iwai return 0;
18621da177e4SLinus Torvalds }
18631da177e4SLinus Torvalds
snd_rme9652_capture_copy(struct snd_pcm_substream * substream,int channel,unsigned long pos,struct iov_iter * dst,unsigned long count)18647b6ae34dSTakashi Iwai static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream,
18657b6ae34dSTakashi Iwai int channel, unsigned long pos,
18662098765eSTakashi Iwai struct iov_iter *dst, unsigned long count)
18677b6ae34dSTakashi Iwai {
18687b6ae34dSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
186950895a55SJason A. Donenfeld signed char *channel_buf;
18707b6ae34dSTakashi Iwai
18717b6ae34dSTakashi Iwai if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES))
1872da3cec35STakashi Iwai return -EINVAL;
18731da177e4SLinus Torvalds
18741da177e4SLinus Torvalds channel_buf = rme9652_channel_buffer_location (rme9652,
18751da177e4SLinus Torvalds substream->pstr->stream,
18761da177e4SLinus Torvalds channel);
1877da3cec35STakashi Iwai if (snd_BUG_ON(!channel_buf))
1878da3cec35STakashi Iwai return -EIO;
18792098765eSTakashi Iwai if (copy_to_iter(channel_buf + pos, count, dst) != count)
18801da177e4SLinus Torvalds return -EFAULT;
18817b6ae34dSTakashi Iwai return 0;
18821da177e4SLinus Torvalds }
18831da177e4SLinus Torvalds
snd_rme9652_hw_silence(struct snd_pcm_substream * substream,int channel,unsigned long pos,unsigned long count)18847b6ae34dSTakashi Iwai static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream,
18857b6ae34dSTakashi Iwai int channel, unsigned long pos,
18867b6ae34dSTakashi Iwai unsigned long count)
18877b6ae34dSTakashi Iwai {
18887b6ae34dSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
188950895a55SJason A. Donenfeld signed char *channel_buf;
18907b6ae34dSTakashi Iwai
18917b6ae34dSTakashi Iwai channel_buf = rme9652_channel_buffer_location (rme9652,
18927b6ae34dSTakashi Iwai substream->pstr->stream,
18937b6ae34dSTakashi Iwai channel);
18947b6ae34dSTakashi Iwai if (snd_BUG_ON(!channel_buf))
18957b6ae34dSTakashi Iwai return -EIO;
18967b6ae34dSTakashi Iwai memset(channel_buf + pos, 0, count);
18977b6ae34dSTakashi Iwai return 0;
18981da177e4SLinus Torvalds }
18991da177e4SLinus Torvalds
snd_rme9652_reset(struct snd_pcm_substream * substream)1900abfd67bdSTakashi Iwai static int snd_rme9652_reset(struct snd_pcm_substream *substream)
19011da177e4SLinus Torvalds {
1902abfd67bdSTakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime;
1903abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
1904abfd67bdSTakashi Iwai struct snd_pcm_substream *other;
19051da177e4SLinus Torvalds if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
19061da177e4SLinus Torvalds other = rme9652->capture_substream;
19071da177e4SLinus Torvalds else
19081da177e4SLinus Torvalds other = rme9652->playback_substream;
19091da177e4SLinus Torvalds if (rme9652->running)
19101da177e4SLinus Torvalds runtime->status->hw_ptr = rme9652_hw_pointer(rme9652);
19111da177e4SLinus Torvalds else
19121da177e4SLinus Torvalds runtime->status->hw_ptr = 0;
19131da177e4SLinus Torvalds if (other) {
1914abfd67bdSTakashi Iwai struct snd_pcm_substream *s;
1915abfd67bdSTakashi Iwai struct snd_pcm_runtime *oruntime = other->runtime;
1916ef991b95STakashi Iwai snd_pcm_group_for_each_entry(s, substream) {
19171da177e4SLinus Torvalds if (s == other) {
19181da177e4SLinus Torvalds oruntime->status->hw_ptr = runtime->status->hw_ptr;
19191da177e4SLinus Torvalds break;
19201da177e4SLinus Torvalds }
19211da177e4SLinus Torvalds }
19221da177e4SLinus Torvalds }
19231da177e4SLinus Torvalds return 0;
19241da177e4SLinus Torvalds }
19251da177e4SLinus Torvalds
snd_rme9652_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)1926abfd67bdSTakashi Iwai static int snd_rme9652_hw_params(struct snd_pcm_substream *substream,
1927abfd67bdSTakashi Iwai struct snd_pcm_hw_params *params)
19281da177e4SLinus Torvalds {
1929abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
19301da177e4SLinus Torvalds int err;
19311da177e4SLinus Torvalds pid_t this_pid;
19321da177e4SLinus Torvalds pid_t other_pid;
19331da177e4SLinus Torvalds
19341da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
19351da177e4SLinus Torvalds
19361da177e4SLinus Torvalds if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
19371da177e4SLinus Torvalds rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP);
19381da177e4SLinus Torvalds rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= rme9652->creg_spdif_stream);
19391da177e4SLinus Torvalds this_pid = rme9652->playback_pid;
19401da177e4SLinus Torvalds other_pid = rme9652->capture_pid;
19411da177e4SLinus Torvalds } else {
19421da177e4SLinus Torvalds this_pid = rme9652->capture_pid;
19431da177e4SLinus Torvalds other_pid = rme9652->playback_pid;
19441da177e4SLinus Torvalds }
19451da177e4SLinus Torvalds
19461da177e4SLinus Torvalds if ((other_pid > 0) && (this_pid != other_pid)) {
19471da177e4SLinus Torvalds
19481da177e4SLinus Torvalds /* The other stream is open, and not by the same
19491da177e4SLinus Torvalds task as this one. Make sure that the parameters
19501da177e4SLinus Torvalds that matter are the same.
19511da177e4SLinus Torvalds */
19521da177e4SLinus Torvalds
19531da177e4SLinus Torvalds if ((int)params_rate(params) !=
19541da177e4SLinus Torvalds rme9652_adat_sample_rate(rme9652)) {
19551da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
19561da177e4SLinus Torvalds _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
19571da177e4SLinus Torvalds return -EBUSY;
19581da177e4SLinus Torvalds }
19591da177e4SLinus Torvalds
19601da177e4SLinus Torvalds if (params_period_size(params) != rme9652->period_bytes / 4) {
19611da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
19621da177e4SLinus Torvalds _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
19631da177e4SLinus Torvalds return -EBUSY;
19641da177e4SLinus Torvalds }
19651da177e4SLinus Torvalds
19661da177e4SLinus Torvalds /* We're fine. */
19671da177e4SLinus Torvalds
19681da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
19691da177e4SLinus Torvalds return 0;
19701da177e4SLinus Torvalds
19711da177e4SLinus Torvalds } else {
19721da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
19731da177e4SLinus Torvalds }
19741da177e4SLinus Torvalds
19751da177e4SLinus Torvalds /* how to make sure that the rate matches an externally-set one ?
19761da177e4SLinus Torvalds */
19771da177e4SLinus Torvalds
19789ebb3697STakashi Iwai err = rme9652_set_rate(rme9652, params_rate(params));
19799ebb3697STakashi Iwai if (err < 0) {
19801da177e4SLinus Torvalds _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
19811da177e4SLinus Torvalds return err;
19821da177e4SLinus Torvalds }
19831da177e4SLinus Torvalds
19849ebb3697STakashi Iwai err = rme9652_set_interrupt_interval(rme9652, params_period_size(params));
19859ebb3697STakashi Iwai if (err < 0) {
19861da177e4SLinus Torvalds _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
19871da177e4SLinus Torvalds return err;
19881da177e4SLinus Torvalds }
19891da177e4SLinus Torvalds
19901da177e4SLinus Torvalds return 0;
19911da177e4SLinus Torvalds }
19921da177e4SLinus Torvalds
snd_rme9652_channel_info(struct snd_pcm_substream * substream,struct snd_pcm_channel_info * info)1993abfd67bdSTakashi Iwai static int snd_rme9652_channel_info(struct snd_pcm_substream *substream,
1994abfd67bdSTakashi Iwai struct snd_pcm_channel_info *info)
19951da177e4SLinus Torvalds {
1996abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
19971da177e4SLinus Torvalds int chn;
19981da177e4SLinus Torvalds
1999da3cec35STakashi Iwai if (snd_BUG_ON(info->channel >= RME9652_NCHANNELS))
2000da3cec35STakashi Iwai return -EINVAL;
20011da177e4SLinus Torvalds
2002f526afcdSTakashi Iwai chn = rme9652->channel_map[array_index_nospec(info->channel,
2003f526afcdSTakashi Iwai RME9652_NCHANNELS)];
2004f526afcdSTakashi Iwai if (chn < 0)
20051da177e4SLinus Torvalds return -EINVAL;
20061da177e4SLinus Torvalds
20071da177e4SLinus Torvalds info->offset = chn * RME9652_CHANNEL_BUFFER_BYTES;
20081da177e4SLinus Torvalds info->first = 0;
20091da177e4SLinus Torvalds info->step = 32;
20101da177e4SLinus Torvalds return 0;
20111da177e4SLinus Torvalds }
20121da177e4SLinus Torvalds
snd_rme9652_ioctl(struct snd_pcm_substream * substream,unsigned int cmd,void * arg)2013abfd67bdSTakashi Iwai static int snd_rme9652_ioctl(struct snd_pcm_substream *substream,
20141da177e4SLinus Torvalds unsigned int cmd, void *arg)
20151da177e4SLinus Torvalds {
20161da177e4SLinus Torvalds switch (cmd) {
20171da177e4SLinus Torvalds case SNDRV_PCM_IOCTL1_RESET:
20181da177e4SLinus Torvalds {
20191da177e4SLinus Torvalds return snd_rme9652_reset(substream);
20201da177e4SLinus Torvalds }
20211da177e4SLinus Torvalds case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
20221da177e4SLinus Torvalds {
2023abfd67bdSTakashi Iwai struct snd_pcm_channel_info *info = arg;
20241da177e4SLinus Torvalds return snd_rme9652_channel_info(substream, info);
20251da177e4SLinus Torvalds }
20261da177e4SLinus Torvalds default:
20271da177e4SLinus Torvalds break;
20281da177e4SLinus Torvalds }
20291da177e4SLinus Torvalds
20301da177e4SLinus Torvalds return snd_pcm_lib_ioctl(substream, cmd, arg);
20311da177e4SLinus Torvalds }
20321da177e4SLinus Torvalds
rme9652_silence_playback(struct snd_rme9652 * rme9652)2033abfd67bdSTakashi Iwai static void rme9652_silence_playback(struct snd_rme9652 *rme9652)
20341da177e4SLinus Torvalds {
20351da177e4SLinus Torvalds memset(rme9652->playback_buffer, 0, RME9652_DMA_AREA_BYTES);
20361da177e4SLinus Torvalds }
20371da177e4SLinus Torvalds
snd_rme9652_trigger(struct snd_pcm_substream * substream,int cmd)2038abfd67bdSTakashi Iwai static int snd_rme9652_trigger(struct snd_pcm_substream *substream,
20391da177e4SLinus Torvalds int cmd)
20401da177e4SLinus Torvalds {
2041abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
2042abfd67bdSTakashi Iwai struct snd_pcm_substream *other;
20431da177e4SLinus Torvalds int running;
20441da177e4SLinus Torvalds spin_lock(&rme9652->lock);
20451da177e4SLinus Torvalds running = rme9652->running;
20461da177e4SLinus Torvalds switch (cmd) {
20471da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_START:
20481da177e4SLinus Torvalds running |= 1 << substream->stream;
20491da177e4SLinus Torvalds break;
20501da177e4SLinus Torvalds case SNDRV_PCM_TRIGGER_STOP:
20511da177e4SLinus Torvalds running &= ~(1 << substream->stream);
20521da177e4SLinus Torvalds break;
20531da177e4SLinus Torvalds default:
20541da177e4SLinus Torvalds snd_BUG();
20551da177e4SLinus Torvalds spin_unlock(&rme9652->lock);
20561da177e4SLinus Torvalds return -EINVAL;
20571da177e4SLinus Torvalds }
20581da177e4SLinus Torvalds if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
20591da177e4SLinus Torvalds other = rme9652->capture_substream;
20601da177e4SLinus Torvalds else
20611da177e4SLinus Torvalds other = rme9652->playback_substream;
20621da177e4SLinus Torvalds
20631da177e4SLinus Torvalds if (other) {
2064abfd67bdSTakashi Iwai struct snd_pcm_substream *s;
2065ef991b95STakashi Iwai snd_pcm_group_for_each_entry(s, substream) {
20661da177e4SLinus Torvalds if (s == other) {
20671da177e4SLinus Torvalds snd_pcm_trigger_done(s, substream);
20681da177e4SLinus Torvalds if (cmd == SNDRV_PCM_TRIGGER_START)
20691da177e4SLinus Torvalds running |= 1 << s->stream;
20701da177e4SLinus Torvalds else
20711da177e4SLinus Torvalds running &= ~(1 << s->stream);
20721da177e4SLinus Torvalds goto _ok;
20731da177e4SLinus Torvalds }
20741da177e4SLinus Torvalds }
20751da177e4SLinus Torvalds if (cmd == SNDRV_PCM_TRIGGER_START) {
20761da177e4SLinus Torvalds if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) &&
20771da177e4SLinus Torvalds substream->stream == SNDRV_PCM_STREAM_CAPTURE)
20781da177e4SLinus Torvalds rme9652_silence_playback(rme9652);
20791da177e4SLinus Torvalds } else {
20801da177e4SLinus Torvalds if (running &&
20811da177e4SLinus Torvalds substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
20821da177e4SLinus Torvalds rme9652_silence_playback(rme9652);
20831da177e4SLinus Torvalds }
20841da177e4SLinus Torvalds } else {
20851da177e4SLinus Torvalds if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
20861da177e4SLinus Torvalds rme9652_silence_playback(rme9652);
20871da177e4SLinus Torvalds }
20881da177e4SLinus Torvalds _ok:
20891da177e4SLinus Torvalds snd_pcm_trigger_done(substream, substream);
20901da177e4SLinus Torvalds if (!rme9652->running && running)
20911da177e4SLinus Torvalds rme9652_start(rme9652);
20921da177e4SLinus Torvalds else if (rme9652->running && !running)
20931da177e4SLinus Torvalds rme9652_stop(rme9652);
20941da177e4SLinus Torvalds rme9652->running = running;
20951da177e4SLinus Torvalds spin_unlock(&rme9652->lock);
20961da177e4SLinus Torvalds
20971da177e4SLinus Torvalds return 0;
20981da177e4SLinus Torvalds }
20991da177e4SLinus Torvalds
snd_rme9652_prepare(struct snd_pcm_substream * substream)2100abfd67bdSTakashi Iwai static int snd_rme9652_prepare(struct snd_pcm_substream *substream)
21011da177e4SLinus Torvalds {
2102abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
21031da177e4SLinus Torvalds unsigned long flags;
21041da177e4SLinus Torvalds
21051da177e4SLinus Torvalds spin_lock_irqsave(&rme9652->lock, flags);
21061da177e4SLinus Torvalds if (!rme9652->running)
21071da177e4SLinus Torvalds rme9652_reset_hw_pointer(rme9652);
21081da177e4SLinus Torvalds spin_unlock_irqrestore(&rme9652->lock, flags);
21092f235d92SHariprasad Kelam return 0;
21101da177e4SLinus Torvalds }
21111da177e4SLinus Torvalds
211218ed1cf0SBhumika Goyal static const struct snd_pcm_hardware snd_rme9652_playback_subinfo =
21131da177e4SLinus Torvalds {
21141da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP |
21151da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID |
21161da177e4SLinus Torvalds SNDRV_PCM_INFO_NONINTERLEAVED |
21171da177e4SLinus Torvalds SNDRV_PCM_INFO_SYNC_START |
21181da177e4SLinus Torvalds SNDRV_PCM_INFO_DOUBLE),
21191da177e4SLinus Torvalds .formats = SNDRV_PCM_FMTBIT_S32_LE,
21201da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_44100 |
21211da177e4SLinus Torvalds SNDRV_PCM_RATE_48000 |
21221da177e4SLinus Torvalds SNDRV_PCM_RATE_88200 |
21231da177e4SLinus Torvalds SNDRV_PCM_RATE_96000),
21241da177e4SLinus Torvalds .rate_min = 44100,
21251da177e4SLinus Torvalds .rate_max = 96000,
21261da177e4SLinus Torvalds .channels_min = 10,
21271da177e4SLinus Torvalds .channels_max = 26,
21281da177e4SLinus Torvalds .buffer_bytes_max = RME9652_CHANNEL_BUFFER_BYTES * 26,
21291da177e4SLinus Torvalds .period_bytes_min = (64 * 4) * 10,
21301da177e4SLinus Torvalds .period_bytes_max = (8192 * 4) * 26,
21311da177e4SLinus Torvalds .periods_min = 2,
21321da177e4SLinus Torvalds .periods_max = 2,
21331da177e4SLinus Torvalds .fifo_size = 0,
21341da177e4SLinus Torvalds };
21351da177e4SLinus Torvalds
213618ed1cf0SBhumika Goyal static const struct snd_pcm_hardware snd_rme9652_capture_subinfo =
21371da177e4SLinus Torvalds {
21381da177e4SLinus Torvalds .info = (SNDRV_PCM_INFO_MMAP |
21391da177e4SLinus Torvalds SNDRV_PCM_INFO_MMAP_VALID |
21401da177e4SLinus Torvalds SNDRV_PCM_INFO_NONINTERLEAVED |
21411da177e4SLinus Torvalds SNDRV_PCM_INFO_SYNC_START),
21421da177e4SLinus Torvalds .formats = SNDRV_PCM_FMTBIT_S32_LE,
21431da177e4SLinus Torvalds .rates = (SNDRV_PCM_RATE_44100 |
21441da177e4SLinus Torvalds SNDRV_PCM_RATE_48000 |
21451da177e4SLinus Torvalds SNDRV_PCM_RATE_88200 |
21461da177e4SLinus Torvalds SNDRV_PCM_RATE_96000),
21471da177e4SLinus Torvalds .rate_min = 44100,
21481da177e4SLinus Torvalds .rate_max = 96000,
21491da177e4SLinus Torvalds .channels_min = 10,
21501da177e4SLinus Torvalds .channels_max = 26,
21511da177e4SLinus Torvalds .buffer_bytes_max = RME9652_CHANNEL_BUFFER_BYTES *26,
21521da177e4SLinus Torvalds .period_bytes_min = (64 * 4) * 10,
21531da177e4SLinus Torvalds .period_bytes_max = (8192 * 4) * 26,
21541da177e4SLinus Torvalds .periods_min = 2,
21551da177e4SLinus Torvalds .periods_max = 2,
21561da177e4SLinus Torvalds .fifo_size = 0,
21571da177e4SLinus Torvalds };
21581da177e4SLinus Torvalds
2159f9fee553STakashi Iwai static const unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
21601da177e4SLinus Torvalds
2161f9fee553STakashi Iwai static const struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
21621da177e4SLinus Torvalds .count = ARRAY_SIZE(period_sizes),
21631da177e4SLinus Torvalds .list = period_sizes,
21641da177e4SLinus Torvalds .mask = 0
21651da177e4SLinus Torvalds };
21661da177e4SLinus Torvalds
snd_rme9652_hw_rule_channels(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)2167abfd67bdSTakashi Iwai static int snd_rme9652_hw_rule_channels(struct snd_pcm_hw_params *params,
2168abfd67bdSTakashi Iwai struct snd_pcm_hw_rule *rule)
21691da177e4SLinus Torvalds {
2170abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = rule->private;
2171abfd67bdSTakashi Iwai struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
21721da177e4SLinus Torvalds unsigned int list[2] = { rme9652->ds_channels, rme9652->ss_channels };
21731da177e4SLinus Torvalds return snd_interval_list(c, 2, list, 0);
21741da177e4SLinus Torvalds }
21751da177e4SLinus Torvalds
snd_rme9652_hw_rule_channels_rate(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)2176abfd67bdSTakashi Iwai static int snd_rme9652_hw_rule_channels_rate(struct snd_pcm_hw_params *params,
2177abfd67bdSTakashi Iwai struct snd_pcm_hw_rule *rule)
21781da177e4SLinus Torvalds {
2179abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = rule->private;
2180abfd67bdSTakashi Iwai struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
2181abfd67bdSTakashi Iwai struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
21821da177e4SLinus Torvalds if (r->min > 48000) {
2183abfd67bdSTakashi Iwai struct snd_interval t = {
21841da177e4SLinus Torvalds .min = rme9652->ds_channels,
21851da177e4SLinus Torvalds .max = rme9652->ds_channels,
21861da177e4SLinus Torvalds .integer = 1,
21871da177e4SLinus Torvalds };
21881da177e4SLinus Torvalds return snd_interval_refine(c, &t);
21891da177e4SLinus Torvalds } else if (r->max < 88200) {
2190abfd67bdSTakashi Iwai struct snd_interval t = {
21911da177e4SLinus Torvalds .min = rme9652->ss_channels,
21921da177e4SLinus Torvalds .max = rme9652->ss_channels,
21931da177e4SLinus Torvalds .integer = 1,
21941da177e4SLinus Torvalds };
21951da177e4SLinus Torvalds return snd_interval_refine(c, &t);
21961da177e4SLinus Torvalds }
21971da177e4SLinus Torvalds return 0;
21981da177e4SLinus Torvalds }
21991da177e4SLinus Torvalds
snd_rme9652_hw_rule_rate_channels(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)2200abfd67bdSTakashi Iwai static int snd_rme9652_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
2201abfd67bdSTakashi Iwai struct snd_pcm_hw_rule *rule)
22021da177e4SLinus Torvalds {
2203abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = rule->private;
2204abfd67bdSTakashi Iwai struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
2205abfd67bdSTakashi Iwai struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
22061da177e4SLinus Torvalds if (c->min >= rme9652->ss_channels) {
2207abfd67bdSTakashi Iwai struct snd_interval t = {
22081da177e4SLinus Torvalds .min = 44100,
22091da177e4SLinus Torvalds .max = 48000,
22101da177e4SLinus Torvalds .integer = 1,
22111da177e4SLinus Torvalds };
22121da177e4SLinus Torvalds return snd_interval_refine(r, &t);
22131da177e4SLinus Torvalds } else if (c->max <= rme9652->ds_channels) {
2214abfd67bdSTakashi Iwai struct snd_interval t = {
22151da177e4SLinus Torvalds .min = 88200,
22161da177e4SLinus Torvalds .max = 96000,
22171da177e4SLinus Torvalds .integer = 1,
22181da177e4SLinus Torvalds };
22191da177e4SLinus Torvalds return snd_interval_refine(r, &t);
22201da177e4SLinus Torvalds }
22211da177e4SLinus Torvalds return 0;
22221da177e4SLinus Torvalds }
22231da177e4SLinus Torvalds
snd_rme9652_playback_open(struct snd_pcm_substream * substream)2224abfd67bdSTakashi Iwai static int snd_rme9652_playback_open(struct snd_pcm_substream *substream)
22251da177e4SLinus Torvalds {
2226abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
2227abfd67bdSTakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime;
22281da177e4SLinus Torvalds
22291da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
22301da177e4SLinus Torvalds
22311da177e4SLinus Torvalds snd_pcm_set_sync(substream);
22321da177e4SLinus Torvalds
22331da177e4SLinus Torvalds runtime->hw = snd_rme9652_playback_subinfo;
223443d35cccSTakashi Iwai snd_pcm_set_runtime_buffer(substream, &rme9652->playback_dma_buf);
22351da177e4SLinus Torvalds
22361da177e4SLinus Torvalds if (rme9652->capture_substream == NULL) {
22371da177e4SLinus Torvalds rme9652_stop(rme9652);
22381da177e4SLinus Torvalds rme9652_set_thru(rme9652, -1, 0);
22391da177e4SLinus Torvalds }
22401da177e4SLinus Torvalds
22411da177e4SLinus Torvalds rme9652->playback_pid = current->pid;
22421da177e4SLinus Torvalds rme9652->playback_substream = substream;
22431da177e4SLinus Torvalds
22441da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
22451da177e4SLinus Torvalds
22461da177e4SLinus Torvalds snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
22471da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes);
22481da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
22491da177e4SLinus Torvalds snd_rme9652_hw_rule_channels, rme9652,
22501da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_CHANNELS, -1);
22511da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
22521da177e4SLinus Torvalds snd_rme9652_hw_rule_channels_rate, rme9652,
22531da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_RATE, -1);
22541da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
22551da177e4SLinus Torvalds snd_rme9652_hw_rule_rate_channels, rme9652,
22561da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_CHANNELS, -1);
22571da177e4SLinus Torvalds
22581da177e4SLinus Torvalds rme9652->creg_spdif_stream = rme9652->creg_spdif;
22591da177e4SLinus Torvalds rme9652->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
22601da177e4SLinus Torvalds snd_ctl_notify(rme9652->card, SNDRV_CTL_EVENT_MASK_VALUE |
22611da177e4SLinus Torvalds SNDRV_CTL_EVENT_MASK_INFO, &rme9652->spdif_ctl->id);
22621da177e4SLinus Torvalds return 0;
22631da177e4SLinus Torvalds }
22641da177e4SLinus Torvalds
snd_rme9652_playback_release(struct snd_pcm_substream * substream)2265abfd67bdSTakashi Iwai static int snd_rme9652_playback_release(struct snd_pcm_substream *substream)
22661da177e4SLinus Torvalds {
2267abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
22681da177e4SLinus Torvalds
22691da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
22701da177e4SLinus Torvalds
22711da177e4SLinus Torvalds rme9652->playback_pid = -1;
22721da177e4SLinus Torvalds rme9652->playback_substream = NULL;
22731da177e4SLinus Torvalds
22741da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
22751da177e4SLinus Torvalds
22761da177e4SLinus Torvalds rme9652->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
22771da177e4SLinus Torvalds snd_ctl_notify(rme9652->card, SNDRV_CTL_EVENT_MASK_VALUE |
22781da177e4SLinus Torvalds SNDRV_CTL_EVENT_MASK_INFO, &rme9652->spdif_ctl->id);
22791da177e4SLinus Torvalds return 0;
22801da177e4SLinus Torvalds }
22811da177e4SLinus Torvalds
22821da177e4SLinus Torvalds
snd_rme9652_capture_open(struct snd_pcm_substream * substream)2283abfd67bdSTakashi Iwai static int snd_rme9652_capture_open(struct snd_pcm_substream *substream)
22841da177e4SLinus Torvalds {
2285abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
2286abfd67bdSTakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime;
22871da177e4SLinus Torvalds
22881da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
22891da177e4SLinus Torvalds
22901da177e4SLinus Torvalds snd_pcm_set_sync(substream);
22911da177e4SLinus Torvalds
22921da177e4SLinus Torvalds runtime->hw = snd_rme9652_capture_subinfo;
229343d35cccSTakashi Iwai snd_pcm_set_runtime_buffer(substream, &rme9652->capture_dma_buf);
22941da177e4SLinus Torvalds
22951da177e4SLinus Torvalds if (rme9652->playback_substream == NULL) {
22961da177e4SLinus Torvalds rme9652_stop(rme9652);
22971da177e4SLinus Torvalds rme9652_set_thru(rme9652, -1, 0);
22981da177e4SLinus Torvalds }
22991da177e4SLinus Torvalds
23001da177e4SLinus Torvalds rme9652->capture_pid = current->pid;
23011da177e4SLinus Torvalds rme9652->capture_substream = substream;
23021da177e4SLinus Torvalds
23031da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
23041da177e4SLinus Torvalds
23051da177e4SLinus Torvalds snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
23061da177e4SLinus Torvalds snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes);
23071da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
23081da177e4SLinus Torvalds snd_rme9652_hw_rule_channels, rme9652,
23091da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_CHANNELS, -1);
23101da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
23111da177e4SLinus Torvalds snd_rme9652_hw_rule_channels_rate, rme9652,
23121da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_RATE, -1);
23131da177e4SLinus Torvalds snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
23141da177e4SLinus Torvalds snd_rme9652_hw_rule_rate_channels, rme9652,
23151da177e4SLinus Torvalds SNDRV_PCM_HW_PARAM_CHANNELS, -1);
23161da177e4SLinus Torvalds return 0;
23171da177e4SLinus Torvalds }
23181da177e4SLinus Torvalds
snd_rme9652_capture_release(struct snd_pcm_substream * substream)2319abfd67bdSTakashi Iwai static int snd_rme9652_capture_release(struct snd_pcm_substream *substream)
23201da177e4SLinus Torvalds {
2321abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
23221da177e4SLinus Torvalds
23231da177e4SLinus Torvalds spin_lock_irq(&rme9652->lock);
23241da177e4SLinus Torvalds
23251da177e4SLinus Torvalds rme9652->capture_pid = -1;
23261da177e4SLinus Torvalds rme9652->capture_substream = NULL;
23271da177e4SLinus Torvalds
23281da177e4SLinus Torvalds spin_unlock_irq(&rme9652->lock);
23291da177e4SLinus Torvalds return 0;
23301da177e4SLinus Torvalds }
23311da177e4SLinus Torvalds
23326769e988SJulia Lawall static const struct snd_pcm_ops snd_rme9652_playback_ops = {
23331da177e4SLinus Torvalds .open = snd_rme9652_playback_open,
23341da177e4SLinus Torvalds .close = snd_rme9652_playback_release,
23351da177e4SLinus Torvalds .ioctl = snd_rme9652_ioctl,
23361da177e4SLinus Torvalds .hw_params = snd_rme9652_hw_params,
23371da177e4SLinus Torvalds .prepare = snd_rme9652_prepare,
23381da177e4SLinus Torvalds .trigger = snd_rme9652_trigger,
23391da177e4SLinus Torvalds .pointer = snd_rme9652_hw_pointer,
23402098765eSTakashi Iwai .copy = snd_rme9652_playback_copy,
23417b6ae34dSTakashi Iwai .fill_silence = snd_rme9652_hw_silence,
23421da177e4SLinus Torvalds };
23431da177e4SLinus Torvalds
23446769e988SJulia Lawall static const struct snd_pcm_ops snd_rme9652_capture_ops = {
23451da177e4SLinus Torvalds .open = snd_rme9652_capture_open,
23461da177e4SLinus Torvalds .close = snd_rme9652_capture_release,
23471da177e4SLinus Torvalds .ioctl = snd_rme9652_ioctl,
23481da177e4SLinus Torvalds .hw_params = snd_rme9652_hw_params,
23491da177e4SLinus Torvalds .prepare = snd_rme9652_prepare,
23501da177e4SLinus Torvalds .trigger = snd_rme9652_trigger,
23511da177e4SLinus Torvalds .pointer = snd_rme9652_hw_pointer,
23522098765eSTakashi Iwai .copy = snd_rme9652_capture_copy,
23531da177e4SLinus Torvalds };
23541da177e4SLinus Torvalds
snd_rme9652_create_pcm(struct snd_card * card,struct snd_rme9652 * rme9652)2355e23e7a14SBill Pemberton static int snd_rme9652_create_pcm(struct snd_card *card,
2356abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652)
23571da177e4SLinus Torvalds {
2358abfd67bdSTakashi Iwai struct snd_pcm *pcm;
23591da177e4SLinus Torvalds int err;
23601da177e4SLinus Torvalds
23619ebb3697STakashi Iwai err = snd_pcm_new(card, rme9652->card_name, 0, 1, 1, &pcm);
23629ebb3697STakashi Iwai if (err < 0)
23631da177e4SLinus Torvalds return err;
23641da177e4SLinus Torvalds
23651da177e4SLinus Torvalds rme9652->pcm = pcm;
23661da177e4SLinus Torvalds pcm->private_data = rme9652;
23671da177e4SLinus Torvalds strscpy(pcm->name, rme9652->card_name);
23681da177e4SLinus Torvalds
23691da177e4SLinus Torvalds snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme9652_playback_ops);
23701da177e4SLinus Torvalds snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme9652_capture_ops);
23711da177e4SLinus Torvalds
23721da177e4SLinus Torvalds pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
23731da177e4SLinus Torvalds
23741da177e4SLinus Torvalds return 0;
23751da177e4SLinus Torvalds }
23761da177e4SLinus Torvalds
snd_rme9652_create(struct snd_card * card,struct snd_rme9652 * rme9652,int precise_ptr)2377e23e7a14SBill Pemberton static int snd_rme9652_create(struct snd_card *card,
2378abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652,
23791da177e4SLinus Torvalds int precise_ptr)
23801da177e4SLinus Torvalds {
23811da177e4SLinus Torvalds struct pci_dev *pci = rme9652->pci;
23821da177e4SLinus Torvalds int err;
23831da177e4SLinus Torvalds int status;
23841da177e4SLinus Torvalds unsigned short rev;
23851da177e4SLinus Torvalds
23861da177e4SLinus Torvalds rme9652->irq = -1;
23871da177e4SLinus Torvalds rme9652->card = card;
23881da177e4SLinus Torvalds
23891da177e4SLinus Torvalds pci_read_config_word(rme9652->pci, PCI_CLASS_REVISION, &rev);
23901da177e4SLinus Torvalds
23911da177e4SLinus Torvalds switch (rev & 0xff) {
23921da177e4SLinus Torvalds case 3:
23931da177e4SLinus Torvalds case 4:
23941da177e4SLinus Torvalds case 8:
23951da177e4SLinus Torvalds case 9:
23961da177e4SLinus Torvalds break;
23971da177e4SLinus Torvalds
23981da177e4SLinus Torvalds default:
23991da177e4SLinus Torvalds /* who knows? */
24001da177e4SLinus Torvalds return -ENODEV;
24011da177e4SLinus Torvalds }
24021da177e4SLinus Torvalds
2403b1002b2dSTakashi Iwai err = pcim_enable_device(pci);
24049ebb3697STakashi Iwai if (err < 0)
24051da177e4SLinus Torvalds return err;
24061da177e4SLinus Torvalds
24071da177e4SLinus Torvalds spin_lock_init(&rme9652->lock);
24081da177e4SLinus Torvalds
2409*9c7f2b5eSPhilipp Stanner err = pcim_request_all_regions(pci, "rme9652");
24109ebb3697STakashi Iwai if (err < 0)
24111da177e4SLinus Torvalds return err;
24121da177e4SLinus Torvalds rme9652->port = pci_resource_start(pci, 0);
2413b1002b2dSTakashi Iwai rme9652->iobase = devm_ioremap(&pci->dev, rme9652->port, RME9652_IO_EXTENT);
24141da177e4SLinus Torvalds if (rme9652->iobase == NULL) {
241509ae539eSTakashi Iwai dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n",
241609ae539eSTakashi Iwai rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1);
24171da177e4SLinus Torvalds return -EBUSY;
24181da177e4SLinus Torvalds }
24191da177e4SLinus Torvalds
2420b1002b2dSTakashi Iwai if (devm_request_irq(&pci->dev, pci->irq, snd_rme9652_interrupt,
2421b1002b2dSTakashi Iwai IRQF_SHARED, KBUILD_MODNAME, rme9652)) {
242209ae539eSTakashi Iwai dev_err(card->dev, "unable to request IRQ %d\n", pci->irq);
24231da177e4SLinus Torvalds return -EBUSY;
24241da177e4SLinus Torvalds }
24251da177e4SLinus Torvalds rme9652->irq = pci->irq;
242639cccf45STakashi Iwai card->sync_irq = rme9652->irq;
24271da177e4SLinus Torvalds rme9652->precise_ptr = precise_ptr;
24281da177e4SLinus Torvalds
24291da177e4SLinus Torvalds /* Determine the h/w rev level of the card. This seems like
24301da177e4SLinus Torvalds a particularly kludgy way to encode it, but its what RME
24311da177e4SLinus Torvalds chose to do, so we follow them ...
24321da177e4SLinus Torvalds */
24331da177e4SLinus Torvalds
24341da177e4SLinus Torvalds status = rme9652_read(rme9652, RME9652_status_register);
24351da177e4SLinus Torvalds if (rme9652_decode_spdif_rate(status&RME9652_F) == 1) {
24361da177e4SLinus Torvalds rme9652->hw_rev = 15;
24371da177e4SLinus Torvalds } else {
24381da177e4SLinus Torvalds rme9652->hw_rev = 11;
24391da177e4SLinus Torvalds }
24401da177e4SLinus Torvalds
24411da177e4SLinus Torvalds /* Differentiate between the standard Hammerfall, and the
24421da177e4SLinus Torvalds "Light", which does not have the expansion board. This
24431da177e4SLinus Torvalds method comes from information received from Mathhias
24441da177e4SLinus Torvalds Clausen at RME. Display the EEPROM and h/w revID where
24451da177e4SLinus Torvalds relevant.
24461da177e4SLinus Torvalds */
24471da177e4SLinus Torvalds
24481da177e4SLinus Torvalds switch (rev) {
24491da177e4SLinus Torvalds case 8: /* original eprom */
24501da177e4SLinus Torvalds strscpy(card->driver, "RME9636");
24511da177e4SLinus Torvalds if (rme9652->hw_rev == 15) {
24521da177e4SLinus Torvalds rme9652->card_name = "RME Digi9636 (Rev 1.5)";
24531da177e4SLinus Torvalds } else {
24541da177e4SLinus Torvalds rme9652->card_name = "RME Digi9636";
24551da177e4SLinus Torvalds }
24561da177e4SLinus Torvalds rme9652->ss_channels = RME9636_NCHANNELS;
24571da177e4SLinus Torvalds break;
24581da177e4SLinus Torvalds case 9: /* W36_G EPROM */
24591da177e4SLinus Torvalds strscpy(card->driver, "RME9636");
24601da177e4SLinus Torvalds rme9652->card_name = "RME Digi9636 (Rev G)";
24611da177e4SLinus Torvalds rme9652->ss_channels = RME9636_NCHANNELS;
24621da177e4SLinus Torvalds break;
24631da177e4SLinus Torvalds case 4: /* W52_G EPROM */
24641da177e4SLinus Torvalds strscpy(card->driver, "RME9652");
24651da177e4SLinus Torvalds rme9652->card_name = "RME Digi9652 (Rev G)";
24661da177e4SLinus Torvalds rme9652->ss_channels = RME9652_NCHANNELS;
24671da177e4SLinus Torvalds break;
24681da177e4SLinus Torvalds case 3: /* original eprom */
24691da177e4SLinus Torvalds strscpy(card->driver, "RME9652");
24701da177e4SLinus Torvalds if (rme9652->hw_rev == 15) {
24711da177e4SLinus Torvalds rme9652->card_name = "RME Digi9652 (Rev 1.5)";
24721da177e4SLinus Torvalds } else {
24731da177e4SLinus Torvalds rme9652->card_name = "RME Digi9652";
24741da177e4SLinus Torvalds }
24751da177e4SLinus Torvalds rme9652->ss_channels = RME9652_NCHANNELS;
24761da177e4SLinus Torvalds break;
24771da177e4SLinus Torvalds }
24781da177e4SLinus Torvalds
24791da177e4SLinus Torvalds rme9652->ds_channels = (rme9652->ss_channels - 2) / 2 + 2;
24801da177e4SLinus Torvalds
24811da177e4SLinus Torvalds pci_set_master(rme9652->pci);
24821da177e4SLinus Torvalds
24839ebb3697STakashi Iwai err = snd_rme9652_initialize_memory(rme9652);
24849ebb3697STakashi Iwai if (err < 0)
24851da177e4SLinus Torvalds return err;
24861da177e4SLinus Torvalds
24879ebb3697STakashi Iwai err = snd_rme9652_create_pcm(card, rme9652);
24889ebb3697STakashi Iwai if (err < 0)
24891da177e4SLinus Torvalds return err;
24901da177e4SLinus Torvalds
24919ebb3697STakashi Iwai err = snd_rme9652_create_controls(card, rme9652);
24929ebb3697STakashi Iwai if (err < 0)
24931da177e4SLinus Torvalds return err;
24941da177e4SLinus Torvalds
24951da177e4SLinus Torvalds snd_rme9652_proc_init(rme9652);
24961da177e4SLinus Torvalds
24971da177e4SLinus Torvalds rme9652->last_spdif_sample_rate = -1;
24981da177e4SLinus Torvalds rme9652->last_adat_sample_rate = -1;
24991da177e4SLinus Torvalds rme9652->playback_pid = -1;
25001da177e4SLinus Torvalds rme9652->capture_pid = -1;
25011da177e4SLinus Torvalds rme9652->capture_substream = NULL;
25021da177e4SLinus Torvalds rme9652->playback_substream = NULL;
25031da177e4SLinus Torvalds
25041da177e4SLinus Torvalds snd_rme9652_set_defaults(rme9652);
25051da177e4SLinus Torvalds
25061da177e4SLinus Torvalds if (rme9652->hw_rev == 15) {
25071da177e4SLinus Torvalds rme9652_initialize_spdif_receiver (rme9652);
25081da177e4SLinus Torvalds }
25091da177e4SLinus Torvalds
25101da177e4SLinus Torvalds return 0;
25111da177e4SLinus Torvalds }
25121da177e4SLinus Torvalds
snd_rme9652_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)2513e23e7a14SBill Pemberton static int snd_rme9652_probe(struct pci_dev *pci,
25141da177e4SLinus Torvalds const struct pci_device_id *pci_id)
25151da177e4SLinus Torvalds {
25161da177e4SLinus Torvalds static int dev;
2517abfd67bdSTakashi Iwai struct snd_rme9652 *rme9652;
2518abfd67bdSTakashi Iwai struct snd_card *card;
25191da177e4SLinus Torvalds int err;
25201da177e4SLinus Torvalds
25211da177e4SLinus Torvalds if (dev >= SNDRV_CARDS)
25221da177e4SLinus Torvalds return -ENODEV;
25231da177e4SLinus Torvalds if (!enable[dev]) {
25241da177e4SLinus Torvalds dev++;
25251da177e4SLinus Torvalds return -ENOENT;
25261da177e4SLinus Torvalds }
25271da177e4SLinus Torvalds
2528b1002b2dSTakashi Iwai err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
2529e58de7baSTakashi Iwai sizeof(struct snd_rme9652), &card);
25301da177e4SLinus Torvalds
2531e58de7baSTakashi Iwai if (err < 0)
2532e58de7baSTakashi Iwai return err;
25331da177e4SLinus Torvalds
2534abfd67bdSTakashi Iwai rme9652 = (struct snd_rme9652 *) card->private_data;
25351da177e4SLinus Torvalds card->private_free = snd_rme9652_card_free;
25361da177e4SLinus Torvalds rme9652->dev = dev;
25371da177e4SLinus Torvalds rme9652->pci = pci;
25382675be5aSMarkus Elfring err = snd_rme9652_create(card, rme9652, precise_ptr[dev]);
25392675be5aSMarkus Elfring if (err)
2540b2aa4f80STakashi Iwai goto error;
25411da177e4SLinus Torvalds
25421da177e4SLinus Torvalds strscpy(card->shortname, rme9652->card_name);
25431da177e4SLinus Torvalds
25441da177e4SLinus Torvalds sprintf(card->longname, "%s at 0x%lx, irq %d",
25451da177e4SLinus Torvalds card->shortname, rme9652->port, rme9652->irq);
25462675be5aSMarkus Elfring err = snd_card_register(card);
2547b1002b2dSTakashi Iwai if (err)
2548b2aa4f80STakashi Iwai goto error;
25491da177e4SLinus Torvalds pci_set_drvdata(pci, card);
25501da177e4SLinus Torvalds dev++;
25511da177e4SLinus Torvalds return 0;
2552b2aa4f80STakashi Iwai
2553b2aa4f80STakashi Iwai error:
2554b2aa4f80STakashi Iwai snd_card_free(card);
2555b2aa4f80STakashi Iwai return err;
25561da177e4SLinus Torvalds }
25571da177e4SLinus Torvalds
2558e9f66d9bSTakashi Iwai static struct pci_driver rme9652_driver = {
25593733e424STakashi Iwai .name = KBUILD_MODNAME,
25601da177e4SLinus Torvalds .id_table = snd_rme9652_ids,
25611da177e4SLinus Torvalds .probe = snd_rme9652_probe,
25621da177e4SLinus Torvalds };
25631da177e4SLinus Torvalds
2564e9f66d9bSTakashi Iwai module_pci_driver(rme9652_driver);
2565