xref: /linux/sound/pci/rme9652/rme9652.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
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