162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ALSA driver for RME Digi9652 audio interfaces 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 1999 IEM - Winfried Ritsch 662306a36Sopenharmony_ci * Copyright (c) 1999-2001 Paul Davis 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/delay.h> 1062306a36Sopenharmony_ci#include <linux/init.h> 1162306a36Sopenharmony_ci#include <linux/interrupt.h> 1262306a36Sopenharmony_ci#include <linux/pci.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/io.h> 1562306a36Sopenharmony_ci#include <linux/nospec.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <sound/core.h> 1862306a36Sopenharmony_ci#include <sound/control.h> 1962306a36Sopenharmony_ci#include <sound/pcm.h> 2062306a36Sopenharmony_ci#include <sound/info.h> 2162306a36Sopenharmony_ci#include <sound/asoundef.h> 2262306a36Sopenharmony_ci#include <sound/initval.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <asm/current.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 2762306a36Sopenharmony_cistatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 2862306a36Sopenharmony_cistatic bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 2962306a36Sopenharmony_cistatic bool precise_ptr[SNDRV_CARDS]; /* Enable precise pointer */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cimodule_param_array(index, int, NULL, 0444); 3262306a36Sopenharmony_ciMODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard."); 3362306a36Sopenharmony_cimodule_param_array(id, charp, NULL, 0444); 3462306a36Sopenharmony_ciMODULE_PARM_DESC(id, "ID string for RME Digi9652 (Hammerfall) soundcard."); 3562306a36Sopenharmony_cimodule_param_array(enable, bool, NULL, 0444); 3662306a36Sopenharmony_ciMODULE_PARM_DESC(enable, "Enable/disable specific RME96{52,36} soundcards."); 3762306a36Sopenharmony_cimodule_param_array(precise_ptr, bool, NULL, 0444); 3862306a36Sopenharmony_ciMODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably)."); 3962306a36Sopenharmony_ciMODULE_AUTHOR("Paul Davis <pbd@op.net>, Winfried Ritsch"); 4062306a36Sopenharmony_ciMODULE_DESCRIPTION("RME Digi9652/Digi9636"); 4162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* The Hammerfall has two sets of 24 ADAT + 2 S/PDIF channels, one for 4462306a36Sopenharmony_ci capture, one for playback. Both the ADAT and S/PDIF channels appear 4562306a36Sopenharmony_ci to the host CPU in the same block of memory. There is no functional 4662306a36Sopenharmony_ci difference between them in terms of access. 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci The Hammerfall Light is identical to the Hammerfall, except that it 4962306a36Sopenharmony_ci has 2 sets 18 channels (16 ADAT + 2 S/PDIF) for capture and playback. 5062306a36Sopenharmony_ci*/ 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define RME9652_NCHANNELS 26 5362306a36Sopenharmony_ci#define RME9636_NCHANNELS 18 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* Preferred sync source choices - used by "sync_pref" control switch */ 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define RME9652_SYNC_FROM_SPDIF 0 5862306a36Sopenharmony_ci#define RME9652_SYNC_FROM_ADAT1 1 5962306a36Sopenharmony_ci#define RME9652_SYNC_FROM_ADAT2 2 6062306a36Sopenharmony_ci#define RME9652_SYNC_FROM_ADAT3 3 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* Possible sources of S/PDIF input */ 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#define RME9652_SPDIFIN_OPTICAL 0 /* optical (ADAT1) */ 6562306a36Sopenharmony_ci#define RME9652_SPDIFIN_COAXIAL 1 /* coaxial (RCA) */ 6662306a36Sopenharmony_ci#define RME9652_SPDIFIN_INTERN 2 /* internal (CDROM) */ 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* ------------- Status-Register bits --------------------- */ 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#define RME9652_IRQ (1<<0) /* IRQ is High if not reset by irq_clear */ 7162306a36Sopenharmony_ci#define RME9652_lock_2 (1<<1) /* ADAT 3-PLL: 1=locked, 0=unlocked */ 7262306a36Sopenharmony_ci#define RME9652_lock_1 (1<<2) /* ADAT 2-PLL: 1=locked, 0=unlocked */ 7362306a36Sopenharmony_ci#define RME9652_lock_0 (1<<3) /* ADAT 1-PLL: 1=locked, 0=unlocked */ 7462306a36Sopenharmony_ci#define RME9652_fs48 (1<<4) /* sample rate is 0=44.1/88.2,1=48/96 Khz */ 7562306a36Sopenharmony_ci#define RME9652_wsel_rd (1<<5) /* if Word-Clock is used and valid then 1 */ 7662306a36Sopenharmony_ci /* bits 6-15 encode h/w buffer pointer position */ 7762306a36Sopenharmony_ci#define RME9652_sync_2 (1<<16) /* if ADAT-IN 3 in sync to system clock */ 7862306a36Sopenharmony_ci#define RME9652_sync_1 (1<<17) /* if ADAT-IN 2 in sync to system clock */ 7962306a36Sopenharmony_ci#define RME9652_sync_0 (1<<18) /* if ADAT-IN 1 in sync to system clock */ 8062306a36Sopenharmony_ci#define RME9652_DS_rd (1<<19) /* 1=Double Speed Mode, 0=Normal Speed */ 8162306a36Sopenharmony_ci#define RME9652_tc_busy (1<<20) /* 1=time-code copy in progress (960ms) */ 8262306a36Sopenharmony_ci#define RME9652_tc_out (1<<21) /* time-code out bit */ 8362306a36Sopenharmony_ci#define RME9652_F_0 (1<<22) /* 000=64kHz, 100=88.2kHz, 011=96kHz */ 8462306a36Sopenharmony_ci#define RME9652_F_1 (1<<23) /* 111=32kHz, 110=44.1kHz, 101=48kHz, */ 8562306a36Sopenharmony_ci#define RME9652_F_2 (1<<24) /* external Crystal Chip if ERF=1 */ 8662306a36Sopenharmony_ci#define RME9652_ERF (1<<25) /* Error-Flag of SDPIF Receiver (1=No Lock) */ 8762306a36Sopenharmony_ci#define RME9652_buffer_id (1<<26) /* toggles by each interrupt on rec/play */ 8862306a36Sopenharmony_ci#define RME9652_tc_valid (1<<27) /* 1 = a signal is detected on time-code input */ 8962306a36Sopenharmony_ci#define RME9652_SPDIF_READ (1<<28) /* byte available from Rev 1.5+ S/PDIF interface */ 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#define RME9652_sync (RME9652_sync_0|RME9652_sync_1|RME9652_sync_2) 9262306a36Sopenharmony_ci#define RME9652_lock (RME9652_lock_0|RME9652_lock_1|RME9652_lock_2) 9362306a36Sopenharmony_ci#define RME9652_F (RME9652_F_0|RME9652_F_1|RME9652_F_2) 9462306a36Sopenharmony_ci#define rme9652_decode_spdif_rate(x) ((x)>>22) 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* Bit 6..15 : h/w buffer pointer */ 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#define RME9652_buf_pos 0x000FFC0 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci/* Bits 31,30,29 are bits 5,4,3 of h/w pointer position on later 10162306a36Sopenharmony_ci Rev G EEPROMS and Rev 1.5 cards or later. 10262306a36Sopenharmony_ci*/ 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci#define RME9652_REV15_buf_pos(x) ((((x)&0xE0000000)>>26)|((x)&RME9652_buf_pos)) 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/* amount of io space we remap for register access. i'm not sure we 10762306a36Sopenharmony_ci even need this much, but 1K is nice round number :) 10862306a36Sopenharmony_ci*/ 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci#define RME9652_IO_EXTENT 1024 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define RME9652_init_buffer 0 11362306a36Sopenharmony_ci#define RME9652_play_buffer 32 /* holds ptr to 26x64kBit host RAM */ 11462306a36Sopenharmony_ci#define RME9652_rec_buffer 36 /* holds ptr to 26x64kBit host RAM */ 11562306a36Sopenharmony_ci#define RME9652_control_register 64 11662306a36Sopenharmony_ci#define RME9652_irq_clear 96 11762306a36Sopenharmony_ci#define RME9652_time_code 100 /* useful if used with alesis adat */ 11862306a36Sopenharmony_ci#define RME9652_thru_base 128 /* 132...228 Thru for 26 channels */ 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* Read-only registers */ 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci/* Writing to any of the register locations writes to the status 12362306a36Sopenharmony_ci register. We'll use the first location as our point of access. 12462306a36Sopenharmony_ci*/ 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci#define RME9652_status_register 0 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci/* --------- Control-Register Bits ---------------- */ 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci#define RME9652_start_bit (1<<0) /* start record/play */ 13262306a36Sopenharmony_ci /* bits 1-3 encode buffersize/latency */ 13362306a36Sopenharmony_ci#define RME9652_Master (1<<4) /* Clock Mode Master=1,Slave/Auto=0 */ 13462306a36Sopenharmony_ci#define RME9652_IE (1<<5) /* Interrupt Enable */ 13562306a36Sopenharmony_ci#define RME9652_freq (1<<6) /* samplerate 0=44.1/88.2, 1=48/96 kHz */ 13662306a36Sopenharmony_ci#define RME9652_freq1 (1<<7) /* if 0, 32kHz, else always 1 */ 13762306a36Sopenharmony_ci#define RME9652_DS (1<<8) /* Doule Speed 0=44.1/48, 1=88.2/96 Khz */ 13862306a36Sopenharmony_ci#define RME9652_PRO (1<<9) /* S/PDIF out: 0=consumer, 1=professional */ 13962306a36Sopenharmony_ci#define RME9652_EMP (1<<10) /* Emphasis 0=None, 1=ON */ 14062306a36Sopenharmony_ci#define RME9652_Dolby (1<<11) /* Non-audio bit 1=set, 0=unset */ 14162306a36Sopenharmony_ci#define RME9652_opt_out (1<<12) /* Use 1st optical OUT as SPDIF: 1=yes,0=no */ 14262306a36Sopenharmony_ci#define RME9652_wsel (1<<13) /* use Wordclock as sync (overwrites master) */ 14362306a36Sopenharmony_ci#define RME9652_inp_0 (1<<14) /* SPDIF-IN: 00=optical (ADAT1), */ 14462306a36Sopenharmony_ci#define RME9652_inp_1 (1<<15) /* 01=koaxial (Cinch), 10=Internal CDROM */ 14562306a36Sopenharmony_ci#define RME9652_SyncPref_ADAT2 (1<<16) 14662306a36Sopenharmony_ci#define RME9652_SyncPref_ADAT3 (1<<17) 14762306a36Sopenharmony_ci#define RME9652_SPDIF_RESET (1<<18) /* Rev 1.5+: h/w S/PDIF receiver */ 14862306a36Sopenharmony_ci#define RME9652_SPDIF_SELECT (1<<19) 14962306a36Sopenharmony_ci#define RME9652_SPDIF_CLOCK (1<<20) 15062306a36Sopenharmony_ci#define RME9652_SPDIF_WRITE (1<<21) 15162306a36Sopenharmony_ci#define RME9652_ADAT1_INTERNAL (1<<22) /* Rev 1.5+: if set, internal CD connector carries ADAT */ 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* buffersize = 512Bytes * 2^n, where n is made from Bit2 ... Bit0 */ 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci#define RME9652_latency 0x0e 15662306a36Sopenharmony_ci#define rme9652_encode_latency(x) (((x)&0x7)<<1) 15762306a36Sopenharmony_ci#define rme9652_decode_latency(x) (((x)>>1)&0x7) 15862306a36Sopenharmony_ci#define rme9652_running_double_speed(s) ((s)->control_register & RME9652_DS) 15962306a36Sopenharmony_ci#define RME9652_inp (RME9652_inp_0|RME9652_inp_1) 16062306a36Sopenharmony_ci#define rme9652_encode_spdif_in(x) (((x)&0x3)<<14) 16162306a36Sopenharmony_ci#define rme9652_decode_spdif_in(x) (((x)>>14)&0x3) 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci#define RME9652_SyncPref_Mask (RME9652_SyncPref_ADAT2|RME9652_SyncPref_ADAT3) 16462306a36Sopenharmony_ci#define RME9652_SyncPref_ADAT1 0 16562306a36Sopenharmony_ci#define RME9652_SyncPref_SPDIF (RME9652_SyncPref_ADAT2|RME9652_SyncPref_ADAT3) 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci/* the size of a substream (1 mono data stream) */ 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci#define RME9652_CHANNEL_BUFFER_SAMPLES (16*1024) 17062306a36Sopenharmony_ci#define RME9652_CHANNEL_BUFFER_BYTES (4*RME9652_CHANNEL_BUFFER_SAMPLES) 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci/* the size of the area we need to allocate for DMA transfers. the 17362306a36Sopenharmony_ci size is the same regardless of the number of channels - the 17462306a36Sopenharmony_ci 9636 still uses the same memory area. 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci Note that we allocate 1 more channel than is apparently needed 17762306a36Sopenharmony_ci because the h/w seems to write 1 byte beyond the end of the last 17862306a36Sopenharmony_ci page. Sigh. 17962306a36Sopenharmony_ci*/ 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci#define RME9652_DMA_AREA_BYTES ((RME9652_NCHANNELS+1) * RME9652_CHANNEL_BUFFER_BYTES) 18262306a36Sopenharmony_ci#define RME9652_DMA_AREA_KILOBYTES (RME9652_DMA_AREA_BYTES/1024) 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistruct snd_rme9652 { 18562306a36Sopenharmony_ci int dev; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci spinlock_t lock; 18862306a36Sopenharmony_ci int irq; 18962306a36Sopenharmony_ci unsigned long port; 19062306a36Sopenharmony_ci void __iomem *iobase; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci int precise_ptr; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci u32 control_register; /* cached value */ 19562306a36Sopenharmony_ci u32 thru_bits; /* thru 1=on, 0=off channel 1=Bit1... channel 26= Bit26 */ 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci u32 creg_spdif; 19862306a36Sopenharmony_ci u32 creg_spdif_stream; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci char *card_name; /* hammerfall or hammerfall light names */ 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci size_t hw_offsetmask; /* &-with status register to get real hw_offset */ 20362306a36Sopenharmony_ci size_t prev_hw_offset; /* previous hw offset */ 20462306a36Sopenharmony_ci size_t max_jitter; /* maximum jitter in frames for 20562306a36Sopenharmony_ci hw pointer */ 20662306a36Sopenharmony_ci size_t period_bytes; /* guess what this is */ 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci unsigned char ds_channels; 20962306a36Sopenharmony_ci unsigned char ss_channels; /* different for hammerfall/hammerfall-light */ 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci /* DMA buffers; those are copied instances from the original snd_dma_buf 21262306a36Sopenharmony_ci * objects (which are managed via devres) for the address alignments 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_ci struct snd_dma_buffer playback_dma_buf; 21562306a36Sopenharmony_ci struct snd_dma_buffer capture_dma_buf; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci unsigned char *capture_buffer; /* suitably aligned address */ 21862306a36Sopenharmony_ci unsigned char *playback_buffer; /* suitably aligned address */ 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci pid_t capture_pid; 22162306a36Sopenharmony_ci pid_t playback_pid; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci struct snd_pcm_substream *capture_substream; 22462306a36Sopenharmony_ci struct snd_pcm_substream *playback_substream; 22562306a36Sopenharmony_ci int running; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci int passthru; /* non-zero if doing pass-thru */ 22862306a36Sopenharmony_ci int hw_rev; /* h/w rev * 10 (i.e. 1.5 has hw_rev = 15) */ 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci int last_spdif_sample_rate; /* so that we can catch externally ... */ 23162306a36Sopenharmony_ci int last_adat_sample_rate; /* ... induced rate changes */ 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci const signed char *channel_map; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci struct snd_card *card; 23662306a36Sopenharmony_ci struct snd_pcm *pcm; 23762306a36Sopenharmony_ci struct pci_dev *pci; 23862306a36Sopenharmony_ci struct snd_kcontrol *spdif_ctl; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci}; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci/* These tables map the ALSA channels 1..N to the channels that we 24362306a36Sopenharmony_ci need to use in order to find the relevant channel buffer. RME 24462306a36Sopenharmony_ci refer to this kind of mapping as between "the ADAT channel and 24562306a36Sopenharmony_ci the DMA channel." We index it using the logical audio channel, 24662306a36Sopenharmony_ci and the value is the DMA channel (i.e. channel buffer number) 24762306a36Sopenharmony_ci where the data for that channel can be read/written from/to. 24862306a36Sopenharmony_ci*/ 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic const signed char channel_map_9652_ss[26] = { 25162306a36Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 25262306a36Sopenharmony_ci 18, 19, 20, 21, 22, 23, 24, 25 25362306a36Sopenharmony_ci}; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic const signed char channel_map_9636_ss[26] = { 25662306a36Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 25762306a36Sopenharmony_ci /* channels 16 and 17 are S/PDIF */ 25862306a36Sopenharmony_ci 24, 25, 25962306a36Sopenharmony_ci /* channels 18-25 don't exist */ 26062306a36Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1 26162306a36Sopenharmony_ci}; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistatic const signed char channel_map_9652_ds[26] = { 26462306a36Sopenharmony_ci /* ADAT channels are remapped */ 26562306a36Sopenharmony_ci 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 26662306a36Sopenharmony_ci /* channels 12 and 13 are S/PDIF */ 26762306a36Sopenharmony_ci 24, 25, 26862306a36Sopenharmony_ci /* others don't exist */ 26962306a36Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 27062306a36Sopenharmony_ci}; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic const signed char channel_map_9636_ds[26] = { 27362306a36Sopenharmony_ci /* ADAT channels are remapped */ 27462306a36Sopenharmony_ci 1, 3, 5, 7, 9, 11, 13, 15, 27562306a36Sopenharmony_ci /* channels 8 and 9 are S/PDIF */ 27662306a36Sopenharmony_ci 24, 25, 27762306a36Sopenharmony_ci /* others don't exist */ 27862306a36Sopenharmony_ci -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 27962306a36Sopenharmony_ci}; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_cistatic struct snd_dma_buffer * 28262306a36Sopenharmony_cisnd_hammerfall_get_buffer(struct pci_dev *pci, size_t size) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci return snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, size); 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic const struct pci_device_id snd_rme9652_ids[] = { 28862306a36Sopenharmony_ci { 28962306a36Sopenharmony_ci .vendor = 0x10ee, 29062306a36Sopenharmony_ci .device = 0x3fc4, 29162306a36Sopenharmony_ci .subvendor = PCI_ANY_ID, 29262306a36Sopenharmony_ci .subdevice = PCI_ANY_ID, 29362306a36Sopenharmony_ci }, /* RME Digi9652 */ 29462306a36Sopenharmony_ci { 0, }, 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, snd_rme9652_ids); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_cistatic inline void rme9652_write(struct snd_rme9652 *rme9652, int reg, int val) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci writel(val, rme9652->iobase + reg); 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic inline unsigned int rme9652_read(struct snd_rme9652 *rme9652, int reg) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci return readl(rme9652->iobase + reg); 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic inline int snd_rme9652_use_is_exclusive(struct snd_rme9652 *rme9652) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci unsigned long flags; 31262306a36Sopenharmony_ci int ret = 1; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci spin_lock_irqsave(&rme9652->lock, flags); 31562306a36Sopenharmony_ci if ((rme9652->playback_pid != rme9652->capture_pid) && 31662306a36Sopenharmony_ci (rme9652->playback_pid >= 0) && (rme9652->capture_pid >= 0)) { 31762306a36Sopenharmony_ci ret = 0; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci spin_unlock_irqrestore(&rme9652->lock, flags); 32062306a36Sopenharmony_ci return ret; 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic inline int rme9652_adat_sample_rate(struct snd_rme9652 *rme9652) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci if (rme9652_running_double_speed(rme9652)) { 32662306a36Sopenharmony_ci return (rme9652_read(rme9652, RME9652_status_register) & 32762306a36Sopenharmony_ci RME9652_fs48) ? 96000 : 88200; 32862306a36Sopenharmony_ci } else { 32962306a36Sopenharmony_ci return (rme9652_read(rme9652, RME9652_status_register) & 33062306a36Sopenharmony_ci RME9652_fs48) ? 48000 : 44100; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic inline void rme9652_compute_period_size(struct snd_rme9652 *rme9652) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci unsigned int i; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci i = rme9652->control_register & RME9652_latency; 33962306a36Sopenharmony_ci rme9652->period_bytes = 1 << ((rme9652_decode_latency(i) + 8)); 34062306a36Sopenharmony_ci rme9652->hw_offsetmask = 34162306a36Sopenharmony_ci (rme9652->period_bytes * 2 - 1) & RME9652_buf_pos; 34262306a36Sopenharmony_ci rme9652->max_jitter = 80; 34362306a36Sopenharmony_ci} 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic snd_pcm_uframes_t rme9652_hw_pointer(struct snd_rme9652 *rme9652) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci int status; 34862306a36Sopenharmony_ci unsigned int offset, frag; 34962306a36Sopenharmony_ci snd_pcm_uframes_t period_size = rme9652->period_bytes / 4; 35062306a36Sopenharmony_ci snd_pcm_sframes_t delta; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci status = rme9652_read(rme9652, RME9652_status_register); 35362306a36Sopenharmony_ci if (!rme9652->precise_ptr) 35462306a36Sopenharmony_ci return (status & RME9652_buffer_id) ? period_size : 0; 35562306a36Sopenharmony_ci offset = status & RME9652_buf_pos; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /* The hardware may give a backward movement for up to 80 frames 35862306a36Sopenharmony_ci Martin Kirst <martin.kirst@freenet.de> knows the details. 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci delta = rme9652->prev_hw_offset - offset; 36262306a36Sopenharmony_ci delta &= 0xffff; 36362306a36Sopenharmony_ci if (delta <= (snd_pcm_sframes_t)rme9652->max_jitter * 4) 36462306a36Sopenharmony_ci offset = rme9652->prev_hw_offset; 36562306a36Sopenharmony_ci else 36662306a36Sopenharmony_ci rme9652->prev_hw_offset = offset; 36762306a36Sopenharmony_ci offset &= rme9652->hw_offsetmask; 36862306a36Sopenharmony_ci offset /= 4; 36962306a36Sopenharmony_ci frag = status & RME9652_buffer_id; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci if (offset < period_size) { 37262306a36Sopenharmony_ci if (offset > rme9652->max_jitter) { 37362306a36Sopenharmony_ci if (frag) 37462306a36Sopenharmony_ci dev_err(rme9652->card->dev, 37562306a36Sopenharmony_ci "Unexpected hw_pointer position (bufid == 0): status: %x offset: %d\n", 37662306a36Sopenharmony_ci status, offset); 37762306a36Sopenharmony_ci } else if (!frag) 37862306a36Sopenharmony_ci return 0; 37962306a36Sopenharmony_ci offset -= rme9652->max_jitter; 38062306a36Sopenharmony_ci if ((int)offset < 0) 38162306a36Sopenharmony_ci offset += period_size * 2; 38262306a36Sopenharmony_ci } else { 38362306a36Sopenharmony_ci if (offset > period_size + rme9652->max_jitter) { 38462306a36Sopenharmony_ci if (!frag) 38562306a36Sopenharmony_ci dev_err(rme9652->card->dev, 38662306a36Sopenharmony_ci "Unexpected hw_pointer position (bufid == 1): status: %x offset: %d\n", 38762306a36Sopenharmony_ci status, offset); 38862306a36Sopenharmony_ci } else if (frag) 38962306a36Sopenharmony_ci return period_size; 39062306a36Sopenharmony_ci offset -= rme9652->max_jitter; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci return offset; 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic inline void rme9652_reset_hw_pointer(struct snd_rme9652 *rme9652) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci int i; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci /* reset the FIFO pointer to zero. We do this by writing to 8 40162306a36Sopenharmony_ci registers, each of which is a 32bit wide register, and set 40262306a36Sopenharmony_ci them all to zero. Note that s->iobase is a pointer to 40362306a36Sopenharmony_ci int32, not pointer to char. 40462306a36Sopenharmony_ci */ 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 40762306a36Sopenharmony_ci rme9652_write(rme9652, i * 4, 0); 40862306a36Sopenharmony_ci udelay(10); 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci rme9652->prev_hw_offset = 0; 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_cistatic inline void rme9652_start(struct snd_rme9652 *s) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci s->control_register |= (RME9652_IE | RME9652_start_bit); 41662306a36Sopenharmony_ci rme9652_write(s, RME9652_control_register, s->control_register); 41762306a36Sopenharmony_ci} 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic inline void rme9652_stop(struct snd_rme9652 *s) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci s->control_register &= ~(RME9652_start_bit | RME9652_IE); 42262306a36Sopenharmony_ci rme9652_write(s, RME9652_control_register, s->control_register); 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic int rme9652_set_interrupt_interval(struct snd_rme9652 *s, 42662306a36Sopenharmony_ci unsigned int frames) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci int restart = 0; 42962306a36Sopenharmony_ci int n; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci spin_lock_irq(&s->lock); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci restart = s->running; 43462306a36Sopenharmony_ci if (restart) 43562306a36Sopenharmony_ci rme9652_stop(s); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci frames >>= 7; 43862306a36Sopenharmony_ci n = 0; 43962306a36Sopenharmony_ci while (frames) { 44062306a36Sopenharmony_ci n++; 44162306a36Sopenharmony_ci frames >>= 1; 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci s->control_register &= ~RME9652_latency; 44562306a36Sopenharmony_ci s->control_register |= rme9652_encode_latency(n); 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci rme9652_write(s, RME9652_control_register, s->control_register); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci rme9652_compute_period_size(s); 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (restart) 45262306a36Sopenharmony_ci rme9652_start(s); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci spin_unlock_irq(&s->lock); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci return 0; 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic int rme9652_set_rate(struct snd_rme9652 *rme9652, int rate) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci int restart; 46262306a36Sopenharmony_ci int reject_if_open = 0; 46362306a36Sopenharmony_ci int xrate; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci if (!snd_rme9652_use_is_exclusive (rme9652)) { 46662306a36Sopenharmony_ci return -EBUSY; 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci /* Changing from a "single speed" to a "double speed" rate is 47062306a36Sopenharmony_ci not allowed if any substreams are open. This is because 47162306a36Sopenharmony_ci such a change causes a shift in the location of 47262306a36Sopenharmony_ci the DMA buffers and a reduction in the number of available 47362306a36Sopenharmony_ci buffers. 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci Note that a similar but essentially insoluble problem 47662306a36Sopenharmony_ci exists for externally-driven rate changes. All we can do 47762306a36Sopenharmony_ci is to flag rate changes in the read/write routines. 47862306a36Sopenharmony_ci */ 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 48162306a36Sopenharmony_ci xrate = rme9652_adat_sample_rate(rme9652); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci switch (rate) { 48462306a36Sopenharmony_ci case 44100: 48562306a36Sopenharmony_ci if (xrate > 48000) { 48662306a36Sopenharmony_ci reject_if_open = 1; 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci rate = 0; 48962306a36Sopenharmony_ci break; 49062306a36Sopenharmony_ci case 48000: 49162306a36Sopenharmony_ci if (xrate > 48000) { 49262306a36Sopenharmony_ci reject_if_open = 1; 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci rate = RME9652_freq; 49562306a36Sopenharmony_ci break; 49662306a36Sopenharmony_ci case 88200: 49762306a36Sopenharmony_ci if (xrate < 48000) { 49862306a36Sopenharmony_ci reject_if_open = 1; 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci rate = RME9652_DS; 50162306a36Sopenharmony_ci break; 50262306a36Sopenharmony_ci case 96000: 50362306a36Sopenharmony_ci if (xrate < 48000) { 50462306a36Sopenharmony_ci reject_if_open = 1; 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci rate = RME9652_DS | RME9652_freq; 50762306a36Sopenharmony_ci break; 50862306a36Sopenharmony_ci default: 50962306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 51062306a36Sopenharmony_ci return -EINVAL; 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci if (reject_if_open && (rme9652->capture_pid >= 0 || rme9652->playback_pid >= 0)) { 51462306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 51562306a36Sopenharmony_ci return -EBUSY; 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci restart = rme9652->running; 51962306a36Sopenharmony_ci if (restart) 52062306a36Sopenharmony_ci rme9652_stop(rme9652); 52162306a36Sopenharmony_ci rme9652->control_register &= ~(RME9652_freq | RME9652_DS); 52262306a36Sopenharmony_ci rme9652->control_register |= rate; 52362306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci if (restart) 52662306a36Sopenharmony_ci rme9652_start(rme9652); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci if (rate & RME9652_DS) { 52962306a36Sopenharmony_ci if (rme9652->ss_channels == RME9652_NCHANNELS) { 53062306a36Sopenharmony_ci rme9652->channel_map = channel_map_9652_ds; 53162306a36Sopenharmony_ci } else { 53262306a36Sopenharmony_ci rme9652->channel_map = channel_map_9636_ds; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci } else { 53562306a36Sopenharmony_ci if (rme9652->ss_channels == RME9652_NCHANNELS) { 53662306a36Sopenharmony_ci rme9652->channel_map = channel_map_9652_ss; 53762306a36Sopenharmony_ci } else { 53862306a36Sopenharmony_ci rme9652->channel_map = channel_map_9636_ss; 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 54362306a36Sopenharmony_ci return 0; 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic void rme9652_set_thru(struct snd_rme9652 *rme9652, int channel, int enable) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci int i; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci rme9652->passthru = 0; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci if (channel < 0) { 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci /* set thru for all channels */ 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci if (enable) { 55762306a36Sopenharmony_ci for (i = 0; i < RME9652_NCHANNELS; i++) { 55862306a36Sopenharmony_ci rme9652->thru_bits |= (1 << i); 55962306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_thru_base + i * 4, 1); 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci } else { 56262306a36Sopenharmony_ci for (i = 0; i < RME9652_NCHANNELS; i++) { 56362306a36Sopenharmony_ci rme9652->thru_bits &= ~(1 << i); 56462306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_thru_base + i * 4, 0); 56562306a36Sopenharmony_ci } 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci } else { 56962306a36Sopenharmony_ci int mapped_channel; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci mapped_channel = rme9652->channel_map[channel]; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci if (enable) { 57462306a36Sopenharmony_ci rme9652->thru_bits |= (1 << mapped_channel); 57562306a36Sopenharmony_ci } else { 57662306a36Sopenharmony_ci rme9652->thru_bits &= ~(1 << mapped_channel); 57762306a36Sopenharmony_ci } 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci rme9652_write(rme9652, 58062306a36Sopenharmony_ci RME9652_thru_base + mapped_channel * 4, 58162306a36Sopenharmony_ci enable ? 1 : 0); 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci} 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_cistatic int rme9652_set_passthru(struct snd_rme9652 *rme9652, int onoff) 58662306a36Sopenharmony_ci{ 58762306a36Sopenharmony_ci if (onoff) { 58862306a36Sopenharmony_ci rme9652_set_thru(rme9652, -1, 1); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci /* we don't want interrupts, so do a 59162306a36Sopenharmony_ci custom version of rme9652_start(). 59262306a36Sopenharmony_ci */ 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci rme9652->control_register = 59562306a36Sopenharmony_ci RME9652_inp_0 | 59662306a36Sopenharmony_ci rme9652_encode_latency(7) | 59762306a36Sopenharmony_ci RME9652_start_bit; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci rme9652_reset_hw_pointer(rme9652); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, 60262306a36Sopenharmony_ci rme9652->control_register); 60362306a36Sopenharmony_ci rme9652->passthru = 1; 60462306a36Sopenharmony_ci } else { 60562306a36Sopenharmony_ci rme9652_set_thru(rme9652, -1, 0); 60662306a36Sopenharmony_ci rme9652_stop(rme9652); 60762306a36Sopenharmony_ci rme9652->passthru = 0; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci return 0; 61162306a36Sopenharmony_ci} 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_cistatic void rme9652_spdif_set_bit (struct snd_rme9652 *rme9652, int mask, int onoff) 61462306a36Sopenharmony_ci{ 61562306a36Sopenharmony_ci if (onoff) 61662306a36Sopenharmony_ci rme9652->control_register |= mask; 61762306a36Sopenharmony_ci else 61862306a36Sopenharmony_ci rme9652->control_register &= ~mask; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_cistatic void rme9652_spdif_write_byte (struct snd_rme9652 *rme9652, const int val) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci long mask; 62662306a36Sopenharmony_ci long i; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci for (i = 0, mask = 0x80; i < 8; i++, mask >>= 1) { 62962306a36Sopenharmony_ci if (val & mask) 63062306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_WRITE, 1); 63162306a36Sopenharmony_ci else 63262306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_WRITE, 0); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 1); 63562306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 0); 63662306a36Sopenharmony_ci } 63762306a36Sopenharmony_ci} 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_cistatic int rme9652_spdif_read_byte (struct snd_rme9652 *rme9652) 64062306a36Sopenharmony_ci{ 64162306a36Sopenharmony_ci long mask; 64262306a36Sopenharmony_ci long val; 64362306a36Sopenharmony_ci long i; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci val = 0; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci for (i = 0, mask = 0x80; i < 8; i++, mask >>= 1) { 64862306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 1); 64962306a36Sopenharmony_ci if (rme9652_read (rme9652, RME9652_status_register) & RME9652_SPDIF_READ) 65062306a36Sopenharmony_ci val |= mask; 65162306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_CLOCK, 0); 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci return val; 65562306a36Sopenharmony_ci} 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_cistatic void rme9652_write_spdif_codec (struct snd_rme9652 *rme9652, const int address, const int data) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 1); 66062306a36Sopenharmony_ci rme9652_spdif_write_byte (rme9652, 0x20); 66162306a36Sopenharmony_ci rme9652_spdif_write_byte (rme9652, address); 66262306a36Sopenharmony_ci rme9652_spdif_write_byte (rme9652, data); 66362306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 0); 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_cistatic int rme9652_spdif_read_codec (struct snd_rme9652 *rme9652, const int address) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci int ret; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 1); 67262306a36Sopenharmony_ci rme9652_spdif_write_byte (rme9652, 0x20); 67362306a36Sopenharmony_ci rme9652_spdif_write_byte (rme9652, address); 67462306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 0); 67562306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 1); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci rme9652_spdif_write_byte (rme9652, 0x21); 67862306a36Sopenharmony_ci ret = rme9652_spdif_read_byte (rme9652); 67962306a36Sopenharmony_ci rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 0); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci return ret; 68262306a36Sopenharmony_ci} 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_cistatic void rme9652_initialize_spdif_receiver (struct snd_rme9652 *rme9652) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci /* XXX what unsets this ? */ 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci rme9652->control_register |= RME9652_SPDIF_RESET; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci rme9652_write_spdif_codec (rme9652, 4, 0x40); 69162306a36Sopenharmony_ci rme9652_write_spdif_codec (rme9652, 17, 0x13); 69262306a36Sopenharmony_ci rme9652_write_spdif_codec (rme9652, 6, 0x02); 69362306a36Sopenharmony_ci} 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_cistatic inline int rme9652_spdif_sample_rate(struct snd_rme9652 *s) 69662306a36Sopenharmony_ci{ 69762306a36Sopenharmony_ci unsigned int rate_bits; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci if (rme9652_read(s, RME9652_status_register) & RME9652_ERF) { 70062306a36Sopenharmony_ci return -1; /* error condition */ 70162306a36Sopenharmony_ci } 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci if (s->hw_rev == 15) { 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci int x, y, ret; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci x = rme9652_spdif_read_codec (s, 30); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci if (x != 0) 71062306a36Sopenharmony_ci y = 48000 * 64 / x; 71162306a36Sopenharmony_ci else 71262306a36Sopenharmony_ci y = 0; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci if (y > 30400 && y < 33600) ret = 32000; 71562306a36Sopenharmony_ci else if (y > 41900 && y < 46000) ret = 44100; 71662306a36Sopenharmony_ci else if (y > 46000 && y < 50400) ret = 48000; 71762306a36Sopenharmony_ci else if (y > 60800 && y < 67200) ret = 64000; 71862306a36Sopenharmony_ci else if (y > 83700 && y < 92000) ret = 88200; 71962306a36Sopenharmony_ci else if (y > 92000 && y < 100000) ret = 96000; 72062306a36Sopenharmony_ci else ret = 0; 72162306a36Sopenharmony_ci return ret; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci rate_bits = rme9652_read(s, RME9652_status_register) & RME9652_F; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci switch (rme9652_decode_spdif_rate(rate_bits)) { 72762306a36Sopenharmony_ci case 0x7: 72862306a36Sopenharmony_ci return 32000; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci case 0x6: 73162306a36Sopenharmony_ci return 44100; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci case 0x5: 73462306a36Sopenharmony_ci return 48000; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci case 0x4: 73762306a36Sopenharmony_ci return 88200; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci case 0x3: 74062306a36Sopenharmony_ci return 96000; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci case 0x0: 74362306a36Sopenharmony_ci return 64000; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci default: 74662306a36Sopenharmony_ci dev_err(s->card->dev, 74762306a36Sopenharmony_ci "%s: unknown S/PDIF input rate (bits = 0x%x)\n", 74862306a36Sopenharmony_ci s->card_name, rate_bits); 74962306a36Sopenharmony_ci return 0; 75062306a36Sopenharmony_ci } 75162306a36Sopenharmony_ci} 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci/*----------------------------------------------------------------------------- 75462306a36Sopenharmony_ci Control Interface 75562306a36Sopenharmony_ci ----------------------------------------------------------------------------*/ 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_cistatic u32 snd_rme9652_convert_from_aes(struct snd_aes_iec958 *aes) 75862306a36Sopenharmony_ci{ 75962306a36Sopenharmony_ci u32 val = 0; 76062306a36Sopenharmony_ci val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME9652_PRO : 0; 76162306a36Sopenharmony_ci val |= (aes->status[0] & IEC958_AES0_NONAUDIO) ? RME9652_Dolby : 0; 76262306a36Sopenharmony_ci if (val & RME9652_PRO) 76362306a36Sopenharmony_ci val |= (aes->status[0] & IEC958_AES0_PRO_EMPHASIS_5015) ? RME9652_EMP : 0; 76462306a36Sopenharmony_ci else 76562306a36Sopenharmony_ci val |= (aes->status[0] & IEC958_AES0_CON_EMPHASIS_5015) ? RME9652_EMP : 0; 76662306a36Sopenharmony_ci return val; 76762306a36Sopenharmony_ci} 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_cistatic void snd_rme9652_convert_to_aes(struct snd_aes_iec958 *aes, u32 val) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci aes->status[0] = ((val & RME9652_PRO) ? IEC958_AES0_PROFESSIONAL : 0) | 77262306a36Sopenharmony_ci ((val & RME9652_Dolby) ? IEC958_AES0_NONAUDIO : 0); 77362306a36Sopenharmony_ci if (val & RME9652_PRO) 77462306a36Sopenharmony_ci aes->status[0] |= (val & RME9652_EMP) ? IEC958_AES0_PRO_EMPHASIS_5015 : 0; 77562306a36Sopenharmony_ci else 77662306a36Sopenharmony_ci aes->status[0] |= (val & RME9652_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0; 77762306a36Sopenharmony_ci} 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_cistatic int snd_rme9652_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 78062306a36Sopenharmony_ci{ 78162306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 78262306a36Sopenharmony_ci uinfo->count = 1; 78362306a36Sopenharmony_ci return 0; 78462306a36Sopenharmony_ci} 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_cistatic int snd_rme9652_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 78762306a36Sopenharmony_ci{ 78862306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif); 79162306a36Sopenharmony_ci return 0; 79262306a36Sopenharmony_ci} 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_cistatic int snd_rme9652_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 79562306a36Sopenharmony_ci{ 79662306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 79762306a36Sopenharmony_ci int change; 79862306a36Sopenharmony_ci u32 val; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958); 80162306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 80262306a36Sopenharmony_ci change = val != rme9652->creg_spdif; 80362306a36Sopenharmony_ci rme9652->creg_spdif = val; 80462306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 80562306a36Sopenharmony_ci return change; 80662306a36Sopenharmony_ci} 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_cistatic int snd_rme9652_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 80962306a36Sopenharmony_ci{ 81062306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 81162306a36Sopenharmony_ci uinfo->count = 1; 81262306a36Sopenharmony_ci return 0; 81362306a36Sopenharmony_ci} 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_cistatic int snd_rme9652_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 81662306a36Sopenharmony_ci{ 81762306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif_stream); 82062306a36Sopenharmony_ci return 0; 82162306a36Sopenharmony_ci} 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic int snd_rme9652_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 82462306a36Sopenharmony_ci{ 82562306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 82662306a36Sopenharmony_ci int change; 82762306a36Sopenharmony_ci u32 val; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958); 83062306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 83162306a36Sopenharmony_ci change = val != rme9652->creg_spdif_stream; 83262306a36Sopenharmony_ci rme9652->creg_spdif_stream = val; 83362306a36Sopenharmony_ci rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP); 83462306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= val); 83562306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 83662306a36Sopenharmony_ci return change; 83762306a36Sopenharmony_ci} 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_cistatic int snd_rme9652_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 84062306a36Sopenharmony_ci{ 84162306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 84262306a36Sopenharmony_ci uinfo->count = 1; 84362306a36Sopenharmony_ci return 0; 84462306a36Sopenharmony_ci} 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_cistatic int snd_rme9652_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 84762306a36Sopenharmony_ci{ 84862306a36Sopenharmony_ci ucontrol->value.iec958.status[0] = kcontrol->private_value; 84962306a36Sopenharmony_ci return 0; 85062306a36Sopenharmony_ci} 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci#define RME9652_ADAT1_IN(xname, xindex) \ 85362306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 85462306a36Sopenharmony_ci .info = snd_rme9652_info_adat1_in, \ 85562306a36Sopenharmony_ci .get = snd_rme9652_get_adat1_in, \ 85662306a36Sopenharmony_ci .put = snd_rme9652_put_adat1_in } 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_cistatic unsigned int rme9652_adat1_in(struct snd_rme9652 *rme9652) 85962306a36Sopenharmony_ci{ 86062306a36Sopenharmony_ci if (rme9652->control_register & RME9652_ADAT1_INTERNAL) 86162306a36Sopenharmony_ci return 1; 86262306a36Sopenharmony_ci return 0; 86362306a36Sopenharmony_ci} 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_cistatic int rme9652_set_adat1_input(struct snd_rme9652 *rme9652, int internal) 86662306a36Sopenharmony_ci{ 86762306a36Sopenharmony_ci int restart = 0; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci if (internal) { 87062306a36Sopenharmony_ci rme9652->control_register |= RME9652_ADAT1_INTERNAL; 87162306a36Sopenharmony_ci } else { 87262306a36Sopenharmony_ci rme9652->control_register &= ~RME9652_ADAT1_INTERNAL; 87362306a36Sopenharmony_ci } 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci /* XXX do we actually need to stop the card when we do this ? */ 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci restart = rme9652->running; 87862306a36Sopenharmony_ci if (restart) 87962306a36Sopenharmony_ci rme9652_stop(rme9652); 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci if (restart) 88462306a36Sopenharmony_ci rme9652_start(rme9652); 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci return 0; 88762306a36Sopenharmony_ci} 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_cistatic int snd_rme9652_info_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 89062306a36Sopenharmony_ci{ 89162306a36Sopenharmony_ci static const char * const texts[2] = {"ADAT1", "Internal"}; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 2, texts); 89462306a36Sopenharmony_ci} 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_cistatic int snd_rme9652_get_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 89762306a36Sopenharmony_ci{ 89862306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 90162306a36Sopenharmony_ci ucontrol->value.enumerated.item[0] = rme9652_adat1_in(rme9652); 90262306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 90362306a36Sopenharmony_ci return 0; 90462306a36Sopenharmony_ci} 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_cistatic int snd_rme9652_put_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 90762306a36Sopenharmony_ci{ 90862306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 90962306a36Sopenharmony_ci int change; 91062306a36Sopenharmony_ci unsigned int val; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci if (!snd_rme9652_use_is_exclusive(rme9652)) 91362306a36Sopenharmony_ci return -EBUSY; 91462306a36Sopenharmony_ci val = ucontrol->value.enumerated.item[0] % 2; 91562306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 91662306a36Sopenharmony_ci change = val != rme9652_adat1_in(rme9652); 91762306a36Sopenharmony_ci if (change) 91862306a36Sopenharmony_ci rme9652_set_adat1_input(rme9652, val); 91962306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 92062306a36Sopenharmony_ci return change; 92162306a36Sopenharmony_ci} 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci#define RME9652_SPDIF_IN(xname, xindex) \ 92462306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 92562306a36Sopenharmony_ci .info = snd_rme9652_info_spdif_in, \ 92662306a36Sopenharmony_ci .get = snd_rme9652_get_spdif_in, .put = snd_rme9652_put_spdif_in } 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_cistatic unsigned int rme9652_spdif_in(struct snd_rme9652 *rme9652) 92962306a36Sopenharmony_ci{ 93062306a36Sopenharmony_ci return rme9652_decode_spdif_in(rme9652->control_register & 93162306a36Sopenharmony_ci RME9652_inp); 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_cistatic int rme9652_set_spdif_input(struct snd_rme9652 *rme9652, int in) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci int restart = 0; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci rme9652->control_register &= ~RME9652_inp; 93962306a36Sopenharmony_ci rme9652->control_register |= rme9652_encode_spdif_in(in); 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci restart = rme9652->running; 94262306a36Sopenharmony_ci if (restart) 94362306a36Sopenharmony_ci rme9652_stop(rme9652); 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci if (restart) 94862306a36Sopenharmony_ci rme9652_start(rme9652); 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci return 0; 95162306a36Sopenharmony_ci} 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_cistatic int snd_rme9652_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci static const char * const texts[3] = {"ADAT1", "Coaxial", "Internal"}; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 3, texts); 95862306a36Sopenharmony_ci} 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_cistatic int snd_rme9652_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 96162306a36Sopenharmony_ci{ 96262306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 96562306a36Sopenharmony_ci ucontrol->value.enumerated.item[0] = rme9652_spdif_in(rme9652); 96662306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 96762306a36Sopenharmony_ci return 0; 96862306a36Sopenharmony_ci} 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_cistatic int snd_rme9652_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 97162306a36Sopenharmony_ci{ 97262306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 97362306a36Sopenharmony_ci int change; 97462306a36Sopenharmony_ci unsigned int val; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci if (!snd_rme9652_use_is_exclusive(rme9652)) 97762306a36Sopenharmony_ci return -EBUSY; 97862306a36Sopenharmony_ci val = ucontrol->value.enumerated.item[0] % 3; 97962306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 98062306a36Sopenharmony_ci change = val != rme9652_spdif_in(rme9652); 98162306a36Sopenharmony_ci if (change) 98262306a36Sopenharmony_ci rme9652_set_spdif_input(rme9652, val); 98362306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 98462306a36Sopenharmony_ci return change; 98562306a36Sopenharmony_ci} 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci#define RME9652_SPDIF_OUT(xname, xindex) \ 98862306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 98962306a36Sopenharmony_ci .info = snd_rme9652_info_spdif_out, \ 99062306a36Sopenharmony_ci .get = snd_rme9652_get_spdif_out, .put = snd_rme9652_put_spdif_out } 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_cistatic int rme9652_spdif_out(struct snd_rme9652 *rme9652) 99362306a36Sopenharmony_ci{ 99462306a36Sopenharmony_ci return (rme9652->control_register & RME9652_opt_out) ? 1 : 0; 99562306a36Sopenharmony_ci} 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_cistatic int rme9652_set_spdif_output(struct snd_rme9652 *rme9652, int out) 99862306a36Sopenharmony_ci{ 99962306a36Sopenharmony_ci int restart = 0; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci if (out) { 100262306a36Sopenharmony_ci rme9652->control_register |= RME9652_opt_out; 100362306a36Sopenharmony_ci } else { 100462306a36Sopenharmony_ci rme9652->control_register &= ~RME9652_opt_out; 100562306a36Sopenharmony_ci } 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci restart = rme9652->running; 100862306a36Sopenharmony_ci if (restart) 100962306a36Sopenharmony_ci rme9652_stop(rme9652); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci if (restart) 101462306a36Sopenharmony_ci rme9652_start(rme9652); 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci return 0; 101762306a36Sopenharmony_ci} 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci#define snd_rme9652_info_spdif_out snd_ctl_boolean_mono_info 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_cistatic int snd_rme9652_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 102262306a36Sopenharmony_ci{ 102362306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 102662306a36Sopenharmony_ci ucontrol->value.integer.value[0] = rme9652_spdif_out(rme9652); 102762306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 102862306a36Sopenharmony_ci return 0; 102962306a36Sopenharmony_ci} 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_cistatic int snd_rme9652_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 103262306a36Sopenharmony_ci{ 103362306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 103462306a36Sopenharmony_ci int change; 103562306a36Sopenharmony_ci unsigned int val; 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci if (!snd_rme9652_use_is_exclusive(rme9652)) 103862306a36Sopenharmony_ci return -EBUSY; 103962306a36Sopenharmony_ci val = ucontrol->value.integer.value[0] & 1; 104062306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 104162306a36Sopenharmony_ci change = (int)val != rme9652_spdif_out(rme9652); 104262306a36Sopenharmony_ci rme9652_set_spdif_output(rme9652, val); 104362306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 104462306a36Sopenharmony_ci return change; 104562306a36Sopenharmony_ci} 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci#define RME9652_SYNC_MODE(xname, xindex) \ 104862306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 104962306a36Sopenharmony_ci .info = snd_rme9652_info_sync_mode, \ 105062306a36Sopenharmony_ci .get = snd_rme9652_get_sync_mode, .put = snd_rme9652_put_sync_mode } 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_cistatic int rme9652_sync_mode(struct snd_rme9652 *rme9652) 105362306a36Sopenharmony_ci{ 105462306a36Sopenharmony_ci if (rme9652->control_register & RME9652_wsel) { 105562306a36Sopenharmony_ci return 2; 105662306a36Sopenharmony_ci } else if (rme9652->control_register & RME9652_Master) { 105762306a36Sopenharmony_ci return 1; 105862306a36Sopenharmony_ci } else { 105962306a36Sopenharmony_ci return 0; 106062306a36Sopenharmony_ci } 106162306a36Sopenharmony_ci} 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_cistatic int rme9652_set_sync_mode(struct snd_rme9652 *rme9652, int mode) 106462306a36Sopenharmony_ci{ 106562306a36Sopenharmony_ci int restart = 0; 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci switch (mode) { 106862306a36Sopenharmony_ci case 0: 106962306a36Sopenharmony_ci rme9652->control_register &= 107062306a36Sopenharmony_ci ~(RME9652_Master | RME9652_wsel); 107162306a36Sopenharmony_ci break; 107262306a36Sopenharmony_ci case 1: 107362306a36Sopenharmony_ci rme9652->control_register = 107462306a36Sopenharmony_ci (rme9652->control_register & ~RME9652_wsel) | RME9652_Master; 107562306a36Sopenharmony_ci break; 107662306a36Sopenharmony_ci case 2: 107762306a36Sopenharmony_ci rme9652->control_register |= 107862306a36Sopenharmony_ci (RME9652_Master | RME9652_wsel); 107962306a36Sopenharmony_ci break; 108062306a36Sopenharmony_ci } 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci restart = rme9652->running; 108362306a36Sopenharmony_ci if (restart) 108462306a36Sopenharmony_ci rme9652_stop(rme9652); 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci if (restart) 108962306a36Sopenharmony_ci rme9652_start(rme9652); 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci return 0; 109262306a36Sopenharmony_ci} 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_cistatic int snd_rme9652_info_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 109562306a36Sopenharmony_ci{ 109662306a36Sopenharmony_ci static const char * const texts[3] = { 109762306a36Sopenharmony_ci "AutoSync", "Master", "Word Clock" 109862306a36Sopenharmony_ci }; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 3, texts); 110162306a36Sopenharmony_ci} 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_cistatic int snd_rme9652_get_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 110462306a36Sopenharmony_ci{ 110562306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 110862306a36Sopenharmony_ci ucontrol->value.enumerated.item[0] = rme9652_sync_mode(rme9652); 110962306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 111062306a36Sopenharmony_ci return 0; 111162306a36Sopenharmony_ci} 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_cistatic int snd_rme9652_put_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 111462306a36Sopenharmony_ci{ 111562306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 111662306a36Sopenharmony_ci int change; 111762306a36Sopenharmony_ci unsigned int val; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci val = ucontrol->value.enumerated.item[0] % 3; 112062306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 112162306a36Sopenharmony_ci change = (int)val != rme9652_sync_mode(rme9652); 112262306a36Sopenharmony_ci rme9652_set_sync_mode(rme9652, val); 112362306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 112462306a36Sopenharmony_ci return change; 112562306a36Sopenharmony_ci} 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci#define RME9652_SYNC_PREF(xname, xindex) \ 112862306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 112962306a36Sopenharmony_ci .info = snd_rme9652_info_sync_pref, \ 113062306a36Sopenharmony_ci .get = snd_rme9652_get_sync_pref, .put = snd_rme9652_put_sync_pref } 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_cistatic int rme9652_sync_pref(struct snd_rme9652 *rme9652) 113362306a36Sopenharmony_ci{ 113462306a36Sopenharmony_ci switch (rme9652->control_register & RME9652_SyncPref_Mask) { 113562306a36Sopenharmony_ci case RME9652_SyncPref_ADAT1: 113662306a36Sopenharmony_ci return RME9652_SYNC_FROM_ADAT1; 113762306a36Sopenharmony_ci case RME9652_SyncPref_ADAT2: 113862306a36Sopenharmony_ci return RME9652_SYNC_FROM_ADAT2; 113962306a36Sopenharmony_ci case RME9652_SyncPref_ADAT3: 114062306a36Sopenharmony_ci return RME9652_SYNC_FROM_ADAT3; 114162306a36Sopenharmony_ci case RME9652_SyncPref_SPDIF: 114262306a36Sopenharmony_ci return RME9652_SYNC_FROM_SPDIF; 114362306a36Sopenharmony_ci } 114462306a36Sopenharmony_ci /* Not reachable */ 114562306a36Sopenharmony_ci return 0; 114662306a36Sopenharmony_ci} 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_cistatic int rme9652_set_sync_pref(struct snd_rme9652 *rme9652, int pref) 114962306a36Sopenharmony_ci{ 115062306a36Sopenharmony_ci int restart; 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci rme9652->control_register &= ~RME9652_SyncPref_Mask; 115362306a36Sopenharmony_ci switch (pref) { 115462306a36Sopenharmony_ci case RME9652_SYNC_FROM_ADAT1: 115562306a36Sopenharmony_ci rme9652->control_register |= RME9652_SyncPref_ADAT1; 115662306a36Sopenharmony_ci break; 115762306a36Sopenharmony_ci case RME9652_SYNC_FROM_ADAT2: 115862306a36Sopenharmony_ci rme9652->control_register |= RME9652_SyncPref_ADAT2; 115962306a36Sopenharmony_ci break; 116062306a36Sopenharmony_ci case RME9652_SYNC_FROM_ADAT3: 116162306a36Sopenharmony_ci rme9652->control_register |= RME9652_SyncPref_ADAT3; 116262306a36Sopenharmony_ci break; 116362306a36Sopenharmony_ci case RME9652_SYNC_FROM_SPDIF: 116462306a36Sopenharmony_ci rme9652->control_register |= RME9652_SyncPref_SPDIF; 116562306a36Sopenharmony_ci break; 116662306a36Sopenharmony_ci } 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci restart = rme9652->running; 116962306a36Sopenharmony_ci if (restart) 117062306a36Sopenharmony_ci rme9652_stop(rme9652); 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci if (restart) 117562306a36Sopenharmony_ci rme9652_start(rme9652); 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci return 0; 117862306a36Sopenharmony_ci} 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_cistatic int snd_rme9652_info_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 118162306a36Sopenharmony_ci{ 118262306a36Sopenharmony_ci static const char * const texts[4] = { 118362306a36Sopenharmony_ci "IEC958 In", "ADAT1 In", "ADAT2 In", "ADAT3 In" 118462306a36Sopenharmony_ci }; 118562306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 118862306a36Sopenharmony_ci rme9652->ss_channels == RME9652_NCHANNELS ? 4 : 3, 118962306a36Sopenharmony_ci texts); 119062306a36Sopenharmony_ci} 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_cistatic int snd_rme9652_get_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 119362306a36Sopenharmony_ci{ 119462306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 119762306a36Sopenharmony_ci ucontrol->value.enumerated.item[0] = rme9652_sync_pref(rme9652); 119862306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 119962306a36Sopenharmony_ci return 0; 120062306a36Sopenharmony_ci} 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_cistatic int snd_rme9652_put_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 120362306a36Sopenharmony_ci{ 120462306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 120562306a36Sopenharmony_ci int change, max; 120662306a36Sopenharmony_ci unsigned int val; 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci if (!snd_rme9652_use_is_exclusive(rme9652)) 120962306a36Sopenharmony_ci return -EBUSY; 121062306a36Sopenharmony_ci max = rme9652->ss_channels == RME9652_NCHANNELS ? 4 : 3; 121162306a36Sopenharmony_ci val = ucontrol->value.enumerated.item[0] % max; 121262306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 121362306a36Sopenharmony_ci change = (int)val != rme9652_sync_pref(rme9652); 121462306a36Sopenharmony_ci rme9652_set_sync_pref(rme9652, val); 121562306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 121662306a36Sopenharmony_ci return change; 121762306a36Sopenharmony_ci} 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_cistatic int snd_rme9652_info_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 122062306a36Sopenharmony_ci{ 122162306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 122262306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 122362306a36Sopenharmony_ci uinfo->count = rme9652->ss_channels; 122462306a36Sopenharmony_ci uinfo->value.integer.min = 0; 122562306a36Sopenharmony_ci uinfo->value.integer.max = 1; 122662306a36Sopenharmony_ci return 0; 122762306a36Sopenharmony_ci} 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_cistatic int snd_rme9652_get_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 123062306a36Sopenharmony_ci{ 123162306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 123262306a36Sopenharmony_ci unsigned int k; 123362306a36Sopenharmony_ci u32 thru_bits = rme9652->thru_bits; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci for (k = 0; k < rme9652->ss_channels; ++k) { 123662306a36Sopenharmony_ci ucontrol->value.integer.value[k] = !!(thru_bits & (1 << k)); 123762306a36Sopenharmony_ci } 123862306a36Sopenharmony_ci return 0; 123962306a36Sopenharmony_ci} 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_cistatic int snd_rme9652_put_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 124262306a36Sopenharmony_ci{ 124362306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 124462306a36Sopenharmony_ci int change; 124562306a36Sopenharmony_ci unsigned int chn; 124662306a36Sopenharmony_ci u32 thru_bits = 0; 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci if (!snd_rme9652_use_is_exclusive(rme9652)) 124962306a36Sopenharmony_ci return -EBUSY; 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci for (chn = 0; chn < rme9652->ss_channels; ++chn) { 125262306a36Sopenharmony_ci if (ucontrol->value.integer.value[chn]) 125362306a36Sopenharmony_ci thru_bits |= 1 << chn; 125462306a36Sopenharmony_ci } 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 125762306a36Sopenharmony_ci change = thru_bits ^ rme9652->thru_bits; 125862306a36Sopenharmony_ci if (change) { 125962306a36Sopenharmony_ci for (chn = 0; chn < rme9652->ss_channels; ++chn) { 126062306a36Sopenharmony_ci if (!(change & (1 << chn))) 126162306a36Sopenharmony_ci continue; 126262306a36Sopenharmony_ci rme9652_set_thru(rme9652,chn,thru_bits&(1<<chn)); 126362306a36Sopenharmony_ci } 126462306a36Sopenharmony_ci } 126562306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 126662306a36Sopenharmony_ci return !!change; 126762306a36Sopenharmony_ci} 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci#define RME9652_PASSTHRU(xname, xindex) \ 127062306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 127162306a36Sopenharmony_ci .info = snd_rme9652_info_passthru, \ 127262306a36Sopenharmony_ci .put = snd_rme9652_put_passthru, \ 127362306a36Sopenharmony_ci .get = snd_rme9652_get_passthru } 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci#define snd_rme9652_info_passthru snd_ctl_boolean_mono_info 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_cistatic int snd_rme9652_get_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 127862306a36Sopenharmony_ci{ 127962306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 128262306a36Sopenharmony_ci ucontrol->value.integer.value[0] = rme9652->passthru; 128362306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 128462306a36Sopenharmony_ci return 0; 128562306a36Sopenharmony_ci} 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_cistatic int snd_rme9652_put_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 128862306a36Sopenharmony_ci{ 128962306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 129062306a36Sopenharmony_ci int change; 129162306a36Sopenharmony_ci unsigned int val; 129262306a36Sopenharmony_ci int err = 0; 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci if (!snd_rme9652_use_is_exclusive(rme9652)) 129562306a36Sopenharmony_ci return -EBUSY; 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci val = ucontrol->value.integer.value[0] & 1; 129862306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 129962306a36Sopenharmony_ci change = (ucontrol->value.integer.value[0] != rme9652->passthru); 130062306a36Sopenharmony_ci if (change) 130162306a36Sopenharmony_ci err = rme9652_set_passthru(rme9652, val); 130262306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 130362306a36Sopenharmony_ci return err ? err : change; 130462306a36Sopenharmony_ci} 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci/* Read-only switches */ 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci#define RME9652_SPDIF_RATE(xname, xindex) \ 130962306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 131062306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ 131162306a36Sopenharmony_ci .info = snd_rme9652_info_spdif_rate, \ 131262306a36Sopenharmony_ci .get = snd_rme9652_get_spdif_rate } 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_cistatic int snd_rme9652_info_spdif_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 131562306a36Sopenharmony_ci{ 131662306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 131762306a36Sopenharmony_ci uinfo->count = 1; 131862306a36Sopenharmony_ci uinfo->value.integer.min = 0; 131962306a36Sopenharmony_ci uinfo->value.integer.max = 96000; 132062306a36Sopenharmony_ci return 0; 132162306a36Sopenharmony_ci} 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_cistatic int snd_rme9652_get_spdif_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 132462306a36Sopenharmony_ci{ 132562306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 132862306a36Sopenharmony_ci ucontrol->value.integer.value[0] = rme9652_spdif_sample_rate(rme9652); 132962306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 133062306a36Sopenharmony_ci return 0; 133162306a36Sopenharmony_ci} 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci#define RME9652_ADAT_SYNC(xname, xindex, xidx) \ 133462306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 133562306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ 133662306a36Sopenharmony_ci .info = snd_rme9652_info_adat_sync, \ 133762306a36Sopenharmony_ci .get = snd_rme9652_get_adat_sync, .private_value = xidx } 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_cistatic int snd_rme9652_info_adat_sync(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 134062306a36Sopenharmony_ci{ 134162306a36Sopenharmony_ci static const char * const texts[4] = { 134262306a36Sopenharmony_ci "No Lock", "Lock", "No Lock Sync", "Lock Sync" 134362306a36Sopenharmony_ci }; 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 4, texts); 134662306a36Sopenharmony_ci} 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_cistatic int snd_rme9652_get_adat_sync(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 134962306a36Sopenharmony_ci{ 135062306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 135162306a36Sopenharmony_ci unsigned int mask1, mask2, val; 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci switch (kcontrol->private_value) { 135462306a36Sopenharmony_ci case 0: mask1 = RME9652_lock_0; mask2 = RME9652_sync_0; break; 135562306a36Sopenharmony_ci case 1: mask1 = RME9652_lock_1; mask2 = RME9652_sync_1; break; 135662306a36Sopenharmony_ci case 2: mask1 = RME9652_lock_2; mask2 = RME9652_sync_2; break; 135762306a36Sopenharmony_ci default: return -EINVAL; 135862306a36Sopenharmony_ci } 135962306a36Sopenharmony_ci val = rme9652_read(rme9652, RME9652_status_register); 136062306a36Sopenharmony_ci ucontrol->value.enumerated.item[0] = (val & mask1) ? 1 : 0; 136162306a36Sopenharmony_ci ucontrol->value.enumerated.item[0] |= (val & mask2) ? 2 : 0; 136262306a36Sopenharmony_ci return 0; 136362306a36Sopenharmony_ci} 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci#define RME9652_TC_VALID(xname, xindex) \ 136662306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 136762306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ 136862306a36Sopenharmony_ci .info = snd_rme9652_info_tc_valid, \ 136962306a36Sopenharmony_ci .get = snd_rme9652_get_tc_valid } 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci#define snd_rme9652_info_tc_valid snd_ctl_boolean_mono_info 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_cistatic int snd_rme9652_get_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 137462306a36Sopenharmony_ci{ 137562306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol); 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci ucontrol->value.integer.value[0] = 137862306a36Sopenharmony_ci (rme9652_read(rme9652, RME9652_status_register) & RME9652_tc_valid) ? 1 : 0; 137962306a36Sopenharmony_ci return 0; 138062306a36Sopenharmony_ci} 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci#ifdef ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci/* FIXME: this routine needs a port to the new control API --jk */ 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_cistatic int snd_rme9652_get_tc_value(void *private_data, 138762306a36Sopenharmony_ci snd_kswitch_t *kswitch, 138862306a36Sopenharmony_ci snd_switch_t *uswitch) 138962306a36Sopenharmony_ci{ 139062306a36Sopenharmony_ci struct snd_rme9652 *s = (struct snd_rme9652 *) private_data; 139162306a36Sopenharmony_ci u32 value; 139262306a36Sopenharmony_ci int i; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci uswitch->type = SNDRV_SW_TYPE_DWORD; 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci if ((rme9652_read(s, RME9652_status_register) & 139762306a36Sopenharmony_ci RME9652_tc_valid) == 0) { 139862306a36Sopenharmony_ci uswitch->value.data32[0] = 0; 139962306a36Sopenharmony_ci return 0; 140062306a36Sopenharmony_ci } 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci /* timecode request */ 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci rme9652_write(s, RME9652_time_code, 0); 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci /* XXX bug alert: loop-based timing !!!! */ 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_ci for (i = 0; i < 50; i++) { 140962306a36Sopenharmony_ci if (!(rme9652_read(s, i * 4) & RME9652_tc_busy)) 141062306a36Sopenharmony_ci break; 141162306a36Sopenharmony_ci } 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci if (!(rme9652_read(s, i * 4) & RME9652_tc_busy)) { 141462306a36Sopenharmony_ci return -EIO; 141562306a36Sopenharmony_ci } 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci value = 0; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci for (i = 0; i < 32; i++) { 142062306a36Sopenharmony_ci value >>= 1; 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci if (rme9652_read(s, i * 4) & RME9652_tc_out) 142362306a36Sopenharmony_ci value |= 0x80000000; 142462306a36Sopenharmony_ci } 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci if (value > 2 * 60 * 48000) { 142762306a36Sopenharmony_ci value -= 2 * 60 * 48000; 142862306a36Sopenharmony_ci } else { 142962306a36Sopenharmony_ci value = 0; 143062306a36Sopenharmony_ci } 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci uswitch->value.data32[0] = value; 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci return 0; 143562306a36Sopenharmony_ci} 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci#endif /* ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE */ 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_cistatic const struct snd_kcontrol_new snd_rme9652_controls[] = { 144062306a36Sopenharmony_ci{ 144162306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_PCM, 144262306a36Sopenharmony_ci .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 144362306a36Sopenharmony_ci .info = snd_rme9652_control_spdif_info, 144462306a36Sopenharmony_ci .get = snd_rme9652_control_spdif_get, 144562306a36Sopenharmony_ci .put = snd_rme9652_control_spdif_put, 144662306a36Sopenharmony_ci}, 144762306a36Sopenharmony_ci{ 144862306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 144962306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_PCM, 145062306a36Sopenharmony_ci .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), 145162306a36Sopenharmony_ci .info = snd_rme9652_control_spdif_stream_info, 145262306a36Sopenharmony_ci .get = snd_rme9652_control_spdif_stream_get, 145362306a36Sopenharmony_ci .put = snd_rme9652_control_spdif_stream_put, 145462306a36Sopenharmony_ci}, 145562306a36Sopenharmony_ci{ 145662306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ, 145762306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_PCM, 145862306a36Sopenharmony_ci .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), 145962306a36Sopenharmony_ci .info = snd_rme9652_control_spdif_mask_info, 146062306a36Sopenharmony_ci .get = snd_rme9652_control_spdif_mask_get, 146162306a36Sopenharmony_ci .private_value = IEC958_AES0_NONAUDIO | 146262306a36Sopenharmony_ci IEC958_AES0_PROFESSIONAL | 146362306a36Sopenharmony_ci IEC958_AES0_CON_EMPHASIS, 146462306a36Sopenharmony_ci}, 146562306a36Sopenharmony_ci{ 146662306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ, 146762306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_PCM, 146862306a36Sopenharmony_ci .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), 146962306a36Sopenharmony_ci .info = snd_rme9652_control_spdif_mask_info, 147062306a36Sopenharmony_ci .get = snd_rme9652_control_spdif_mask_get, 147162306a36Sopenharmony_ci .private_value = IEC958_AES0_NONAUDIO | 147262306a36Sopenharmony_ci IEC958_AES0_PROFESSIONAL | 147362306a36Sopenharmony_ci IEC958_AES0_PRO_EMPHASIS, 147462306a36Sopenharmony_ci}, 147562306a36Sopenharmony_ciRME9652_SPDIF_IN("IEC958 Input Connector", 0), 147662306a36Sopenharmony_ciRME9652_SPDIF_OUT("IEC958 Output also on ADAT1", 0), 147762306a36Sopenharmony_ciRME9652_SYNC_MODE("Sync Mode", 0), 147862306a36Sopenharmony_ciRME9652_SYNC_PREF("Preferred Sync Source", 0), 147962306a36Sopenharmony_ci{ 148062306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 148162306a36Sopenharmony_ci .name = "Channels Thru", 148262306a36Sopenharmony_ci .index = 0, 148362306a36Sopenharmony_ci .info = snd_rme9652_info_thru, 148462306a36Sopenharmony_ci .get = snd_rme9652_get_thru, 148562306a36Sopenharmony_ci .put = snd_rme9652_put_thru, 148662306a36Sopenharmony_ci}, 148762306a36Sopenharmony_ciRME9652_SPDIF_RATE("IEC958 Sample Rate", 0), 148862306a36Sopenharmony_ciRME9652_ADAT_SYNC("ADAT1 Sync Check", 0, 0), 148962306a36Sopenharmony_ciRME9652_ADAT_SYNC("ADAT2 Sync Check", 0, 1), 149062306a36Sopenharmony_ciRME9652_TC_VALID("Timecode Valid", 0), 149162306a36Sopenharmony_ciRME9652_PASSTHRU("Passthru", 0) 149262306a36Sopenharmony_ci}; 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_cistatic const struct snd_kcontrol_new snd_rme9652_adat3_check = 149562306a36Sopenharmony_ciRME9652_ADAT_SYNC("ADAT3 Sync Check", 0, 2); 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_cistatic const struct snd_kcontrol_new snd_rme9652_adat1_input = 149862306a36Sopenharmony_ciRME9652_ADAT1_IN("ADAT1 Input Source", 0); 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_cistatic int snd_rme9652_create_controls(struct snd_card *card, struct snd_rme9652 *rme9652) 150162306a36Sopenharmony_ci{ 150262306a36Sopenharmony_ci unsigned int idx; 150362306a36Sopenharmony_ci int err; 150462306a36Sopenharmony_ci struct snd_kcontrol *kctl; 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_ci for (idx = 0; idx < ARRAY_SIZE(snd_rme9652_controls); idx++) { 150762306a36Sopenharmony_ci kctl = snd_ctl_new1(&snd_rme9652_controls[idx], rme9652); 150862306a36Sopenharmony_ci err = snd_ctl_add(card, kctl); 150962306a36Sopenharmony_ci if (err < 0) 151062306a36Sopenharmony_ci return err; 151162306a36Sopenharmony_ci if (idx == 1) /* IEC958 (S/PDIF) Stream */ 151262306a36Sopenharmony_ci rme9652->spdif_ctl = kctl; 151362306a36Sopenharmony_ci } 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci if (rme9652->ss_channels == RME9652_NCHANNELS) { 151662306a36Sopenharmony_ci kctl = snd_ctl_new1(&snd_rme9652_adat3_check, rme9652); 151762306a36Sopenharmony_ci err = snd_ctl_add(card, kctl); 151862306a36Sopenharmony_ci if (err < 0) 151962306a36Sopenharmony_ci return err; 152062306a36Sopenharmony_ci } 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci if (rme9652->hw_rev >= 15) { 152362306a36Sopenharmony_ci kctl = snd_ctl_new1(&snd_rme9652_adat1_input, rme9652); 152462306a36Sopenharmony_ci err = snd_ctl_add(card, kctl); 152562306a36Sopenharmony_ci if (err < 0) 152662306a36Sopenharmony_ci return err; 152762306a36Sopenharmony_ci } 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci return 0; 153062306a36Sopenharmony_ci} 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci/*------------------------------------------------------------ 153362306a36Sopenharmony_ci /proc interface 153462306a36Sopenharmony_ci ------------------------------------------------------------*/ 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_cistatic void 153762306a36Sopenharmony_cisnd_rme9652_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 153862306a36Sopenharmony_ci{ 153962306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) entry->private_data; 154062306a36Sopenharmony_ci u32 thru_bits = rme9652->thru_bits; 154162306a36Sopenharmony_ci int show_auto_sync_source = 0; 154262306a36Sopenharmony_ci int i; 154362306a36Sopenharmony_ci unsigned int status; 154462306a36Sopenharmony_ci int x; 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci status = rme9652_read(rme9652, RME9652_status_register); 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci snd_iprintf(buffer, "%s (Card #%d)\n", rme9652->card_name, rme9652->card->number + 1); 154962306a36Sopenharmony_ci snd_iprintf(buffer, "Buffers: capture %p playback %p\n", 155062306a36Sopenharmony_ci rme9652->capture_buffer, rme9652->playback_buffer); 155162306a36Sopenharmony_ci snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", 155262306a36Sopenharmony_ci rme9652->irq, rme9652->port, (unsigned long)rme9652->iobase); 155362306a36Sopenharmony_ci snd_iprintf(buffer, "Control register: %x\n", rme9652->control_register); 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci snd_iprintf(buffer, "\n"); 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci x = 1 << (6 + rme9652_decode_latency(rme9652->control_register & 155862306a36Sopenharmony_ci RME9652_latency)); 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci snd_iprintf(buffer, "Latency: %d samples (2 periods of %lu bytes)\n", 156162306a36Sopenharmony_ci x, (unsigned long) rme9652->period_bytes); 156262306a36Sopenharmony_ci snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", 156362306a36Sopenharmony_ci rme9652_hw_pointer(rme9652)); 156462306a36Sopenharmony_ci snd_iprintf(buffer, "Passthru: %s\n", 156562306a36Sopenharmony_ci rme9652->passthru ? "yes" : "no"); 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci if ((rme9652->control_register & (RME9652_Master | RME9652_wsel)) == 0) { 156862306a36Sopenharmony_ci snd_iprintf(buffer, "Clock mode: autosync\n"); 156962306a36Sopenharmony_ci show_auto_sync_source = 1; 157062306a36Sopenharmony_ci } else if (rme9652->control_register & RME9652_wsel) { 157162306a36Sopenharmony_ci if (status & RME9652_wsel_rd) { 157262306a36Sopenharmony_ci snd_iprintf(buffer, "Clock mode: word clock\n"); 157362306a36Sopenharmony_ci } else { 157462306a36Sopenharmony_ci snd_iprintf(buffer, "Clock mode: word clock (no signal)\n"); 157562306a36Sopenharmony_ci } 157662306a36Sopenharmony_ci } else { 157762306a36Sopenharmony_ci snd_iprintf(buffer, "Clock mode: master\n"); 157862306a36Sopenharmony_ci } 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci if (show_auto_sync_source) { 158162306a36Sopenharmony_ci switch (rme9652->control_register & RME9652_SyncPref_Mask) { 158262306a36Sopenharmony_ci case RME9652_SyncPref_ADAT1: 158362306a36Sopenharmony_ci snd_iprintf(buffer, "Pref. sync source: ADAT1\n"); 158462306a36Sopenharmony_ci break; 158562306a36Sopenharmony_ci case RME9652_SyncPref_ADAT2: 158662306a36Sopenharmony_ci snd_iprintf(buffer, "Pref. sync source: ADAT2\n"); 158762306a36Sopenharmony_ci break; 158862306a36Sopenharmony_ci case RME9652_SyncPref_ADAT3: 158962306a36Sopenharmony_ci snd_iprintf(buffer, "Pref. sync source: ADAT3\n"); 159062306a36Sopenharmony_ci break; 159162306a36Sopenharmony_ci case RME9652_SyncPref_SPDIF: 159262306a36Sopenharmony_ci snd_iprintf(buffer, "Pref. sync source: IEC958\n"); 159362306a36Sopenharmony_ci break; 159462306a36Sopenharmony_ci default: 159562306a36Sopenharmony_ci snd_iprintf(buffer, "Pref. sync source: ???\n"); 159662306a36Sopenharmony_ci } 159762306a36Sopenharmony_ci } 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci if (rme9652->hw_rev >= 15) 160062306a36Sopenharmony_ci snd_iprintf(buffer, "\nADAT1 Input source: %s\n", 160162306a36Sopenharmony_ci (rme9652->control_register & RME9652_ADAT1_INTERNAL) ? 160262306a36Sopenharmony_ci "Internal" : "ADAT1 optical"); 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci snd_iprintf(buffer, "\n"); 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_ci switch (rme9652_decode_spdif_in(rme9652->control_register & 160762306a36Sopenharmony_ci RME9652_inp)) { 160862306a36Sopenharmony_ci case RME9652_SPDIFIN_OPTICAL: 160962306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 input: ADAT1\n"); 161062306a36Sopenharmony_ci break; 161162306a36Sopenharmony_ci case RME9652_SPDIFIN_COAXIAL: 161262306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 input: Coaxial\n"); 161362306a36Sopenharmony_ci break; 161462306a36Sopenharmony_ci case RME9652_SPDIFIN_INTERN: 161562306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 input: Internal\n"); 161662306a36Sopenharmony_ci break; 161762306a36Sopenharmony_ci default: 161862306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 input: ???\n"); 161962306a36Sopenharmony_ci break; 162062306a36Sopenharmony_ci } 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci if (rme9652->control_register & RME9652_opt_out) { 162362306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 output: Coaxial & ADAT1\n"); 162462306a36Sopenharmony_ci } else { 162562306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 output: Coaxial only\n"); 162662306a36Sopenharmony_ci } 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci if (rme9652->control_register & RME9652_PRO) { 162962306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 quality: Professional\n"); 163062306a36Sopenharmony_ci } else { 163162306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 quality: Consumer\n"); 163262306a36Sopenharmony_ci } 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_ci if (rme9652->control_register & RME9652_EMP) { 163562306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 emphasis: on\n"); 163662306a36Sopenharmony_ci } else { 163762306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 emphasis: off\n"); 163862306a36Sopenharmony_ci } 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci if (rme9652->control_register & RME9652_Dolby) { 164162306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 Dolby: on\n"); 164262306a36Sopenharmony_ci } else { 164362306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 Dolby: off\n"); 164462306a36Sopenharmony_ci } 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci i = rme9652_spdif_sample_rate(rme9652); 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci if (i < 0) { 164962306a36Sopenharmony_ci snd_iprintf(buffer, 165062306a36Sopenharmony_ci "IEC958 sample rate: error flag set\n"); 165162306a36Sopenharmony_ci } else if (i == 0) { 165262306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 sample rate: undetermined\n"); 165362306a36Sopenharmony_ci } else { 165462306a36Sopenharmony_ci snd_iprintf(buffer, "IEC958 sample rate: %d\n", i); 165562306a36Sopenharmony_ci } 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci snd_iprintf(buffer, "\n"); 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci snd_iprintf(buffer, "ADAT Sample rate: %dHz\n", 166062306a36Sopenharmony_ci rme9652_adat_sample_rate(rme9652)); 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci /* Sync Check */ 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci x = status & RME9652_sync_0; 166562306a36Sopenharmony_ci if (status & RME9652_lock_0) { 166662306a36Sopenharmony_ci snd_iprintf(buffer, "ADAT1: %s\n", x ? "Sync" : "Lock"); 166762306a36Sopenharmony_ci } else { 166862306a36Sopenharmony_ci snd_iprintf(buffer, "ADAT1: No Lock\n"); 166962306a36Sopenharmony_ci } 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci x = status & RME9652_sync_1; 167262306a36Sopenharmony_ci if (status & RME9652_lock_1) { 167362306a36Sopenharmony_ci snd_iprintf(buffer, "ADAT2: %s\n", x ? "Sync" : "Lock"); 167462306a36Sopenharmony_ci } else { 167562306a36Sopenharmony_ci snd_iprintf(buffer, "ADAT2: No Lock\n"); 167662306a36Sopenharmony_ci } 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_ci x = status & RME9652_sync_2; 167962306a36Sopenharmony_ci if (status & RME9652_lock_2) { 168062306a36Sopenharmony_ci snd_iprintf(buffer, "ADAT3: %s\n", x ? "Sync" : "Lock"); 168162306a36Sopenharmony_ci } else { 168262306a36Sopenharmony_ci snd_iprintf(buffer, "ADAT3: No Lock\n"); 168362306a36Sopenharmony_ci } 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci snd_iprintf(buffer, "\n"); 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci snd_iprintf(buffer, "Timecode signal: %s\n", 168862306a36Sopenharmony_ci (status & RME9652_tc_valid) ? "yes" : "no"); 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci /* thru modes */ 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci snd_iprintf(buffer, "Punch Status:\n\n"); 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci for (i = 0; i < rme9652->ss_channels; i++) { 169562306a36Sopenharmony_ci if (thru_bits & (1 << i)) { 169662306a36Sopenharmony_ci snd_iprintf(buffer, "%2d: on ", i + 1); 169762306a36Sopenharmony_ci } else { 169862306a36Sopenharmony_ci snd_iprintf(buffer, "%2d: off ", i + 1); 169962306a36Sopenharmony_ci } 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_ci if (((i + 1) % 8) == 0) { 170262306a36Sopenharmony_ci snd_iprintf(buffer, "\n"); 170362306a36Sopenharmony_ci } 170462306a36Sopenharmony_ci } 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci snd_iprintf(buffer, "\n"); 170762306a36Sopenharmony_ci} 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_cistatic void snd_rme9652_proc_init(struct snd_rme9652 *rme9652) 171062306a36Sopenharmony_ci{ 171162306a36Sopenharmony_ci snd_card_ro_proc_new(rme9652->card, "rme9652", rme9652, 171262306a36Sopenharmony_ci snd_rme9652_proc_read); 171362306a36Sopenharmony_ci} 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_cistatic void snd_rme9652_card_free(struct snd_card *card) 171662306a36Sopenharmony_ci{ 171762306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) card->private_data; 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci if (rme9652->irq >= 0) 172062306a36Sopenharmony_ci rme9652_stop(rme9652); 172162306a36Sopenharmony_ci} 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_cistatic int snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652) 172462306a36Sopenharmony_ci{ 172562306a36Sopenharmony_ci struct snd_dma_buffer *capture_dma, *playback_dma; 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci capture_dma = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES); 172862306a36Sopenharmony_ci playback_dma = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES); 172962306a36Sopenharmony_ci if (!capture_dma || !playback_dma) { 173062306a36Sopenharmony_ci dev_err(rme9652->card->dev, 173162306a36Sopenharmony_ci "%s: no buffers available\n", rme9652->card_name); 173262306a36Sopenharmony_ci return -ENOMEM; 173362306a36Sopenharmony_ci } 173462306a36Sopenharmony_ci 173562306a36Sopenharmony_ci /* copy to the own data for alignment */ 173662306a36Sopenharmony_ci rme9652->capture_dma_buf = *capture_dma; 173762306a36Sopenharmony_ci rme9652->playback_dma_buf = *playback_dma; 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci /* Align to bus-space 64K boundary */ 174062306a36Sopenharmony_ci rme9652->capture_dma_buf.addr = ALIGN(capture_dma->addr, 0x10000ul); 174162306a36Sopenharmony_ci rme9652->playback_dma_buf.addr = ALIGN(playback_dma->addr, 0x10000ul); 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci /* Tell the card where it is */ 174462306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_rec_buffer, rme9652->capture_dma_buf.addr); 174562306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_play_buffer, rme9652->playback_dma_buf.addr); 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci rme9652->capture_dma_buf.area += rme9652->capture_dma_buf.addr - capture_dma->addr; 174862306a36Sopenharmony_ci rme9652->playback_dma_buf.area += rme9652->playback_dma_buf.addr - playback_dma->addr; 174962306a36Sopenharmony_ci rme9652->capture_buffer = rme9652->capture_dma_buf.area; 175062306a36Sopenharmony_ci rme9652->playback_buffer = rme9652->playback_dma_buf.area; 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ci return 0; 175362306a36Sopenharmony_ci} 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_cistatic void snd_rme9652_set_defaults(struct snd_rme9652 *rme9652) 175662306a36Sopenharmony_ci{ 175762306a36Sopenharmony_ci unsigned int k; 175862306a36Sopenharmony_ci 175962306a36Sopenharmony_ci /* ASSUMPTION: rme9652->lock is either held, or 176062306a36Sopenharmony_ci there is no need to hold it (e.g. during module 176162306a36Sopenharmony_ci initialization). 176262306a36Sopenharmony_ci */ 176362306a36Sopenharmony_ci 176462306a36Sopenharmony_ci /* set defaults: 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci SPDIF Input via Coax 176762306a36Sopenharmony_ci autosync clock mode 176862306a36Sopenharmony_ci maximum latency (7 = 8192 samples, 64Kbyte buffer, 176962306a36Sopenharmony_ci which implies 2 4096 sample, 32Kbyte periods). 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci if rev 1.5, initialize the S/PDIF receiver. 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci */ 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci rme9652->control_register = 177662306a36Sopenharmony_ci RME9652_inp_0 | rme9652_encode_latency(7); 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, rme9652->control_register); 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci rme9652_reset_hw_pointer(rme9652); 178162306a36Sopenharmony_ci rme9652_compute_period_size(rme9652); 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci /* default: thru off for all channels */ 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_ci for (k = 0; k < RME9652_NCHANNELS; ++k) 178662306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_thru_base + k * 4, 0); 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci rme9652->thru_bits = 0; 178962306a36Sopenharmony_ci rme9652->passthru = 0; 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci /* set a default rate so that the channel map is set up */ 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci rme9652_set_rate(rme9652, 48000); 179462306a36Sopenharmony_ci} 179562306a36Sopenharmony_ci 179662306a36Sopenharmony_cistatic irqreturn_t snd_rme9652_interrupt(int irq, void *dev_id) 179762306a36Sopenharmony_ci{ 179862306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) dev_id; 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci if (!(rme9652_read(rme9652, RME9652_status_register) & RME9652_IRQ)) { 180162306a36Sopenharmony_ci return IRQ_NONE; 180262306a36Sopenharmony_ci } 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_irq_clear, 0); 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci if (rme9652->capture_substream) { 180762306a36Sopenharmony_ci snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); 180862306a36Sopenharmony_ci } 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci if (rme9652->playback_substream) { 181162306a36Sopenharmony_ci snd_pcm_period_elapsed(rme9652->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream); 181262306a36Sopenharmony_ci } 181362306a36Sopenharmony_ci return IRQ_HANDLED; 181462306a36Sopenharmony_ci} 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_cistatic snd_pcm_uframes_t snd_rme9652_hw_pointer(struct snd_pcm_substream *substream) 181762306a36Sopenharmony_ci{ 181862306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 181962306a36Sopenharmony_ci return rme9652_hw_pointer(rme9652); 182062306a36Sopenharmony_ci} 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_cistatic signed char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652, 182362306a36Sopenharmony_ci int stream, 182462306a36Sopenharmony_ci int channel) 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci{ 182762306a36Sopenharmony_ci int mapped_channel; 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci if (snd_BUG_ON(channel < 0 || channel >= RME9652_NCHANNELS)) 183062306a36Sopenharmony_ci return NULL; 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci mapped_channel = rme9652->channel_map[channel]; 183362306a36Sopenharmony_ci if (mapped_channel < 0) 183462306a36Sopenharmony_ci return NULL; 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci if (stream == SNDRV_PCM_STREAM_CAPTURE) { 183762306a36Sopenharmony_ci return rme9652->capture_buffer + 183862306a36Sopenharmony_ci (mapped_channel * RME9652_CHANNEL_BUFFER_BYTES); 183962306a36Sopenharmony_ci } else { 184062306a36Sopenharmony_ci return rme9652->playback_buffer + 184162306a36Sopenharmony_ci (mapped_channel * RME9652_CHANNEL_BUFFER_BYTES); 184262306a36Sopenharmony_ci } 184362306a36Sopenharmony_ci} 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_cistatic int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, 184662306a36Sopenharmony_ci int channel, unsigned long pos, 184762306a36Sopenharmony_ci struct iov_iter *src, unsigned long count) 184862306a36Sopenharmony_ci{ 184962306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 185062306a36Sopenharmony_ci signed char *channel_buf; 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES)) 185362306a36Sopenharmony_ci return -EINVAL; 185462306a36Sopenharmony_ci 185562306a36Sopenharmony_ci channel_buf = rme9652_channel_buffer_location (rme9652, 185662306a36Sopenharmony_ci substream->pstr->stream, 185762306a36Sopenharmony_ci channel); 185862306a36Sopenharmony_ci if (snd_BUG_ON(!channel_buf)) 185962306a36Sopenharmony_ci return -EIO; 186062306a36Sopenharmony_ci if (copy_from_iter(channel_buf + pos, count, src) != count) 186162306a36Sopenharmony_ci return -EFAULT; 186262306a36Sopenharmony_ci return 0; 186362306a36Sopenharmony_ci} 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_cistatic int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, 186662306a36Sopenharmony_ci int channel, unsigned long pos, 186762306a36Sopenharmony_ci struct iov_iter *dst, unsigned long count) 186862306a36Sopenharmony_ci{ 186962306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 187062306a36Sopenharmony_ci signed char *channel_buf; 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES)) 187362306a36Sopenharmony_ci return -EINVAL; 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci channel_buf = rme9652_channel_buffer_location (rme9652, 187662306a36Sopenharmony_ci substream->pstr->stream, 187762306a36Sopenharmony_ci channel); 187862306a36Sopenharmony_ci if (snd_BUG_ON(!channel_buf)) 187962306a36Sopenharmony_ci return -EIO; 188062306a36Sopenharmony_ci if (copy_to_iter(channel_buf + pos, count, dst) != count) 188162306a36Sopenharmony_ci return -EFAULT; 188262306a36Sopenharmony_ci return 0; 188362306a36Sopenharmony_ci} 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_cistatic int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, 188662306a36Sopenharmony_ci int channel, unsigned long pos, 188762306a36Sopenharmony_ci unsigned long count) 188862306a36Sopenharmony_ci{ 188962306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 189062306a36Sopenharmony_ci signed char *channel_buf; 189162306a36Sopenharmony_ci 189262306a36Sopenharmony_ci channel_buf = rme9652_channel_buffer_location (rme9652, 189362306a36Sopenharmony_ci substream->pstr->stream, 189462306a36Sopenharmony_ci channel); 189562306a36Sopenharmony_ci if (snd_BUG_ON(!channel_buf)) 189662306a36Sopenharmony_ci return -EIO; 189762306a36Sopenharmony_ci memset(channel_buf + pos, 0, count); 189862306a36Sopenharmony_ci return 0; 189962306a36Sopenharmony_ci} 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_cistatic int snd_rme9652_reset(struct snd_pcm_substream *substream) 190262306a36Sopenharmony_ci{ 190362306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 190462306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 190562306a36Sopenharmony_ci struct snd_pcm_substream *other; 190662306a36Sopenharmony_ci if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 190762306a36Sopenharmony_ci other = rme9652->capture_substream; 190862306a36Sopenharmony_ci else 190962306a36Sopenharmony_ci other = rme9652->playback_substream; 191062306a36Sopenharmony_ci if (rme9652->running) 191162306a36Sopenharmony_ci runtime->status->hw_ptr = rme9652_hw_pointer(rme9652); 191262306a36Sopenharmony_ci else 191362306a36Sopenharmony_ci runtime->status->hw_ptr = 0; 191462306a36Sopenharmony_ci if (other) { 191562306a36Sopenharmony_ci struct snd_pcm_substream *s; 191662306a36Sopenharmony_ci struct snd_pcm_runtime *oruntime = other->runtime; 191762306a36Sopenharmony_ci snd_pcm_group_for_each_entry(s, substream) { 191862306a36Sopenharmony_ci if (s == other) { 191962306a36Sopenharmony_ci oruntime->status->hw_ptr = runtime->status->hw_ptr; 192062306a36Sopenharmony_ci break; 192162306a36Sopenharmony_ci } 192262306a36Sopenharmony_ci } 192362306a36Sopenharmony_ci } 192462306a36Sopenharmony_ci return 0; 192562306a36Sopenharmony_ci} 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_cistatic int snd_rme9652_hw_params(struct snd_pcm_substream *substream, 192862306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 192962306a36Sopenharmony_ci{ 193062306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 193162306a36Sopenharmony_ci int err; 193262306a36Sopenharmony_ci pid_t this_pid; 193362306a36Sopenharmony_ci pid_t other_pid; 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 193662306a36Sopenharmony_ci 193762306a36Sopenharmony_ci if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { 193862306a36Sopenharmony_ci rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP); 193962306a36Sopenharmony_ci rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= rme9652->creg_spdif_stream); 194062306a36Sopenharmony_ci this_pid = rme9652->playback_pid; 194162306a36Sopenharmony_ci other_pid = rme9652->capture_pid; 194262306a36Sopenharmony_ci } else { 194362306a36Sopenharmony_ci this_pid = rme9652->capture_pid; 194462306a36Sopenharmony_ci other_pid = rme9652->playback_pid; 194562306a36Sopenharmony_ci } 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci if ((other_pid > 0) && (this_pid != other_pid)) { 194862306a36Sopenharmony_ci 194962306a36Sopenharmony_ci /* The other stream is open, and not by the same 195062306a36Sopenharmony_ci task as this one. Make sure that the parameters 195162306a36Sopenharmony_ci that matter are the same. 195262306a36Sopenharmony_ci */ 195362306a36Sopenharmony_ci 195462306a36Sopenharmony_ci if ((int)params_rate(params) != 195562306a36Sopenharmony_ci rme9652_adat_sample_rate(rme9652)) { 195662306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 195762306a36Sopenharmony_ci _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); 195862306a36Sopenharmony_ci return -EBUSY; 195962306a36Sopenharmony_ci } 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci if (params_period_size(params) != rme9652->period_bytes / 4) { 196262306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 196362306a36Sopenharmony_ci _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); 196462306a36Sopenharmony_ci return -EBUSY; 196562306a36Sopenharmony_ci } 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci /* We're fine. */ 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 197062306a36Sopenharmony_ci return 0; 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci } else { 197362306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 197462306a36Sopenharmony_ci } 197562306a36Sopenharmony_ci 197662306a36Sopenharmony_ci /* how to make sure that the rate matches an externally-set one ? 197762306a36Sopenharmony_ci */ 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_ci err = rme9652_set_rate(rme9652, params_rate(params)); 198062306a36Sopenharmony_ci if (err < 0) { 198162306a36Sopenharmony_ci _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); 198262306a36Sopenharmony_ci return err; 198362306a36Sopenharmony_ci } 198462306a36Sopenharmony_ci 198562306a36Sopenharmony_ci err = rme9652_set_interrupt_interval(rme9652, params_period_size(params)); 198662306a36Sopenharmony_ci if (err < 0) { 198762306a36Sopenharmony_ci _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); 198862306a36Sopenharmony_ci return err; 198962306a36Sopenharmony_ci } 199062306a36Sopenharmony_ci 199162306a36Sopenharmony_ci return 0; 199262306a36Sopenharmony_ci} 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_cistatic int snd_rme9652_channel_info(struct snd_pcm_substream *substream, 199562306a36Sopenharmony_ci struct snd_pcm_channel_info *info) 199662306a36Sopenharmony_ci{ 199762306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 199862306a36Sopenharmony_ci int chn; 199962306a36Sopenharmony_ci 200062306a36Sopenharmony_ci if (snd_BUG_ON(info->channel >= RME9652_NCHANNELS)) 200162306a36Sopenharmony_ci return -EINVAL; 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci chn = rme9652->channel_map[array_index_nospec(info->channel, 200462306a36Sopenharmony_ci RME9652_NCHANNELS)]; 200562306a36Sopenharmony_ci if (chn < 0) 200662306a36Sopenharmony_ci return -EINVAL; 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci info->offset = chn * RME9652_CHANNEL_BUFFER_BYTES; 200962306a36Sopenharmony_ci info->first = 0; 201062306a36Sopenharmony_ci info->step = 32; 201162306a36Sopenharmony_ci return 0; 201262306a36Sopenharmony_ci} 201362306a36Sopenharmony_ci 201462306a36Sopenharmony_cistatic int snd_rme9652_ioctl(struct snd_pcm_substream *substream, 201562306a36Sopenharmony_ci unsigned int cmd, void *arg) 201662306a36Sopenharmony_ci{ 201762306a36Sopenharmony_ci switch (cmd) { 201862306a36Sopenharmony_ci case SNDRV_PCM_IOCTL1_RESET: 201962306a36Sopenharmony_ci { 202062306a36Sopenharmony_ci return snd_rme9652_reset(substream); 202162306a36Sopenharmony_ci } 202262306a36Sopenharmony_ci case SNDRV_PCM_IOCTL1_CHANNEL_INFO: 202362306a36Sopenharmony_ci { 202462306a36Sopenharmony_ci struct snd_pcm_channel_info *info = arg; 202562306a36Sopenharmony_ci return snd_rme9652_channel_info(substream, info); 202662306a36Sopenharmony_ci } 202762306a36Sopenharmony_ci default: 202862306a36Sopenharmony_ci break; 202962306a36Sopenharmony_ci } 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_ci return snd_pcm_lib_ioctl(substream, cmd, arg); 203262306a36Sopenharmony_ci} 203362306a36Sopenharmony_ci 203462306a36Sopenharmony_cistatic void rme9652_silence_playback(struct snd_rme9652 *rme9652) 203562306a36Sopenharmony_ci{ 203662306a36Sopenharmony_ci memset(rme9652->playback_buffer, 0, RME9652_DMA_AREA_BYTES); 203762306a36Sopenharmony_ci} 203862306a36Sopenharmony_ci 203962306a36Sopenharmony_cistatic int snd_rme9652_trigger(struct snd_pcm_substream *substream, 204062306a36Sopenharmony_ci int cmd) 204162306a36Sopenharmony_ci{ 204262306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 204362306a36Sopenharmony_ci struct snd_pcm_substream *other; 204462306a36Sopenharmony_ci int running; 204562306a36Sopenharmony_ci spin_lock(&rme9652->lock); 204662306a36Sopenharmony_ci running = rme9652->running; 204762306a36Sopenharmony_ci switch (cmd) { 204862306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_START: 204962306a36Sopenharmony_ci running |= 1 << substream->stream; 205062306a36Sopenharmony_ci break; 205162306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_STOP: 205262306a36Sopenharmony_ci running &= ~(1 << substream->stream); 205362306a36Sopenharmony_ci break; 205462306a36Sopenharmony_ci default: 205562306a36Sopenharmony_ci snd_BUG(); 205662306a36Sopenharmony_ci spin_unlock(&rme9652->lock); 205762306a36Sopenharmony_ci return -EINVAL; 205862306a36Sopenharmony_ci } 205962306a36Sopenharmony_ci if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 206062306a36Sopenharmony_ci other = rme9652->capture_substream; 206162306a36Sopenharmony_ci else 206262306a36Sopenharmony_ci other = rme9652->playback_substream; 206362306a36Sopenharmony_ci 206462306a36Sopenharmony_ci if (other) { 206562306a36Sopenharmony_ci struct snd_pcm_substream *s; 206662306a36Sopenharmony_ci snd_pcm_group_for_each_entry(s, substream) { 206762306a36Sopenharmony_ci if (s == other) { 206862306a36Sopenharmony_ci snd_pcm_trigger_done(s, substream); 206962306a36Sopenharmony_ci if (cmd == SNDRV_PCM_TRIGGER_START) 207062306a36Sopenharmony_ci running |= 1 << s->stream; 207162306a36Sopenharmony_ci else 207262306a36Sopenharmony_ci running &= ~(1 << s->stream); 207362306a36Sopenharmony_ci goto _ok; 207462306a36Sopenharmony_ci } 207562306a36Sopenharmony_ci } 207662306a36Sopenharmony_ci if (cmd == SNDRV_PCM_TRIGGER_START) { 207762306a36Sopenharmony_ci if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) && 207862306a36Sopenharmony_ci substream->stream == SNDRV_PCM_STREAM_CAPTURE) 207962306a36Sopenharmony_ci rme9652_silence_playback(rme9652); 208062306a36Sopenharmony_ci } else { 208162306a36Sopenharmony_ci if (running && 208262306a36Sopenharmony_ci substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 208362306a36Sopenharmony_ci rme9652_silence_playback(rme9652); 208462306a36Sopenharmony_ci } 208562306a36Sopenharmony_ci } else { 208662306a36Sopenharmony_ci if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 208762306a36Sopenharmony_ci rme9652_silence_playback(rme9652); 208862306a36Sopenharmony_ci } 208962306a36Sopenharmony_ci _ok: 209062306a36Sopenharmony_ci snd_pcm_trigger_done(substream, substream); 209162306a36Sopenharmony_ci if (!rme9652->running && running) 209262306a36Sopenharmony_ci rme9652_start(rme9652); 209362306a36Sopenharmony_ci else if (rme9652->running && !running) 209462306a36Sopenharmony_ci rme9652_stop(rme9652); 209562306a36Sopenharmony_ci rme9652->running = running; 209662306a36Sopenharmony_ci spin_unlock(&rme9652->lock); 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_ci return 0; 209962306a36Sopenharmony_ci} 210062306a36Sopenharmony_ci 210162306a36Sopenharmony_cistatic int snd_rme9652_prepare(struct snd_pcm_substream *substream) 210262306a36Sopenharmony_ci{ 210362306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 210462306a36Sopenharmony_ci unsigned long flags; 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci spin_lock_irqsave(&rme9652->lock, flags); 210762306a36Sopenharmony_ci if (!rme9652->running) 210862306a36Sopenharmony_ci rme9652_reset_hw_pointer(rme9652); 210962306a36Sopenharmony_ci spin_unlock_irqrestore(&rme9652->lock, flags); 211062306a36Sopenharmony_ci return 0; 211162306a36Sopenharmony_ci} 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_cistatic const struct snd_pcm_hardware snd_rme9652_playback_subinfo = 211462306a36Sopenharmony_ci{ 211562306a36Sopenharmony_ci .info = (SNDRV_PCM_INFO_MMAP | 211662306a36Sopenharmony_ci SNDRV_PCM_INFO_MMAP_VALID | 211762306a36Sopenharmony_ci SNDRV_PCM_INFO_NONINTERLEAVED | 211862306a36Sopenharmony_ci SNDRV_PCM_INFO_SYNC_START | 211962306a36Sopenharmony_ci SNDRV_PCM_INFO_DOUBLE), 212062306a36Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE, 212162306a36Sopenharmony_ci .rates = (SNDRV_PCM_RATE_44100 | 212262306a36Sopenharmony_ci SNDRV_PCM_RATE_48000 | 212362306a36Sopenharmony_ci SNDRV_PCM_RATE_88200 | 212462306a36Sopenharmony_ci SNDRV_PCM_RATE_96000), 212562306a36Sopenharmony_ci .rate_min = 44100, 212662306a36Sopenharmony_ci .rate_max = 96000, 212762306a36Sopenharmony_ci .channels_min = 10, 212862306a36Sopenharmony_ci .channels_max = 26, 212962306a36Sopenharmony_ci .buffer_bytes_max = RME9652_CHANNEL_BUFFER_BYTES * 26, 213062306a36Sopenharmony_ci .period_bytes_min = (64 * 4) * 10, 213162306a36Sopenharmony_ci .period_bytes_max = (8192 * 4) * 26, 213262306a36Sopenharmony_ci .periods_min = 2, 213362306a36Sopenharmony_ci .periods_max = 2, 213462306a36Sopenharmony_ci .fifo_size = 0, 213562306a36Sopenharmony_ci}; 213662306a36Sopenharmony_ci 213762306a36Sopenharmony_cistatic const struct snd_pcm_hardware snd_rme9652_capture_subinfo = 213862306a36Sopenharmony_ci{ 213962306a36Sopenharmony_ci .info = (SNDRV_PCM_INFO_MMAP | 214062306a36Sopenharmony_ci SNDRV_PCM_INFO_MMAP_VALID | 214162306a36Sopenharmony_ci SNDRV_PCM_INFO_NONINTERLEAVED | 214262306a36Sopenharmony_ci SNDRV_PCM_INFO_SYNC_START), 214362306a36Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S32_LE, 214462306a36Sopenharmony_ci .rates = (SNDRV_PCM_RATE_44100 | 214562306a36Sopenharmony_ci SNDRV_PCM_RATE_48000 | 214662306a36Sopenharmony_ci SNDRV_PCM_RATE_88200 | 214762306a36Sopenharmony_ci SNDRV_PCM_RATE_96000), 214862306a36Sopenharmony_ci .rate_min = 44100, 214962306a36Sopenharmony_ci .rate_max = 96000, 215062306a36Sopenharmony_ci .channels_min = 10, 215162306a36Sopenharmony_ci .channels_max = 26, 215262306a36Sopenharmony_ci .buffer_bytes_max = RME9652_CHANNEL_BUFFER_BYTES *26, 215362306a36Sopenharmony_ci .period_bytes_min = (64 * 4) * 10, 215462306a36Sopenharmony_ci .period_bytes_max = (8192 * 4) * 26, 215562306a36Sopenharmony_ci .periods_min = 2, 215662306a36Sopenharmony_ci .periods_max = 2, 215762306a36Sopenharmony_ci .fifo_size = 0, 215862306a36Sopenharmony_ci}; 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_cistatic const unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; 216162306a36Sopenharmony_ci 216262306a36Sopenharmony_cistatic const struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { 216362306a36Sopenharmony_ci .count = ARRAY_SIZE(period_sizes), 216462306a36Sopenharmony_ci .list = period_sizes, 216562306a36Sopenharmony_ci .mask = 0 216662306a36Sopenharmony_ci}; 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_cistatic int snd_rme9652_hw_rule_channels(struct snd_pcm_hw_params *params, 216962306a36Sopenharmony_ci struct snd_pcm_hw_rule *rule) 217062306a36Sopenharmony_ci{ 217162306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = rule->private; 217262306a36Sopenharmony_ci struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 217362306a36Sopenharmony_ci unsigned int list[2] = { rme9652->ds_channels, rme9652->ss_channels }; 217462306a36Sopenharmony_ci return snd_interval_list(c, 2, list, 0); 217562306a36Sopenharmony_ci} 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_cistatic int snd_rme9652_hw_rule_channels_rate(struct snd_pcm_hw_params *params, 217862306a36Sopenharmony_ci struct snd_pcm_hw_rule *rule) 217962306a36Sopenharmony_ci{ 218062306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = rule->private; 218162306a36Sopenharmony_ci struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 218262306a36Sopenharmony_ci struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 218362306a36Sopenharmony_ci if (r->min > 48000) { 218462306a36Sopenharmony_ci struct snd_interval t = { 218562306a36Sopenharmony_ci .min = rme9652->ds_channels, 218662306a36Sopenharmony_ci .max = rme9652->ds_channels, 218762306a36Sopenharmony_ci .integer = 1, 218862306a36Sopenharmony_ci }; 218962306a36Sopenharmony_ci return snd_interval_refine(c, &t); 219062306a36Sopenharmony_ci } else if (r->max < 88200) { 219162306a36Sopenharmony_ci struct snd_interval t = { 219262306a36Sopenharmony_ci .min = rme9652->ss_channels, 219362306a36Sopenharmony_ci .max = rme9652->ss_channels, 219462306a36Sopenharmony_ci .integer = 1, 219562306a36Sopenharmony_ci }; 219662306a36Sopenharmony_ci return snd_interval_refine(c, &t); 219762306a36Sopenharmony_ci } 219862306a36Sopenharmony_ci return 0; 219962306a36Sopenharmony_ci} 220062306a36Sopenharmony_ci 220162306a36Sopenharmony_cistatic int snd_rme9652_hw_rule_rate_channels(struct snd_pcm_hw_params *params, 220262306a36Sopenharmony_ci struct snd_pcm_hw_rule *rule) 220362306a36Sopenharmony_ci{ 220462306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = rule->private; 220562306a36Sopenharmony_ci struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); 220662306a36Sopenharmony_ci struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 220762306a36Sopenharmony_ci if (c->min >= rme9652->ss_channels) { 220862306a36Sopenharmony_ci struct snd_interval t = { 220962306a36Sopenharmony_ci .min = 44100, 221062306a36Sopenharmony_ci .max = 48000, 221162306a36Sopenharmony_ci .integer = 1, 221262306a36Sopenharmony_ci }; 221362306a36Sopenharmony_ci return snd_interval_refine(r, &t); 221462306a36Sopenharmony_ci } else if (c->max <= rme9652->ds_channels) { 221562306a36Sopenharmony_ci struct snd_interval t = { 221662306a36Sopenharmony_ci .min = 88200, 221762306a36Sopenharmony_ci .max = 96000, 221862306a36Sopenharmony_ci .integer = 1, 221962306a36Sopenharmony_ci }; 222062306a36Sopenharmony_ci return snd_interval_refine(r, &t); 222162306a36Sopenharmony_ci } 222262306a36Sopenharmony_ci return 0; 222362306a36Sopenharmony_ci} 222462306a36Sopenharmony_ci 222562306a36Sopenharmony_cistatic int snd_rme9652_playback_open(struct snd_pcm_substream *substream) 222662306a36Sopenharmony_ci{ 222762306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 222862306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_ci snd_pcm_set_sync(substream); 223362306a36Sopenharmony_ci 223462306a36Sopenharmony_ci runtime->hw = snd_rme9652_playback_subinfo; 223562306a36Sopenharmony_ci snd_pcm_set_runtime_buffer(substream, &rme9652->playback_dma_buf); 223662306a36Sopenharmony_ci 223762306a36Sopenharmony_ci if (rme9652->capture_substream == NULL) { 223862306a36Sopenharmony_ci rme9652_stop(rme9652); 223962306a36Sopenharmony_ci rme9652_set_thru(rme9652, -1, 0); 224062306a36Sopenharmony_ci } 224162306a36Sopenharmony_ci 224262306a36Sopenharmony_ci rme9652->playback_pid = current->pid; 224362306a36Sopenharmony_ci rme9652->playback_substream = substream; 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_ci snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); 224862306a36Sopenharmony_ci snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes); 224962306a36Sopenharmony_ci snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 225062306a36Sopenharmony_ci snd_rme9652_hw_rule_channels, rme9652, 225162306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_CHANNELS, -1); 225262306a36Sopenharmony_ci snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 225362306a36Sopenharmony_ci snd_rme9652_hw_rule_channels_rate, rme9652, 225462306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_RATE, -1); 225562306a36Sopenharmony_ci snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 225662306a36Sopenharmony_ci snd_rme9652_hw_rule_rate_channels, rme9652, 225762306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_CHANNELS, -1); 225862306a36Sopenharmony_ci 225962306a36Sopenharmony_ci rme9652->creg_spdif_stream = rme9652->creg_spdif; 226062306a36Sopenharmony_ci rme9652->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; 226162306a36Sopenharmony_ci snd_ctl_notify(rme9652->card, SNDRV_CTL_EVENT_MASK_VALUE | 226262306a36Sopenharmony_ci SNDRV_CTL_EVENT_MASK_INFO, &rme9652->spdif_ctl->id); 226362306a36Sopenharmony_ci return 0; 226462306a36Sopenharmony_ci} 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_cistatic int snd_rme9652_playback_release(struct snd_pcm_substream *substream) 226762306a36Sopenharmony_ci{ 226862306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 227162306a36Sopenharmony_ci 227262306a36Sopenharmony_ci rme9652->playback_pid = -1; 227362306a36Sopenharmony_ci rme9652->playback_substream = NULL; 227462306a36Sopenharmony_ci 227562306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_ci rme9652->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; 227862306a36Sopenharmony_ci snd_ctl_notify(rme9652->card, SNDRV_CTL_EVENT_MASK_VALUE | 227962306a36Sopenharmony_ci SNDRV_CTL_EVENT_MASK_INFO, &rme9652->spdif_ctl->id); 228062306a36Sopenharmony_ci return 0; 228162306a36Sopenharmony_ci} 228262306a36Sopenharmony_ci 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_cistatic int snd_rme9652_capture_open(struct snd_pcm_substream *substream) 228562306a36Sopenharmony_ci{ 228662306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 228762306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 228862306a36Sopenharmony_ci 228962306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci snd_pcm_set_sync(substream); 229262306a36Sopenharmony_ci 229362306a36Sopenharmony_ci runtime->hw = snd_rme9652_capture_subinfo; 229462306a36Sopenharmony_ci snd_pcm_set_runtime_buffer(substream, &rme9652->capture_dma_buf); 229562306a36Sopenharmony_ci 229662306a36Sopenharmony_ci if (rme9652->playback_substream == NULL) { 229762306a36Sopenharmony_ci rme9652_stop(rme9652); 229862306a36Sopenharmony_ci rme9652_set_thru(rme9652, -1, 0); 229962306a36Sopenharmony_ci } 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_ci rme9652->capture_pid = current->pid; 230262306a36Sopenharmony_ci rme9652->capture_substream = substream; 230362306a36Sopenharmony_ci 230462306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 230562306a36Sopenharmony_ci 230662306a36Sopenharmony_ci snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); 230762306a36Sopenharmony_ci snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes); 230862306a36Sopenharmony_ci snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 230962306a36Sopenharmony_ci snd_rme9652_hw_rule_channels, rme9652, 231062306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_CHANNELS, -1); 231162306a36Sopenharmony_ci snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 231262306a36Sopenharmony_ci snd_rme9652_hw_rule_channels_rate, rme9652, 231362306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_RATE, -1); 231462306a36Sopenharmony_ci snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 231562306a36Sopenharmony_ci snd_rme9652_hw_rule_rate_channels, rme9652, 231662306a36Sopenharmony_ci SNDRV_PCM_HW_PARAM_CHANNELS, -1); 231762306a36Sopenharmony_ci return 0; 231862306a36Sopenharmony_ci} 231962306a36Sopenharmony_ci 232062306a36Sopenharmony_cistatic int snd_rme9652_capture_release(struct snd_pcm_substream *substream) 232162306a36Sopenharmony_ci{ 232262306a36Sopenharmony_ci struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_ci spin_lock_irq(&rme9652->lock); 232562306a36Sopenharmony_ci 232662306a36Sopenharmony_ci rme9652->capture_pid = -1; 232762306a36Sopenharmony_ci rme9652->capture_substream = NULL; 232862306a36Sopenharmony_ci 232962306a36Sopenharmony_ci spin_unlock_irq(&rme9652->lock); 233062306a36Sopenharmony_ci return 0; 233162306a36Sopenharmony_ci} 233262306a36Sopenharmony_ci 233362306a36Sopenharmony_cistatic const struct snd_pcm_ops snd_rme9652_playback_ops = { 233462306a36Sopenharmony_ci .open = snd_rme9652_playback_open, 233562306a36Sopenharmony_ci .close = snd_rme9652_playback_release, 233662306a36Sopenharmony_ci .ioctl = snd_rme9652_ioctl, 233762306a36Sopenharmony_ci .hw_params = snd_rme9652_hw_params, 233862306a36Sopenharmony_ci .prepare = snd_rme9652_prepare, 233962306a36Sopenharmony_ci .trigger = snd_rme9652_trigger, 234062306a36Sopenharmony_ci .pointer = snd_rme9652_hw_pointer, 234162306a36Sopenharmony_ci .copy = snd_rme9652_playback_copy, 234262306a36Sopenharmony_ci .fill_silence = snd_rme9652_hw_silence, 234362306a36Sopenharmony_ci}; 234462306a36Sopenharmony_ci 234562306a36Sopenharmony_cistatic const struct snd_pcm_ops snd_rme9652_capture_ops = { 234662306a36Sopenharmony_ci .open = snd_rme9652_capture_open, 234762306a36Sopenharmony_ci .close = snd_rme9652_capture_release, 234862306a36Sopenharmony_ci .ioctl = snd_rme9652_ioctl, 234962306a36Sopenharmony_ci .hw_params = snd_rme9652_hw_params, 235062306a36Sopenharmony_ci .prepare = snd_rme9652_prepare, 235162306a36Sopenharmony_ci .trigger = snd_rme9652_trigger, 235262306a36Sopenharmony_ci .pointer = snd_rme9652_hw_pointer, 235362306a36Sopenharmony_ci .copy = snd_rme9652_capture_copy, 235462306a36Sopenharmony_ci}; 235562306a36Sopenharmony_ci 235662306a36Sopenharmony_cistatic int snd_rme9652_create_pcm(struct snd_card *card, 235762306a36Sopenharmony_ci struct snd_rme9652 *rme9652) 235862306a36Sopenharmony_ci{ 235962306a36Sopenharmony_ci struct snd_pcm *pcm; 236062306a36Sopenharmony_ci int err; 236162306a36Sopenharmony_ci 236262306a36Sopenharmony_ci err = snd_pcm_new(card, rme9652->card_name, 0, 1, 1, &pcm); 236362306a36Sopenharmony_ci if (err < 0) 236462306a36Sopenharmony_ci return err; 236562306a36Sopenharmony_ci 236662306a36Sopenharmony_ci rme9652->pcm = pcm; 236762306a36Sopenharmony_ci pcm->private_data = rme9652; 236862306a36Sopenharmony_ci strcpy(pcm->name, rme9652->card_name); 236962306a36Sopenharmony_ci 237062306a36Sopenharmony_ci snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_rme9652_playback_ops); 237162306a36Sopenharmony_ci snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme9652_capture_ops); 237262306a36Sopenharmony_ci 237362306a36Sopenharmony_ci pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; 237462306a36Sopenharmony_ci 237562306a36Sopenharmony_ci return 0; 237662306a36Sopenharmony_ci} 237762306a36Sopenharmony_ci 237862306a36Sopenharmony_cistatic int snd_rme9652_create(struct snd_card *card, 237962306a36Sopenharmony_ci struct snd_rme9652 *rme9652, 238062306a36Sopenharmony_ci int precise_ptr) 238162306a36Sopenharmony_ci{ 238262306a36Sopenharmony_ci struct pci_dev *pci = rme9652->pci; 238362306a36Sopenharmony_ci int err; 238462306a36Sopenharmony_ci int status; 238562306a36Sopenharmony_ci unsigned short rev; 238662306a36Sopenharmony_ci 238762306a36Sopenharmony_ci rme9652->irq = -1; 238862306a36Sopenharmony_ci rme9652->card = card; 238962306a36Sopenharmony_ci 239062306a36Sopenharmony_ci pci_read_config_word(rme9652->pci, PCI_CLASS_REVISION, &rev); 239162306a36Sopenharmony_ci 239262306a36Sopenharmony_ci switch (rev & 0xff) { 239362306a36Sopenharmony_ci case 3: 239462306a36Sopenharmony_ci case 4: 239562306a36Sopenharmony_ci case 8: 239662306a36Sopenharmony_ci case 9: 239762306a36Sopenharmony_ci break; 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci default: 240062306a36Sopenharmony_ci /* who knows? */ 240162306a36Sopenharmony_ci return -ENODEV; 240262306a36Sopenharmony_ci } 240362306a36Sopenharmony_ci 240462306a36Sopenharmony_ci err = pcim_enable_device(pci); 240562306a36Sopenharmony_ci if (err < 0) 240662306a36Sopenharmony_ci return err; 240762306a36Sopenharmony_ci 240862306a36Sopenharmony_ci spin_lock_init(&rme9652->lock); 240962306a36Sopenharmony_ci 241062306a36Sopenharmony_ci err = pci_request_regions(pci, "rme9652"); 241162306a36Sopenharmony_ci if (err < 0) 241262306a36Sopenharmony_ci return err; 241362306a36Sopenharmony_ci rme9652->port = pci_resource_start(pci, 0); 241462306a36Sopenharmony_ci rme9652->iobase = devm_ioremap(&pci->dev, rme9652->port, RME9652_IO_EXTENT); 241562306a36Sopenharmony_ci if (rme9652->iobase == NULL) { 241662306a36Sopenharmony_ci dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n", 241762306a36Sopenharmony_ci rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1); 241862306a36Sopenharmony_ci return -EBUSY; 241962306a36Sopenharmony_ci } 242062306a36Sopenharmony_ci 242162306a36Sopenharmony_ci if (devm_request_irq(&pci->dev, pci->irq, snd_rme9652_interrupt, 242262306a36Sopenharmony_ci IRQF_SHARED, KBUILD_MODNAME, rme9652)) { 242362306a36Sopenharmony_ci dev_err(card->dev, "unable to request IRQ %d\n", pci->irq); 242462306a36Sopenharmony_ci return -EBUSY; 242562306a36Sopenharmony_ci } 242662306a36Sopenharmony_ci rme9652->irq = pci->irq; 242762306a36Sopenharmony_ci card->sync_irq = rme9652->irq; 242862306a36Sopenharmony_ci rme9652->precise_ptr = precise_ptr; 242962306a36Sopenharmony_ci 243062306a36Sopenharmony_ci /* Determine the h/w rev level of the card. This seems like 243162306a36Sopenharmony_ci a particularly kludgy way to encode it, but its what RME 243262306a36Sopenharmony_ci chose to do, so we follow them ... 243362306a36Sopenharmony_ci */ 243462306a36Sopenharmony_ci 243562306a36Sopenharmony_ci status = rme9652_read(rme9652, RME9652_status_register); 243662306a36Sopenharmony_ci if (rme9652_decode_spdif_rate(status&RME9652_F) == 1) { 243762306a36Sopenharmony_ci rme9652->hw_rev = 15; 243862306a36Sopenharmony_ci } else { 243962306a36Sopenharmony_ci rme9652->hw_rev = 11; 244062306a36Sopenharmony_ci } 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci /* Differentiate between the standard Hammerfall, and the 244362306a36Sopenharmony_ci "Light", which does not have the expansion board. This 244462306a36Sopenharmony_ci method comes from information received from Mathhias 244562306a36Sopenharmony_ci Clausen at RME. Display the EEPROM and h/w revID where 244662306a36Sopenharmony_ci relevant. 244762306a36Sopenharmony_ci */ 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci switch (rev) { 245062306a36Sopenharmony_ci case 8: /* original eprom */ 245162306a36Sopenharmony_ci strcpy(card->driver, "RME9636"); 245262306a36Sopenharmony_ci if (rme9652->hw_rev == 15) { 245362306a36Sopenharmony_ci rme9652->card_name = "RME Digi9636 (Rev 1.5)"; 245462306a36Sopenharmony_ci } else { 245562306a36Sopenharmony_ci rme9652->card_name = "RME Digi9636"; 245662306a36Sopenharmony_ci } 245762306a36Sopenharmony_ci rme9652->ss_channels = RME9636_NCHANNELS; 245862306a36Sopenharmony_ci break; 245962306a36Sopenharmony_ci case 9: /* W36_G EPROM */ 246062306a36Sopenharmony_ci strcpy(card->driver, "RME9636"); 246162306a36Sopenharmony_ci rme9652->card_name = "RME Digi9636 (Rev G)"; 246262306a36Sopenharmony_ci rme9652->ss_channels = RME9636_NCHANNELS; 246362306a36Sopenharmony_ci break; 246462306a36Sopenharmony_ci case 4: /* W52_G EPROM */ 246562306a36Sopenharmony_ci strcpy(card->driver, "RME9652"); 246662306a36Sopenharmony_ci rme9652->card_name = "RME Digi9652 (Rev G)"; 246762306a36Sopenharmony_ci rme9652->ss_channels = RME9652_NCHANNELS; 246862306a36Sopenharmony_ci break; 246962306a36Sopenharmony_ci case 3: /* original eprom */ 247062306a36Sopenharmony_ci strcpy(card->driver, "RME9652"); 247162306a36Sopenharmony_ci if (rme9652->hw_rev == 15) { 247262306a36Sopenharmony_ci rme9652->card_name = "RME Digi9652 (Rev 1.5)"; 247362306a36Sopenharmony_ci } else { 247462306a36Sopenharmony_ci rme9652->card_name = "RME Digi9652"; 247562306a36Sopenharmony_ci } 247662306a36Sopenharmony_ci rme9652->ss_channels = RME9652_NCHANNELS; 247762306a36Sopenharmony_ci break; 247862306a36Sopenharmony_ci } 247962306a36Sopenharmony_ci 248062306a36Sopenharmony_ci rme9652->ds_channels = (rme9652->ss_channels - 2) / 2 + 2; 248162306a36Sopenharmony_ci 248262306a36Sopenharmony_ci pci_set_master(rme9652->pci); 248362306a36Sopenharmony_ci 248462306a36Sopenharmony_ci err = snd_rme9652_initialize_memory(rme9652); 248562306a36Sopenharmony_ci if (err < 0) 248662306a36Sopenharmony_ci return err; 248762306a36Sopenharmony_ci 248862306a36Sopenharmony_ci err = snd_rme9652_create_pcm(card, rme9652); 248962306a36Sopenharmony_ci if (err < 0) 249062306a36Sopenharmony_ci return err; 249162306a36Sopenharmony_ci 249262306a36Sopenharmony_ci err = snd_rme9652_create_controls(card, rme9652); 249362306a36Sopenharmony_ci if (err < 0) 249462306a36Sopenharmony_ci return err; 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_ci snd_rme9652_proc_init(rme9652); 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ci rme9652->last_spdif_sample_rate = -1; 249962306a36Sopenharmony_ci rme9652->last_adat_sample_rate = -1; 250062306a36Sopenharmony_ci rme9652->playback_pid = -1; 250162306a36Sopenharmony_ci rme9652->capture_pid = -1; 250262306a36Sopenharmony_ci rme9652->capture_substream = NULL; 250362306a36Sopenharmony_ci rme9652->playback_substream = NULL; 250462306a36Sopenharmony_ci 250562306a36Sopenharmony_ci snd_rme9652_set_defaults(rme9652); 250662306a36Sopenharmony_ci 250762306a36Sopenharmony_ci if (rme9652->hw_rev == 15) { 250862306a36Sopenharmony_ci rme9652_initialize_spdif_receiver (rme9652); 250962306a36Sopenharmony_ci } 251062306a36Sopenharmony_ci 251162306a36Sopenharmony_ci return 0; 251262306a36Sopenharmony_ci} 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_cistatic int snd_rme9652_probe(struct pci_dev *pci, 251562306a36Sopenharmony_ci const struct pci_device_id *pci_id) 251662306a36Sopenharmony_ci{ 251762306a36Sopenharmony_ci static int dev; 251862306a36Sopenharmony_ci struct snd_rme9652 *rme9652; 251962306a36Sopenharmony_ci struct snd_card *card; 252062306a36Sopenharmony_ci int err; 252162306a36Sopenharmony_ci 252262306a36Sopenharmony_ci if (dev >= SNDRV_CARDS) 252362306a36Sopenharmony_ci return -ENODEV; 252462306a36Sopenharmony_ci if (!enable[dev]) { 252562306a36Sopenharmony_ci dev++; 252662306a36Sopenharmony_ci return -ENOENT; 252762306a36Sopenharmony_ci } 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_ci err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 253062306a36Sopenharmony_ci sizeof(struct snd_rme9652), &card); 253162306a36Sopenharmony_ci 253262306a36Sopenharmony_ci if (err < 0) 253362306a36Sopenharmony_ci return err; 253462306a36Sopenharmony_ci 253562306a36Sopenharmony_ci rme9652 = (struct snd_rme9652 *) card->private_data; 253662306a36Sopenharmony_ci card->private_free = snd_rme9652_card_free; 253762306a36Sopenharmony_ci rme9652->dev = dev; 253862306a36Sopenharmony_ci rme9652->pci = pci; 253962306a36Sopenharmony_ci err = snd_rme9652_create(card, rme9652, precise_ptr[dev]); 254062306a36Sopenharmony_ci if (err) 254162306a36Sopenharmony_ci goto error; 254262306a36Sopenharmony_ci 254362306a36Sopenharmony_ci strcpy(card->shortname, rme9652->card_name); 254462306a36Sopenharmony_ci 254562306a36Sopenharmony_ci sprintf(card->longname, "%s at 0x%lx, irq %d", 254662306a36Sopenharmony_ci card->shortname, rme9652->port, rme9652->irq); 254762306a36Sopenharmony_ci err = snd_card_register(card); 254862306a36Sopenharmony_ci if (err) 254962306a36Sopenharmony_ci goto error; 255062306a36Sopenharmony_ci pci_set_drvdata(pci, card); 255162306a36Sopenharmony_ci dev++; 255262306a36Sopenharmony_ci return 0; 255362306a36Sopenharmony_ci 255462306a36Sopenharmony_ci error: 255562306a36Sopenharmony_ci snd_card_free(card); 255662306a36Sopenharmony_ci return err; 255762306a36Sopenharmony_ci} 255862306a36Sopenharmony_ci 255962306a36Sopenharmony_cistatic struct pci_driver rme9652_driver = { 256062306a36Sopenharmony_ci .name = KBUILD_MODNAME, 256162306a36Sopenharmony_ci .id_table = snd_rme9652_ids, 256262306a36Sopenharmony_ci .probe = snd_rme9652_probe, 256362306a36Sopenharmony_ci}; 256462306a36Sopenharmony_ci 256562306a36Sopenharmony_cimodule_pci_driver(rme9652_driver); 2566