blob: 7055d893855d1df75781a7a77d5d4818e7931ee8 [file] [log] [blame]
Takashi Iwai763f3562005-06-03 11:25:34 +02001/* -*- linux-c -*-
2 *
3 * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
4 *
5 * Copyright (c) 2003 Winfried Ritsch (IEM)
6 * code based on hdsp.c Paul Davis
7 * Marcus Andersson
8 * Thomas Charbonnel
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25#include <sound/driver.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/interrupt.h>
29#include <linux/moduleparam.h>
30#include <linux/slab.h>
31#include <linux/pci.h>
32#include <asm/io.h>
33
34#include <sound/core.h>
35#include <sound/control.h>
36#include <sound/pcm.h>
37#include <sound/info.h>
38#include <sound/asoundef.h>
39#include <sound/rawmidi.h>
40#include <sound/hwdep.h>
41#include <sound/initval.h>
42
43#include <sound/hdspm.h>
44
45static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
46static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
47static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
48
49/* Disable precise pointer at start */
50static int precise_ptr[SNDRV_CARDS];
51
52/* Send all playback to line outs */
53static int line_outs_monitor[SNDRV_CARDS];
54
55/* Enable Analog Outs on Channel 63/64 by default */
56static int enable_monitor[SNDRV_CARDS];
57
58module_param_array(index, int, NULL, 0444);
59MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
60
61module_param_array(id, charp, NULL, 0444);
62MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
63
64module_param_array(enable, bool, NULL, 0444);
65MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
66
67module_param_array(precise_ptr, bool, NULL, 0444);
Takashi Iwaie8da2fb2005-08-16 16:55:13 +020068MODULE_PARM_DESC(precise_ptr, "Enable or disable precise pointer.");
Takashi Iwai763f3562005-06-03 11:25:34 +020069
70module_param_array(line_outs_monitor, bool, NULL, 0444);
71MODULE_PARM_DESC(line_outs_monitor,
72 "Send playback streams to analog outs by default.");
73
74module_param_array(enable_monitor, bool, NULL, 0444);
75MODULE_PARM_DESC(enable_monitor,
76 "Enable Analog Out on Channel 63/64 by default.");
77
78MODULE_AUTHOR
79 ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, "
80 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
81MODULE_DESCRIPTION("RME HDSPM");
82MODULE_LICENSE("GPL");
83MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
84
85/* --- Write registers. ---
86 These are defined as byte-offsets from the iobase value. */
87
88#define HDSPM_controlRegister 64
89#define HDSPM_interruptConfirmation 96
90#define HDSPM_control2Reg 256 /* not in specs ???????? */
91#define HDSPM_midiDataOut0 352 /* just believe in old code */
92#define HDSPM_midiDataOut1 356
93
94/* DMA enable for 64 channels, only Bit 0 is relevant */
95#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
96#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
97
98/* 16 page addresses for each of the 64 channels DMA buffer in and out
99 (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
100#define HDSPM_pageAddressBufferOut 8192
101#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
102
103#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
104
105#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
106
107/* --- Read registers. ---
108 These are defined as byte-offsets from the iobase value */
109#define HDSPM_statusRegister 0
110#define HDSPM_statusRegister2 96
111
112#define HDSPM_midiDataIn0 360
113#define HDSPM_midiDataIn1 364
114
115/* status is data bytes in MIDI-FIFO (0-128) */
116#define HDSPM_midiStatusOut0 384
117#define HDSPM_midiStatusOut1 388
118#define HDSPM_midiStatusIn0 392
119#define HDSPM_midiStatusIn1 396
120
121
122/* the meters are regular i/o-mapped registers, but offset
123 considerably from the rest. the peak registers are reset
124 when read; the least-significant 4 bits are full-scale counters;
125 the actual peak value is in the most-significant 24 bits.
126*/
127#define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters */
128
129/* --- Control Register bits --------- */
130#define HDSPM_Start (1<<0) /* start engine */
131
132#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
133#define HDSPM_Latency1 (1<<2) /* where n is defined */
134#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
135
136#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
137
138#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
139
140#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
141#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
142#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
143#define HDSPM_QuadSpeed (1<<31) /* quad speed bit, not implemented now */
144
145#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
146 56channelMODE=0 */
147
148#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
149 0=off, 1=on */
150
151#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */
152#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
153
154#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */
155#define HDSPM_SyncRef1 (1<<17) /* should be 0 */
156
157#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
158 AES additional bits in
159 lower 5 Audiodatabits ??? */
160
161#define HDSPM_Midi0InterruptEnable (1<<22)
162#define HDSPM_Midi1InterruptEnable (1<<23)
163
164#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
165
166
167/* --- bit helper defines */
168#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
169#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1)
170#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
171#define HDSPM_InputOptical 0
172#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
173#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1)
174#define HDSPM_SyncRef_Word 0
175#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0)
176
177#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
178#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
179
180#define HDSPM_Frequency32KHz HDSPM_Frequency0
181#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
182#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
183#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
184#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
185#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
186
187/* --- for internal discrimination */
188#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */
189#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1
190#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
191#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3
192#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4
193#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
194#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6
195#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7
196#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
197#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9
198
199/* Synccheck Status */
200#define HDSPM_SYNC_CHECK_NO_LOCK 0
201#define HDSPM_SYNC_CHECK_LOCK 1
202#define HDSPM_SYNC_CHECK_SYNC 2
203
204/* AutoSync References - used by "autosync_ref" control switch */
205#define HDSPM_AUTOSYNC_FROM_WORD 0
206#define HDSPM_AUTOSYNC_FROM_MADI 1
207#define HDSPM_AUTOSYNC_FROM_NONE 2
208
209/* Possible sources of MADI input */
210#define HDSPM_OPTICAL 0 /* optical */
211#define HDSPM_COAXIAL 1 /* BNC */
212
213#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
214#define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1)
215
216#define hdspm_encode_in(x) (((x)&0x3)<<14)
217#define hdspm_decode_in(x) (((x)>>14)&0x3)
218
219/* --- control2 register bits --- */
220#define HDSPM_TMS (1<<0)
221#define HDSPM_TCK (1<<1)
222#define HDSPM_TDI (1<<2)
223#define HDSPM_JTAG (1<<3)
224#define HDSPM_PWDN (1<<4)
225#define HDSPM_PROGRAM (1<<5)
226#define HDSPM_CONFIG_MODE_0 (1<<6)
227#define HDSPM_CONFIG_MODE_1 (1<<7)
228/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
229#define HDSPM_BIGENDIAN_MODE (1<<9)
230#define HDSPM_RD_MULTIPLE (1<<10)
231
232/* --- Status Register bits --- */
233#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
234#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */
235#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */
236#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
237
238#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
239 /* since 64byte accurate last 6 bits
240 are not used */
241
242#define HDSPM_madiSync (1<<18) /* MADI is in sync */
243#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
244
245#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
246#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
247#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
248#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
249
250#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with Interrupt */
251#define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */
252#define HDSPM_midi1IRQPending (1<<31) /* and aktiv */
253
254/* --- status bit helpers */
255#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3)
256#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
257#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
258#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
259#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
260#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
261#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
262#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
263#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
264#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
265
266/* Status2 Register bits */
267
268#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
269#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
270#define HDSPM_version2 (1<<2)
271
272#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
273#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
274
275#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
276#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
277#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
278/* missing Bit for 111=128, 1000=176.4, 1001=192 */
279
280#define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */
281#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
282#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
283
284#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
285
286#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
287#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
288#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
289#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
290#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
291#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
292#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
293
294
295#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
296#define HDSPM_SelSyncRef_WORD 0
297#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
298#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
299
300/* Mixer Values */
301#define UNITY_GAIN 32768 /* = 65536/2 */
302#define MINUS_INFINITY_GAIN 0
303
Takashi Iwai763f3562005-06-03 11:25:34 +0200304/* Number of channels for different Speed Modes */
305#define MADI_SS_CHANNELS 64
306#define MADI_DS_CHANNELS 32
307#define MADI_QS_CHANNELS 16
308
309/* the size of a substream (1 mono data stream) */
310#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
311#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
312
313/* the size of the area we need to allocate for DMA transfers. the
314 size is the same regardless of the number of channels, and
315 also the latency to use.
316 for one direction !!!
317*/
318#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
319#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
320
Takashi Iwai98274f02005-11-17 14:52:34 +0100321struct hdspm_midi {
322 struct hdspm *hdspm;
Takashi Iwai763f3562005-06-03 11:25:34 +0200323 int id;
Takashi Iwai98274f02005-11-17 14:52:34 +0100324 struct snd_rawmidi *rmidi;
325 struct snd_rawmidi_substream *input;
326 struct snd_rawmidi_substream *output;
Takashi Iwai763f3562005-06-03 11:25:34 +0200327 char istimer; /* timer in use */
328 struct timer_list timer;
329 spinlock_t lock;
330 int pending;
331};
332
Takashi Iwai98274f02005-11-17 14:52:34 +0100333struct hdspm {
Takashi Iwai763f3562005-06-03 11:25:34 +0200334 spinlock_t lock;
Takashi Iwai98274f02005-11-17 14:52:34 +0100335 struct snd_pcm_substream *capture_substream; /* only one playback */
336 struct snd_pcm_substream *playback_substream; /* and/or capture stream */
Takashi Iwai763f3562005-06-03 11:25:34 +0200337
338 char *card_name; /* for procinfo */
339 unsigned short firmware_rev; /* dont know if relevant */
340
341 int precise_ptr; /* use precise pointers, to be tested */
342 int monitor_outs; /* set up monitoring outs init flag */
343
344 u32 control_register; /* cached value */
345 u32 control2_register; /* cached value */
346
Takashi Iwai98274f02005-11-17 14:52:34 +0100347 struct hdspm_midi midi[2];
Takashi Iwai763f3562005-06-03 11:25:34 +0200348 struct tasklet_struct midi_tasklet;
349
350 size_t period_bytes;
351 unsigned char ss_channels; /* channels of card in single speed */
352 unsigned char ds_channels; /* Double Speed */
353 unsigned char qs_channels; /* Quad Speed */
354
355 unsigned char *playback_buffer; /* suitably aligned address */
356 unsigned char *capture_buffer; /* suitably aligned address */
357
358 pid_t capture_pid; /* process id which uses capture */
359 pid_t playback_pid; /* process id which uses capture */
360 int running; /* running status */
361
362 int last_external_sample_rate; /* samplerate mystic ... */
363 int last_internal_sample_rate;
364 int system_sample_rate;
365
366 char *channel_map; /* channel map for DS and Quadspeed */
367
368 int dev; /* Hardware vars... */
369 int irq;
370 unsigned long port;
371 void __iomem *iobase;
372
373 int irq_count; /* for debug */
374
Takashi Iwai98274f02005-11-17 14:52:34 +0100375 struct snd_card *card; /* one card */
376 struct snd_pcm *pcm; /* has one pcm */
377 struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
Takashi Iwai763f3562005-06-03 11:25:34 +0200378 struct pci_dev *pci; /* and an pci info */
379
380 /* Mixer vars */
Takashi Iwai98274f02005-11-17 14:52:34 +0100381 struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */
382 struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */
383 struct hdspm_mixer *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */
Takashi Iwai763f3562005-06-03 11:25:34 +0200384
385};
386
387/* These tables map the ALSA channels 1..N to the channels that we
388 need to use in order to find the relevant channel buffer. RME
389 refer to this kind of mapping as between "the ADAT channel and
390 the DMA channel." We index it using the logical audio channel,
391 and the value is the DMA channel (i.e. channel buffer number)
392 where the data for that channel can be read/written from/to.
393*/
394
395static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
396 0, 1, 2, 3, 4, 5, 6, 7,
397 8, 9, 10, 11, 12, 13, 14, 15,
398 16, 17, 18, 19, 20, 21, 22, 23,
399 24, 25, 26, 27, 28, 29, 30, 31,
400 32, 33, 34, 35, 36, 37, 38, 39,
401 40, 41, 42, 43, 44, 45, 46, 47,
402 48, 49, 50, 51, 52, 53, 54, 55,
403 56, 57, 58, 59, 60, 61, 62, 63
404};
405
406static char channel_map_madi_ds[HDSPM_MAX_CHANNELS] = {
407 0, 2, 4, 6, 8, 10, 12, 14,
408 16, 18, 20, 22, 24, 26, 28, 30,
409 32, 34, 36, 38, 40, 42, 44, 46,
410 48, 50, 52, 54, 56, 58, 60, 62,
411 -1, -1, -1, -1, -1, -1, -1, -1,
412 -1, -1, -1, -1, -1, -1, -1, -1,
413 -1, -1, -1, -1, -1, -1, -1, -1,
414 -1, -1, -1, -1, -1, -1, -1, -1
415};
416
417static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = {
418 0, 4, 8, 12, 16, 20, 24, 28,
419 32, 36, 40, 44, 48, 52, 56, 60
420 -1, -1, -1, -1, -1, -1, -1, -1,
421 -1, -1, -1, -1, -1, -1, -1, -1,
422 -1, -1, -1, -1, -1, -1, -1, -1,
423 -1, -1, -1, -1, -1, -1, -1, -1,
424 -1, -1, -1, -1, -1, -1, -1, -1,
425 -1, -1, -1, -1, -1, -1, -1, -1
426};
427
428
Henrik Kretzschmar396c9b92006-04-24 15:59:04 +0200429static struct pci_device_id snd_hdspm_ids[] __devinitdata = {
Takashi Iwai763f3562005-06-03 11:25:34 +0200430 {
431 .vendor = PCI_VENDOR_ID_XILINX,
432 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
433 .subvendor = PCI_ANY_ID,
434 .subdevice = PCI_ANY_ID,
435 .class = 0,
436 .class_mask = 0,
437 .driver_data = 0},
438 {0,}
439};
440
441MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
442
443/* prototypes */
Takashi Iwai98274f02005-11-17 14:52:34 +0100444static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
445 struct hdspm * hdspm);
446static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
447 struct hdspm * hdspm);
Takashi Iwai763f3562005-06-03 11:25:34 +0200448
Takashi Iwai98274f02005-11-17 14:52:34 +0100449static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm);
450static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm);
451static int hdspm_autosync_ref(struct hdspm * hdspm);
452static int snd_hdspm_set_defaults(struct hdspm * hdspm);
453static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
Takashi Iwai763f3562005-06-03 11:25:34 +0200454 unsigned int reg, int channels);
455
456/* Write/read to/from HDSPM with Adresses in Bytes
457 not words but only 32Bit writes are allowed */
458
Takashi Iwai98274f02005-11-17 14:52:34 +0100459static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
Takashi Iwai763f3562005-06-03 11:25:34 +0200460 unsigned int val)
461{
462 writel(val, hdspm->iobase + reg);
463}
464
Takashi Iwai98274f02005-11-17 14:52:34 +0100465static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
Takashi Iwai763f3562005-06-03 11:25:34 +0200466{
467 return readl(hdspm->iobase + reg);
468}
469
470/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
471 mixer is write only on hardware so we have to cache him for read
472 each fader is a u32, but uses only the first 16 bit */
473
Takashi Iwai98274f02005-11-17 14:52:34 +0100474static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200475 unsigned int in)
476{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100477 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200478 return 0;
479
480 return hdspm->mixer->ch[chan].in[in];
481}
482
Takashi Iwai98274f02005-11-17 14:52:34 +0100483static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200484 unsigned int pb)
485{
Adrian Bunk5bab24822006-03-13 14:15:04 +0100486 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
Takashi Iwai763f3562005-06-03 11:25:34 +0200487 return 0;
488 return hdspm->mixer->ch[chan].pb[pb];
489}
490
Takashi Iwai98274f02005-11-17 14:52:34 +0100491static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200492 unsigned int in, unsigned short data)
493{
494 if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
495 return -1;
496
497 hdspm_write(hdspm,
498 HDSPM_MADI_mixerBase +
499 ((in + 128 * chan) * sizeof(u32)),
500 (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
501 return 0;
502}
503
Takashi Iwai98274f02005-11-17 14:52:34 +0100504static inline int hdspm_write_pb_gain(struct hdspm * hdspm, unsigned int chan,
Takashi Iwai763f3562005-06-03 11:25:34 +0200505 unsigned int pb, unsigned short data)
506{
507 if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
508 return -1;
509
510 hdspm_write(hdspm,
511 HDSPM_MADI_mixerBase +
512 ((64 + pb + 128 * chan) * sizeof(u32)),
513 (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
514 return 0;
515}
516
517
518/* enable DMA for specific channels, now available for DSP-MADI */
Takashi Iwai98274f02005-11-17 14:52:34 +0100519static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200520{
521 hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
522}
523
Takashi Iwai98274f02005-11-17 14:52:34 +0100524static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
Takashi Iwai763f3562005-06-03 11:25:34 +0200525{
526 hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
527}
528
529/* check if same process is writing and reading */
Takashi Iwai98274f02005-11-17 14:52:34 +0100530static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200531{
532 unsigned long flags;
533 int ret = 1;
534
535 spin_lock_irqsave(&hdspm->lock, flags);
536 if ((hdspm->playback_pid != hdspm->capture_pid) &&
537 (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
538 ret = 0;
539 }
540 spin_unlock_irqrestore(&hdspm->lock, flags);
541 return ret;
542}
543
544/* check for external sample rate */
Takashi Iwai98274f02005-11-17 14:52:34 +0100545static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200546{
547 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
548 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
549 unsigned int rate_bits;
550 int rate = 0;
551
552 /* if wordclock has synced freq and wordclock is valid */
553 if ((status2 & HDSPM_wcLock) != 0 &&
554 (status & HDSPM_SelSyncRef0) == 0) {
555
556 rate_bits = status2 & HDSPM_wcFreqMask;
557
558 switch (rate_bits) {
559 case HDSPM_wcFreq32:
560 rate = 32000;
561 break;
562 case HDSPM_wcFreq44_1:
563 rate = 44100;
564 break;
565 case HDSPM_wcFreq48:
566 rate = 48000;
567 break;
568 case HDSPM_wcFreq64:
569 rate = 64000;
570 break;
571 case HDSPM_wcFreq88_2:
572 rate = 88200;
573 break;
574 case HDSPM_wcFreq96:
575 rate = 96000;
576 break;
577 /* Quadspeed Bit missing ???? */
578 default:
579 rate = 0;
580 break;
581 }
582 }
583
584 /* if rate detected and Syncref is Word than have it, word has priority to MADI */
585 if (rate != 0
586 && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
587 return rate;
588
589 /* maby a madi input (which is taken if sel sync is madi) */
590 if (status & HDSPM_madiLock) {
591 rate_bits = status & HDSPM_madiFreqMask;
592
593 switch (rate_bits) {
594 case HDSPM_madiFreq32:
595 rate = 32000;
596 break;
597 case HDSPM_madiFreq44_1:
598 rate = 44100;
599 break;
600 case HDSPM_madiFreq48:
601 rate = 48000;
602 break;
603 case HDSPM_madiFreq64:
604 rate = 64000;
605 break;
606 case HDSPM_madiFreq88_2:
607 rate = 88200;
608 break;
609 case HDSPM_madiFreq96:
610 rate = 96000;
611 break;
612 case HDSPM_madiFreq128:
613 rate = 128000;
614 break;
615 case HDSPM_madiFreq176_4:
616 rate = 176400;
617 break;
618 case HDSPM_madiFreq192:
619 rate = 192000;
620 break;
621 default:
622 rate = 0;
623 break;
624 }
625 }
626 return rate;
627}
628
629/* Latency function */
Takashi Iwai98274f02005-11-17 14:52:34 +0100630static inline void hdspm_compute_period_size(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200631{
632 hdspm->period_bytes =
633 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
634}
635
Takashi Iwai98274f02005-11-17 14:52:34 +0100636static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200637{
638 int position;
639
640 position = hdspm_read(hdspm, HDSPM_statusRegister);
641
642 if (!hdspm->precise_ptr) {
643 return (position & HDSPM_BufferID) ? (hdspm->period_bytes /
644 4) : 0;
645 }
646
647 /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst)
648 i have experimented that it is at most 64 Byte to much for playing
649 so substraction of 64 byte should be ok for ALSA, but use it only
650 for application where you know what you do since if you come to
651 near with record pointer it can be a disaster */
652
653 position &= HDSPM_BufferPositionMask;
654 position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;
655
656 return position;
657}
658
659
Takashi Iwai98274f02005-11-17 14:52:34 +0100660static inline void hdspm_start_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +0200661{
662 s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
663 hdspm_write(s, HDSPM_controlRegister, s->control_register);
664}
665
Takashi Iwai98274f02005-11-17 14:52:34 +0100666static inline void hdspm_stop_audio(struct hdspm * s)
Takashi Iwai763f3562005-06-03 11:25:34 +0200667{
668 s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
669 hdspm_write(s, HDSPM_controlRegister, s->control_register);
670}
671
672/* should I silence all or only opened ones ? doit all for first even is 4MB*/
Takashi Iwai98274f02005-11-17 14:52:34 +0100673static inline void hdspm_silence_playback(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +0200674{
675 int i;
676 int n = hdspm->period_bytes;
677 void *buf = hdspm->playback_buffer;
678
679 snd_assert(buf != NULL, return);
680
681 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
682 memset(buf, 0, n);
683 buf += HDSPM_CHANNEL_BUFFER_BYTES;
684 }
685}
686
Takashi Iwai98274f02005-11-17 14:52:34 +0100687static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames)
Takashi Iwai763f3562005-06-03 11:25:34 +0200688{
689 int n;
690
691 spin_lock_irq(&s->lock);
692
693 frames >>= 7;
694 n = 0;
695 while (frames) {
696 n++;
697 frames >>= 1;
698 }
699 s->control_register &= ~HDSPM_LatencyMask;
700 s->control_register |= hdspm_encode_latency(n);
701
702 hdspm_write(s, HDSPM_controlRegister, s->control_register);
703
704 hdspm_compute_period_size(s);
705
706 spin_unlock_irq(&s->lock);
707
708 return 0;
709}
710
711
712/* dummy set rate lets see what happens */
Takashi Iwai98274f02005-11-17 14:52:34 +0100713static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
Takashi Iwai763f3562005-06-03 11:25:34 +0200714{
715 int reject_if_open = 0;
716 int current_rate;
717 int rate_bits;
718 int not_set = 0;
719
720 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
721 it (e.g. during module initialization).
722 */
723
724 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
725
726 /* SLAVE --- */
727 if (called_internally) {
728
729 /* request from ctl or card initialization
730 just make a warning an remember setting
731 for future master mode switching */
732
733 snd_printk
734 (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n");
735 not_set = 1;
736 } else {
737
738 /* hw_param request while in AutoSync mode */
739 int external_freq =
740 hdspm_external_sample_rate(hdspm);
741
742 if ((hdspm_autosync_ref(hdspm) ==
743 HDSPM_AUTOSYNC_FROM_NONE)) {
744
745 snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n");
746 not_set = 1;
747
748 } else if (rate != external_freq) {
749
750 snd_printk
751 (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n");
752 not_set = 1;
753 }
754 }
755 }
756
757 current_rate = hdspm->system_sample_rate;
758
759 /* Changing between Singe, Double and Quad speed is not
760 allowed if any substreams are open. This is because such a change
761 causes a shift in the location of the DMA buffers and a reduction
762 in the number of available buffers.
763
764 Note that a similar but essentially insoluble problem exists for
765 externally-driven rate changes. All we can do is to flag rate
766 changes in the read/write routines.
767 */
768
769 switch (rate) {
770 case 32000:
771 if (current_rate > 48000) {
772 reject_if_open = 1;
773 }
774 rate_bits = HDSPM_Frequency32KHz;
775 break;
776 case 44100:
777 if (current_rate > 48000) {
778 reject_if_open = 1;
779 }
780 rate_bits = HDSPM_Frequency44_1KHz;
781 break;
782 case 48000:
783 if (current_rate > 48000) {
784 reject_if_open = 1;
785 }
786 rate_bits = HDSPM_Frequency48KHz;
787 break;
788 case 64000:
789 if (current_rate <= 48000) {
790 reject_if_open = 1;
791 }
792 rate_bits = HDSPM_Frequency64KHz;
793 break;
794 case 88200:
795 if (current_rate <= 48000) {
796 reject_if_open = 1;
797 }
798 rate_bits = HDSPM_Frequency88_2KHz;
799 break;
800 case 96000:
801 if (current_rate <= 48000) {
802 reject_if_open = 1;
803 }
804 rate_bits = HDSPM_Frequency96KHz;
805 break;
806 default:
807 return -EINVAL;
808 }
809
810 if (reject_if_open
811 && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
812 snd_printk
813 (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n",
814 hdspm->capture_pid, hdspm->playback_pid);
815 return -EBUSY;
816 }
817
818 hdspm->control_register &= ~HDSPM_FrequencyMask;
819 hdspm->control_register |= rate_bits;
820 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
821
822 if (rate > 64000)
823 hdspm->channel_map = channel_map_madi_qs;
824 else if (rate > 48000)
825 hdspm->channel_map = channel_map_madi_ds;
826 else
827 hdspm->channel_map = channel_map_madi_ss;
828
829 hdspm->system_sample_rate = rate;
830
831 if (not_set != 0)
832 return -1;
833
834 return 0;
835}
836
837/* mainly for init to 0 on load */
Takashi Iwai98274f02005-11-17 14:52:34 +0100838static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
Takashi Iwai763f3562005-06-03 11:25:34 +0200839{
840 int i, j;
841 unsigned int gain =
842 (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain;
843
844 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
845 for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
846 hdspm_write_in_gain(hdspm, i, j, gain);
847 hdspm_write_pb_gain(hdspm, i, j, gain);
848 }
849}
850
851/*----------------------------------------------------------------------------
852 MIDI
853 ----------------------------------------------------------------------------*/
854
Takashi Iwai98274f02005-11-17 14:52:34 +0100855static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +0200856{
857 /* the hardware already does the relevant bit-mask with 0xff */
858 if (id)
859 return hdspm_read(hdspm, HDSPM_midiDataIn1);
860 else
861 return hdspm_read(hdspm, HDSPM_midiDataIn0);
862}
863
Takashi Iwai98274f02005-11-17 14:52:34 +0100864static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, int val)
Takashi Iwai763f3562005-06-03 11:25:34 +0200865{
866 /* the hardware already does the relevant bit-mask with 0xff */
867 if (id)
868 return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
869 else
870 return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
871}
872
Takashi Iwai98274f02005-11-17 14:52:34 +0100873static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +0200874{
875 if (id)
876 return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
877 else
878 return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
879}
880
Takashi Iwai98274f02005-11-17 14:52:34 +0100881static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +0200882{
883 int fifo_bytes_used;
884
885 if (id)
886 fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff;
887 else
888 fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff;
889
890 if (fifo_bytes_used < 128)
891 return 128 - fifo_bytes_used;
892 else
893 return 0;
894}
895
Takashi Iwai98274f02005-11-17 14:52:34 +0100896static inline void snd_hdspm_flush_midi_input (struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +0200897{
898 while (snd_hdspm_midi_input_available (hdspm, id))
899 snd_hdspm_midi_read_byte (hdspm, id);
900}
901
Takashi Iwai98274f02005-11-17 14:52:34 +0100902static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +0200903{
904 unsigned long flags;
905 int n_pending;
906 int to_write;
907 int i;
908 unsigned char buf[128];
909
910 /* Output is not interrupt driven */
911
912 spin_lock_irqsave (&hmidi->lock, flags);
913 if (hmidi->output) {
914 if (!snd_rawmidi_transmit_empty (hmidi->output)) {
915 if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) {
916 if (n_pending > (int)sizeof (buf))
917 n_pending = sizeof (buf);
918
919 if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
920 for (i = 0; i < to_write; ++i)
921 snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]);
922 }
923 }
924 }
925 }
926 spin_unlock_irqrestore (&hmidi->lock, flags);
927 return 0;
928}
929
Takashi Iwai98274f02005-11-17 14:52:34 +0100930static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
Takashi Iwai763f3562005-06-03 11:25:34 +0200931{
932 unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
933 unsigned long flags;
934 int n_pending;
935 int i;
936
937 spin_lock_irqsave (&hmidi->lock, flags);
938 if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) {
939 if (hmidi->input) {
940 if (n_pending > (int)sizeof (buf)) {
941 n_pending = sizeof (buf);
942 }
943 for (i = 0; i < n_pending; ++i) {
944 buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
945 }
946 if (n_pending) {
947 snd_rawmidi_receive (hmidi->input, buf, n_pending);
948 }
949 } else {
950 /* flush the MIDI input FIFO */
951 while (n_pending--) {
952 snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
953 }
954 }
955 }
956 hmidi->pending = 0;
957 if (hmidi->id) {
958 hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
959 } else {
960 hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
961 }
962 hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register);
963 spin_unlock_irqrestore (&hmidi->lock, flags);
964 return snd_hdspm_midi_output_write (hmidi);
965}
966
Takashi Iwai98274f02005-11-17 14:52:34 +0100967static void snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +0200968{
Takashi Iwai98274f02005-11-17 14:52:34 +0100969 struct hdspm *hdspm;
970 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +0200971 unsigned long flags;
972 u32 ie;
973
Takashi Iwai98274f02005-11-17 14:52:34 +0100974 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +0200975 hdspm = hmidi->hdspm;
976 ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
977 spin_lock_irqsave (&hdspm->lock, flags);
978 if (up) {
979 if (!(hdspm->control_register & ie)) {
980 snd_hdspm_flush_midi_input (hdspm, hmidi->id);
981 hdspm->control_register |= ie;
982 }
983 } else {
984 hdspm->control_register &= ~ie;
985 }
986
987 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
988 spin_unlock_irqrestore (&hdspm->lock, flags);
989}
990
991static void snd_hdspm_midi_output_timer(unsigned long data)
992{
Takashi Iwai98274f02005-11-17 14:52:34 +0100993 struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
Takashi Iwai763f3562005-06-03 11:25:34 +0200994 unsigned long flags;
995
996 snd_hdspm_midi_output_write(hmidi);
997 spin_lock_irqsave (&hmidi->lock, flags);
998
999 /* this does not bump hmidi->istimer, because the
1000 kernel automatically removed the timer when it
1001 expired, and we are now adding it back, thus
1002 leaving istimer wherever it was set before.
1003 */
1004
1005 if (hmidi->istimer) {
1006 hmidi->timer.expires = 1 + jiffies;
1007 add_timer(&hmidi->timer);
1008 }
1009
1010 spin_unlock_irqrestore (&hmidi->lock, flags);
1011}
1012
Takashi Iwai98274f02005-11-17 14:52:34 +01001013static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
Takashi Iwai763f3562005-06-03 11:25:34 +02001014{
Takashi Iwai98274f02005-11-17 14:52:34 +01001015 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001016 unsigned long flags;
1017
Takashi Iwai98274f02005-11-17 14:52:34 +01001018 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001019 spin_lock_irqsave (&hmidi->lock, flags);
1020 if (up) {
1021 if (!hmidi->istimer) {
1022 init_timer(&hmidi->timer);
1023 hmidi->timer.function = snd_hdspm_midi_output_timer;
1024 hmidi->timer.data = (unsigned long) hmidi;
1025 hmidi->timer.expires = 1 + jiffies;
1026 add_timer(&hmidi->timer);
1027 hmidi->istimer++;
1028 }
1029 } else {
1030 if (hmidi->istimer && --hmidi->istimer <= 0) {
1031 del_timer (&hmidi->timer);
1032 }
1033 }
1034 spin_unlock_irqrestore (&hmidi->lock, flags);
1035 if (up)
1036 snd_hdspm_midi_output_write(hmidi);
1037}
1038
Takashi Iwai98274f02005-11-17 14:52:34 +01001039static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001040{
Takashi Iwai98274f02005-11-17 14:52:34 +01001041 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001042
Takashi Iwai98274f02005-11-17 14:52:34 +01001043 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001044 spin_lock_irq (&hmidi->lock);
1045 snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
1046 hmidi->input = substream;
1047 spin_unlock_irq (&hmidi->lock);
1048
1049 return 0;
1050}
1051
Takashi Iwai98274f02005-11-17 14:52:34 +01001052static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001053{
Takashi Iwai98274f02005-11-17 14:52:34 +01001054 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001055
Takashi Iwai98274f02005-11-17 14:52:34 +01001056 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001057 spin_lock_irq (&hmidi->lock);
1058 hmidi->output = substream;
1059 spin_unlock_irq (&hmidi->lock);
1060
1061 return 0;
1062}
1063
Takashi Iwai98274f02005-11-17 14:52:34 +01001064static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001065{
Takashi Iwai98274f02005-11-17 14:52:34 +01001066 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001067
1068 snd_hdspm_midi_input_trigger (substream, 0);
1069
Takashi Iwai98274f02005-11-17 14:52:34 +01001070 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001071 spin_lock_irq (&hmidi->lock);
1072 hmidi->input = NULL;
1073 spin_unlock_irq (&hmidi->lock);
1074
1075 return 0;
1076}
1077
Takashi Iwai98274f02005-11-17 14:52:34 +01001078static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02001079{
Takashi Iwai98274f02005-11-17 14:52:34 +01001080 struct hdspm_midi *hmidi;
Takashi Iwai763f3562005-06-03 11:25:34 +02001081
1082 snd_hdspm_midi_output_trigger (substream, 0);
1083
Takashi Iwai98274f02005-11-17 14:52:34 +01001084 hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02001085 spin_lock_irq (&hmidi->lock);
1086 hmidi->output = NULL;
1087 spin_unlock_irq (&hmidi->lock);
1088
1089 return 0;
1090}
1091
Takashi Iwai98274f02005-11-17 14:52:34 +01001092static struct snd_rawmidi_ops snd_hdspm_midi_output =
Takashi Iwai763f3562005-06-03 11:25:34 +02001093{
1094 .open = snd_hdspm_midi_output_open,
1095 .close = snd_hdspm_midi_output_close,
1096 .trigger = snd_hdspm_midi_output_trigger,
1097};
1098
Takashi Iwai98274f02005-11-17 14:52:34 +01001099static struct snd_rawmidi_ops snd_hdspm_midi_input =
Takashi Iwai763f3562005-06-03 11:25:34 +02001100{
1101 .open = snd_hdspm_midi_input_open,
1102 .close = snd_hdspm_midi_input_close,
1103 .trigger = snd_hdspm_midi_input_trigger,
1104};
1105
Takashi Iwai98274f02005-11-17 14:52:34 +01001106static int __devinit snd_hdspm_create_midi (struct snd_card *card, struct hdspm *hdspm, int id)
Takashi Iwai763f3562005-06-03 11:25:34 +02001107{
1108 int err;
1109 char buf[32];
1110
1111 hdspm->midi[id].id = id;
1112 hdspm->midi[id].rmidi = NULL;
1113 hdspm->midi[id].input = NULL;
1114 hdspm->midi[id].output = NULL;
1115 hdspm->midi[id].hdspm = hdspm;
1116 hdspm->midi[id].istimer = 0;
1117 hdspm->midi[id].pending = 0;
1118 spin_lock_init (&hdspm->midi[id].lock);
1119
1120 sprintf (buf, "%s MIDI %d", card->shortname, id+1);
1121 if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0)
1122 return err;
1123
1124 sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
1125 hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
1126
1127 snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output);
1128 snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input);
1129
1130 hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
1131 SNDRV_RAWMIDI_INFO_INPUT |
1132 SNDRV_RAWMIDI_INFO_DUPLEX;
1133
1134 return 0;
1135}
1136
1137
1138static void hdspm_midi_tasklet(unsigned long arg)
1139{
Takashi Iwai98274f02005-11-17 14:52:34 +01001140 struct hdspm *hdspm = (struct hdspm *)arg;
Takashi Iwai763f3562005-06-03 11:25:34 +02001141
1142 if (hdspm->midi[0].pending)
1143 snd_hdspm_midi_input_read (&hdspm->midi[0]);
1144 if (hdspm->midi[1].pending)
1145 snd_hdspm_midi_input_read (&hdspm->midi[1]);
1146}
1147
1148
1149/*-----------------------------------------------------------------------------
1150 Status Interface
1151 ----------------------------------------------------------------------------*/
1152
1153/* get the system sample rate which is set */
1154
1155#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001156{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001157 .name = xname, \
1158 .index = xindex, \
1159 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1160 .info = snd_hdspm_info_system_sample_rate, \
1161 .get = snd_hdspm_get_system_sample_rate \
1162}
1163
Takashi Iwai98274f02005-11-17 14:52:34 +01001164static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
1165 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001166{
1167 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1168 uinfo->count = 1;
1169 return 0;
1170}
1171
Takashi Iwai98274f02005-11-17 14:52:34 +01001172static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
1173 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001174 ucontrol)
1175{
Takashi Iwai98274f02005-11-17 14:52:34 +01001176 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001177
1178 ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
1179 return 0;
1180}
1181
1182#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001183{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001184 .name = xname, \
1185 .index = xindex, \
1186 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1187 .info = snd_hdspm_info_autosync_sample_rate, \
1188 .get = snd_hdspm_get_autosync_sample_rate \
1189}
1190
Takashi Iwai98274f02005-11-17 14:52:34 +01001191static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1192 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001193{
1194 static char *texts[] = { "32000", "44100", "48000",
1195 "64000", "88200", "96000",
1196 "128000", "176400", "192000",
1197 "None"
1198 };
1199 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1200 uinfo->count = 1;
1201 uinfo->value.enumerated.items = 10;
1202 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1203 uinfo->value.enumerated.item =
1204 uinfo->value.enumerated.items - 1;
1205 strcpy(uinfo->value.enumerated.name,
1206 texts[uinfo->value.enumerated.item]);
1207 return 0;
1208}
1209
Takashi Iwai98274f02005-11-17 14:52:34 +01001210static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
1211 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02001212 ucontrol)
1213{
Takashi Iwai98274f02005-11-17 14:52:34 +01001214 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001215
1216 switch (hdspm_external_sample_rate(hdspm)) {
1217 case 32000:
1218 ucontrol->value.enumerated.item[0] = 0;
1219 break;
1220 case 44100:
1221 ucontrol->value.enumerated.item[0] = 1;
1222 break;
1223 case 48000:
1224 ucontrol->value.enumerated.item[0] = 2;
1225 break;
1226 case 64000:
1227 ucontrol->value.enumerated.item[0] = 3;
1228 break;
1229 case 88200:
1230 ucontrol->value.enumerated.item[0] = 4;
1231 break;
1232 case 96000:
1233 ucontrol->value.enumerated.item[0] = 5;
1234 break;
1235 case 128000:
1236 ucontrol->value.enumerated.item[0] = 6;
1237 break;
1238 case 176400:
1239 ucontrol->value.enumerated.item[0] = 7;
1240 break;
1241 case 192000:
1242 ucontrol->value.enumerated.item[0] = 8;
1243 break;
1244
1245 default:
1246 ucontrol->value.enumerated.item[0] = 9;
1247 }
1248 return 0;
1249}
1250
1251#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001252{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001253 .name = xname, \
1254 .index = xindex, \
1255 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1256 .info = snd_hdspm_info_system_clock_mode, \
1257 .get = snd_hdspm_get_system_clock_mode, \
1258}
1259
1260
1261
Takashi Iwai98274f02005-11-17 14:52:34 +01001262static int hdspm_system_clock_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001263{
1264 /* Always reflect the hardware info, rme is never wrong !!!! */
1265
1266 if (hdspm->control_register & HDSPM_ClockModeMaster)
1267 return 0;
1268 return 1;
1269}
1270
Takashi Iwai98274f02005-11-17 14:52:34 +01001271static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
1272 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001273{
1274 static char *texts[] = { "Master", "Slave" };
1275
1276 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1277 uinfo->count = 1;
1278 uinfo->value.enumerated.items = 2;
1279 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1280 uinfo->value.enumerated.item =
1281 uinfo->value.enumerated.items - 1;
1282 strcpy(uinfo->value.enumerated.name,
1283 texts[uinfo->value.enumerated.item]);
1284 return 0;
1285}
1286
Takashi Iwai98274f02005-11-17 14:52:34 +01001287static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
1288 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001289{
Takashi Iwai98274f02005-11-17 14:52:34 +01001290 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001291
1292 ucontrol->value.enumerated.item[0] =
1293 hdspm_system_clock_mode(hdspm);
1294 return 0;
1295}
1296
1297#define HDSPM_CLOCK_SOURCE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001298{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001299 .name = xname, \
1300 .index = xindex, \
1301 .info = snd_hdspm_info_clock_source, \
1302 .get = snd_hdspm_get_clock_source, \
1303 .put = snd_hdspm_put_clock_source \
1304}
1305
Takashi Iwai98274f02005-11-17 14:52:34 +01001306static int hdspm_clock_source(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001307{
1308 if (hdspm->control_register & HDSPM_ClockModeMaster) {
1309 switch (hdspm->system_sample_rate) {
1310 case 32000:
1311 return 1;
1312 case 44100:
1313 return 2;
1314 case 48000:
1315 return 3;
1316 case 64000:
1317 return 4;
1318 case 88200:
1319 return 5;
1320 case 96000:
1321 return 6;
1322 case 128000:
1323 return 7;
1324 case 176400:
1325 return 8;
1326 case 192000:
1327 return 9;
1328 default:
1329 return 3;
1330 }
1331 } else {
1332 return 0;
1333 }
1334}
1335
Takashi Iwai98274f02005-11-17 14:52:34 +01001336static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
Takashi Iwai763f3562005-06-03 11:25:34 +02001337{
1338 int rate;
1339 switch (mode) {
1340
1341 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
1342 if (hdspm_external_sample_rate(hdspm) != 0) {
1343 hdspm->control_register &= ~HDSPM_ClockModeMaster;
1344 hdspm_write(hdspm, HDSPM_controlRegister,
1345 hdspm->control_register);
1346 return 0;
1347 }
1348 return -1;
1349 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
1350 rate = 32000;
1351 break;
1352 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
1353 rate = 44100;
1354 break;
1355 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
1356 rate = 48000;
1357 break;
1358 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
1359 rate = 64000;
1360 break;
1361 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
1362 rate = 88200;
1363 break;
1364 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
1365 rate = 96000;
1366 break;
1367 case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
1368 rate = 128000;
1369 break;
1370 case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
1371 rate = 176400;
1372 break;
1373 case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
1374 rate = 192000;
1375 break;
1376
1377 default:
1378 rate = 44100;
1379 }
1380 hdspm->control_register |= HDSPM_ClockModeMaster;
1381 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1382 hdspm_set_rate(hdspm, rate, 1);
1383 return 0;
1384}
1385
Takashi Iwai98274f02005-11-17 14:52:34 +01001386static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
1387 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001388{
1389 static char *texts[] = { "AutoSync",
1390 "Internal 32.0 kHz", "Internal 44.1 kHz",
1391 "Internal 48.0 kHz",
1392 "Internal 64.0 kHz", "Internal 88.2 kHz",
1393 "Internal 96.0 kHz",
1394 "Internal 128.0 kHz", "Internal 176.4 kHz",
1395 "Internal 192.0 kHz"
1396 };
1397
1398 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1399 uinfo->count = 1;
1400 uinfo->value.enumerated.items = 10;
1401
1402 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1403 uinfo->value.enumerated.item =
1404 uinfo->value.enumerated.items - 1;
1405
1406 strcpy(uinfo->value.enumerated.name,
1407 texts[uinfo->value.enumerated.item]);
1408
1409 return 0;
1410}
1411
Takashi Iwai98274f02005-11-17 14:52:34 +01001412static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
1413 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001414{
Takashi Iwai98274f02005-11-17 14:52:34 +01001415 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001416
1417 ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
1418 return 0;
1419}
1420
Takashi Iwai98274f02005-11-17 14:52:34 +01001421static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
1422 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001423{
Takashi Iwai98274f02005-11-17 14:52:34 +01001424 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001425 int change;
1426 int val;
1427
1428 if (!snd_hdspm_use_is_exclusive(hdspm))
1429 return -EBUSY;
1430 val = ucontrol->value.enumerated.item[0];
1431 if (val < 0)
1432 val = 0;
1433 if (val > 6)
1434 val = 6;
1435 spin_lock_irq(&hdspm->lock);
1436 if (val != hdspm_clock_source(hdspm))
1437 change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
1438 else
1439 change = 0;
1440 spin_unlock_irq(&hdspm->lock);
1441 return change;
1442}
1443
1444#define HDSPM_PREF_SYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001445{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001446 .name = xname, \
1447 .index = xindex, \
1448 .info = snd_hdspm_info_pref_sync_ref, \
1449 .get = snd_hdspm_get_pref_sync_ref, \
1450 .put = snd_hdspm_put_pref_sync_ref \
1451}
1452
Takashi Iwai98274f02005-11-17 14:52:34 +01001453static int hdspm_pref_sync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001454{
1455 /* Notice that this looks at the requested sync source,
1456 not the one actually in use.
1457 */
1458 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1459 case HDSPM_SyncRef_Word:
1460 return HDSPM_SYNC_FROM_WORD;
1461 case HDSPM_SyncRef_MADI:
1462 return HDSPM_SYNC_FROM_MADI;
1463 }
1464
1465 return HDSPM_SYNC_FROM_WORD;
1466}
1467
Takashi Iwai98274f02005-11-17 14:52:34 +01001468static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
Takashi Iwai763f3562005-06-03 11:25:34 +02001469{
1470 hdspm->control_register &= ~HDSPM_SyncRefMask;
1471
1472 switch (pref) {
1473 case HDSPM_SYNC_FROM_MADI:
1474 hdspm->control_register |= HDSPM_SyncRef_MADI;
1475 break;
1476 case HDSPM_SYNC_FROM_WORD:
1477 hdspm->control_register |= HDSPM_SyncRef_Word;
1478 break;
1479 default:
1480 return -1;
1481 }
1482 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1483 return 0;
1484}
1485
Takashi Iwai98274f02005-11-17 14:52:34 +01001486static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
1487 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001488{
1489 static char *texts[] = { "Word", "MADI" };
1490
1491 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1492 uinfo->count = 1;
1493
1494 uinfo->value.enumerated.items = 2;
1495
1496 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1497 uinfo->value.enumerated.item =
1498 uinfo->value.enumerated.items - 1;
1499 strcpy(uinfo->value.enumerated.name,
1500 texts[uinfo->value.enumerated.item]);
1501 return 0;
1502}
1503
Takashi Iwai98274f02005-11-17 14:52:34 +01001504static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
1505 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001506{
Takashi Iwai98274f02005-11-17 14:52:34 +01001507 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001508
1509 ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
1510 return 0;
1511}
1512
Takashi Iwai98274f02005-11-17 14:52:34 +01001513static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
1514 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001515{
Takashi Iwai98274f02005-11-17 14:52:34 +01001516 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001517 int change, max;
1518 unsigned int val;
1519
1520 max = 2;
1521
1522 if (!snd_hdspm_use_is_exclusive(hdspm))
1523 return -EBUSY;
1524
1525 val = ucontrol->value.enumerated.item[0] % max;
1526
1527 spin_lock_irq(&hdspm->lock);
1528 change = (int) val != hdspm_pref_sync_ref(hdspm);
1529 hdspm_set_pref_sync_ref(hdspm, val);
1530 spin_unlock_irq(&hdspm->lock);
1531 return change;
1532}
1533
1534#define HDSPM_AUTOSYNC_REF(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001535{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001536 .name = xname, \
1537 .index = xindex, \
1538 .access = SNDRV_CTL_ELEM_ACCESS_READ, \
1539 .info = snd_hdspm_info_autosync_ref, \
1540 .get = snd_hdspm_get_autosync_ref, \
1541}
1542
Takashi Iwai98274f02005-11-17 14:52:34 +01001543static int hdspm_autosync_ref(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001544{
1545 /* This looks at the autosync selected sync reference */
1546 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1547
1548 switch (status2 & HDSPM_SelSyncRefMask) {
1549
1550 case HDSPM_SelSyncRef_WORD:
1551 return HDSPM_AUTOSYNC_FROM_WORD;
1552
1553 case HDSPM_SelSyncRef_MADI:
1554 return HDSPM_AUTOSYNC_FROM_MADI;
1555
1556 case HDSPM_SelSyncRef_NVALID:
1557 return HDSPM_AUTOSYNC_FROM_NONE;
1558
1559 default:
1560 return 0;
1561 }
1562
1563 return 0;
1564}
1565
Takashi Iwai98274f02005-11-17 14:52:34 +01001566static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
1567 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001568{
1569 static char *texts[] = { "WordClock", "MADI", "None" };
1570
1571 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1572 uinfo->count = 1;
1573 uinfo->value.enumerated.items = 3;
1574 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1575 uinfo->value.enumerated.item =
1576 uinfo->value.enumerated.items - 1;
1577 strcpy(uinfo->value.enumerated.name,
1578 texts[uinfo->value.enumerated.item]);
1579 return 0;
1580}
1581
Takashi Iwai98274f02005-11-17 14:52:34 +01001582static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
1583 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001584{
Takashi Iwai98274f02005-11-17 14:52:34 +01001585 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001586
1587 ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
1588 return 0;
1589}
1590
1591#define HDSPM_LINE_OUT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001592{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001593 .name = xname, \
1594 .index = xindex, \
1595 .info = snd_hdspm_info_line_out, \
1596 .get = snd_hdspm_get_line_out, \
1597 .put = snd_hdspm_put_line_out \
1598}
1599
Takashi Iwai98274f02005-11-17 14:52:34 +01001600static int hdspm_line_out(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001601{
1602 return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
1603}
1604
1605
Takashi Iwai98274f02005-11-17 14:52:34 +01001606static int hdspm_set_line_output(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001607{
1608 if (out)
1609 hdspm->control_register |= HDSPM_LineOut;
1610 else
1611 hdspm->control_register &= ~HDSPM_LineOut;
1612 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1613
1614 return 0;
1615}
1616
Takashi Iwai98274f02005-11-17 14:52:34 +01001617static int snd_hdspm_info_line_out(struct snd_kcontrol *kcontrol,
1618 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001619{
1620 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1621 uinfo->count = 1;
1622 uinfo->value.integer.min = 0;
1623 uinfo->value.integer.max = 1;
1624 return 0;
1625}
1626
Takashi Iwai98274f02005-11-17 14:52:34 +01001627static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
1628 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001629{
Takashi Iwai98274f02005-11-17 14:52:34 +01001630 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001631
1632 spin_lock_irq(&hdspm->lock);
1633 ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
1634 spin_unlock_irq(&hdspm->lock);
1635 return 0;
1636}
1637
Takashi Iwai98274f02005-11-17 14:52:34 +01001638static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
1639 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001640{
Takashi Iwai98274f02005-11-17 14:52:34 +01001641 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001642 int change;
1643 unsigned int val;
1644
1645 if (!snd_hdspm_use_is_exclusive(hdspm))
1646 return -EBUSY;
1647 val = ucontrol->value.integer.value[0] & 1;
1648 spin_lock_irq(&hdspm->lock);
1649 change = (int) val != hdspm_line_out(hdspm);
1650 hdspm_set_line_output(hdspm, val);
1651 spin_unlock_irq(&hdspm->lock);
1652 return change;
1653}
1654
1655#define HDSPM_TX_64(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001656{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001657 .name = xname, \
1658 .index = xindex, \
1659 .info = snd_hdspm_info_tx_64, \
1660 .get = snd_hdspm_get_tx_64, \
1661 .put = snd_hdspm_put_tx_64 \
1662}
1663
Takashi Iwai98274f02005-11-17 14:52:34 +01001664static int hdspm_tx_64(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001665{
1666 return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
1667}
1668
Takashi Iwai98274f02005-11-17 14:52:34 +01001669static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001670{
1671 if (out)
1672 hdspm->control_register |= HDSPM_TX_64ch;
1673 else
1674 hdspm->control_register &= ~HDSPM_TX_64ch;
1675 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1676
1677 return 0;
1678}
1679
Takashi Iwai98274f02005-11-17 14:52:34 +01001680static int snd_hdspm_info_tx_64(struct snd_kcontrol *kcontrol,
1681 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001682{
1683 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1684 uinfo->count = 1;
1685 uinfo->value.integer.min = 0;
1686 uinfo->value.integer.max = 1;
1687 return 0;
1688}
1689
Takashi Iwai98274f02005-11-17 14:52:34 +01001690static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
1691 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001692{
Takashi Iwai98274f02005-11-17 14:52:34 +01001693 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001694
1695 spin_lock_irq(&hdspm->lock);
1696 ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
1697 spin_unlock_irq(&hdspm->lock);
1698 return 0;
1699}
1700
Takashi Iwai98274f02005-11-17 14:52:34 +01001701static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
1702 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001703{
Takashi Iwai98274f02005-11-17 14:52:34 +01001704 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001705 int change;
1706 unsigned int val;
1707
1708 if (!snd_hdspm_use_is_exclusive(hdspm))
1709 return -EBUSY;
1710 val = ucontrol->value.integer.value[0] & 1;
1711 spin_lock_irq(&hdspm->lock);
1712 change = (int) val != hdspm_tx_64(hdspm);
1713 hdspm_set_tx_64(hdspm, val);
1714 spin_unlock_irq(&hdspm->lock);
1715 return change;
1716}
1717
1718#define HDSPM_C_TMS(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001719{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001720 .name = xname, \
1721 .index = xindex, \
1722 .info = snd_hdspm_info_c_tms, \
1723 .get = snd_hdspm_get_c_tms, \
1724 .put = snd_hdspm_put_c_tms \
1725}
1726
Takashi Iwai98274f02005-11-17 14:52:34 +01001727static int hdspm_c_tms(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001728{
1729 return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
1730}
1731
Takashi Iwai98274f02005-11-17 14:52:34 +01001732static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001733{
1734 if (out)
1735 hdspm->control_register |= HDSPM_clr_tms;
1736 else
1737 hdspm->control_register &= ~HDSPM_clr_tms;
1738 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1739
1740 return 0;
1741}
1742
Takashi Iwai98274f02005-11-17 14:52:34 +01001743static int snd_hdspm_info_c_tms(struct snd_kcontrol *kcontrol,
1744 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001745{
1746 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1747 uinfo->count = 1;
1748 uinfo->value.integer.min = 0;
1749 uinfo->value.integer.max = 1;
1750 return 0;
1751}
1752
Takashi Iwai98274f02005-11-17 14:52:34 +01001753static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
1754 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001755{
Takashi Iwai98274f02005-11-17 14:52:34 +01001756 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001757
1758 spin_lock_irq(&hdspm->lock);
1759 ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
1760 spin_unlock_irq(&hdspm->lock);
1761 return 0;
1762}
1763
Takashi Iwai98274f02005-11-17 14:52:34 +01001764static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
1765 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001766{
Takashi Iwai98274f02005-11-17 14:52:34 +01001767 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001768 int change;
1769 unsigned int val;
1770
1771 if (!snd_hdspm_use_is_exclusive(hdspm))
1772 return -EBUSY;
1773 val = ucontrol->value.integer.value[0] & 1;
1774 spin_lock_irq(&hdspm->lock);
1775 change = (int) val != hdspm_c_tms(hdspm);
1776 hdspm_set_c_tms(hdspm, val);
1777 spin_unlock_irq(&hdspm->lock);
1778 return change;
1779}
1780
1781#define HDSPM_SAFE_MODE(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001782{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001783 .name = xname, \
1784 .index = xindex, \
1785 .info = snd_hdspm_info_safe_mode, \
1786 .get = snd_hdspm_get_safe_mode, \
1787 .put = snd_hdspm_put_safe_mode \
1788}
1789
Takashi Iwai98274f02005-11-17 14:52:34 +01001790static int hdspm_safe_mode(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001791{
1792 return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
1793}
1794
Takashi Iwai98274f02005-11-17 14:52:34 +01001795static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001796{
1797 if (out)
1798 hdspm->control_register |= HDSPM_AutoInp;
1799 else
1800 hdspm->control_register &= ~HDSPM_AutoInp;
1801 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1802
1803 return 0;
1804}
1805
Takashi Iwai98274f02005-11-17 14:52:34 +01001806static int snd_hdspm_info_safe_mode(struct snd_kcontrol *kcontrol,
1807 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001808{
1809 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1810 uinfo->count = 1;
1811 uinfo->value.integer.min = 0;
1812 uinfo->value.integer.max = 1;
1813 return 0;
1814}
1815
Takashi Iwai98274f02005-11-17 14:52:34 +01001816static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
1817 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001818{
Takashi Iwai98274f02005-11-17 14:52:34 +01001819 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001820
1821 spin_lock_irq(&hdspm->lock);
1822 ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
1823 spin_unlock_irq(&hdspm->lock);
1824 return 0;
1825}
1826
Takashi Iwai98274f02005-11-17 14:52:34 +01001827static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
1828 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001829{
Takashi Iwai98274f02005-11-17 14:52:34 +01001830 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001831 int change;
1832 unsigned int val;
1833
1834 if (!snd_hdspm_use_is_exclusive(hdspm))
1835 return -EBUSY;
1836 val = ucontrol->value.integer.value[0] & 1;
1837 spin_lock_irq(&hdspm->lock);
1838 change = (int) val != hdspm_safe_mode(hdspm);
1839 hdspm_set_safe_mode(hdspm, val);
1840 spin_unlock_irq(&hdspm->lock);
1841 return change;
1842}
1843
1844#define HDSPM_INPUT_SELECT(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001845{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001846 .name = xname, \
1847 .index = xindex, \
1848 .info = snd_hdspm_info_input_select, \
1849 .get = snd_hdspm_get_input_select, \
1850 .put = snd_hdspm_put_input_select \
1851}
1852
Takashi Iwai98274f02005-11-17 14:52:34 +01001853static int hdspm_input_select(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02001854{
1855 return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
1856}
1857
Takashi Iwai98274f02005-11-17 14:52:34 +01001858static int hdspm_set_input_select(struct hdspm * hdspm, int out)
Takashi Iwai763f3562005-06-03 11:25:34 +02001859{
1860 if (out)
1861 hdspm->control_register |= HDSPM_InputSelect0;
1862 else
1863 hdspm->control_register &= ~HDSPM_InputSelect0;
1864 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1865
1866 return 0;
1867}
1868
Takashi Iwai98274f02005-11-17 14:52:34 +01001869static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
1870 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001871{
1872 static char *texts[] = { "optical", "coaxial" };
1873
1874 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1875 uinfo->count = 1;
1876 uinfo->value.enumerated.items = 2;
1877
1878 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1879 uinfo->value.enumerated.item =
1880 uinfo->value.enumerated.items - 1;
1881 strcpy(uinfo->value.enumerated.name,
1882 texts[uinfo->value.enumerated.item]);
1883
1884 return 0;
1885}
1886
Takashi Iwai98274f02005-11-17 14:52:34 +01001887static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
1888 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001889{
Takashi Iwai98274f02005-11-17 14:52:34 +01001890 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001891
1892 spin_lock_irq(&hdspm->lock);
1893 ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
1894 spin_unlock_irq(&hdspm->lock);
1895 return 0;
1896}
1897
Takashi Iwai98274f02005-11-17 14:52:34 +01001898static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
1899 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001900{
Takashi Iwai98274f02005-11-17 14:52:34 +01001901 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001902 int change;
1903 unsigned int val;
1904
1905 if (!snd_hdspm_use_is_exclusive(hdspm))
1906 return -EBUSY;
1907 val = ucontrol->value.integer.value[0] & 1;
1908 spin_lock_irq(&hdspm->lock);
1909 change = (int) val != hdspm_input_select(hdspm);
1910 hdspm_set_input_select(hdspm, val);
1911 spin_unlock_irq(&hdspm->lock);
1912 return change;
1913}
1914
1915/* Simple Mixer
1916 deprecated since to much faders ???
1917 MIXER interface says output (source, destination, value)
1918 where source > MAX_channels are playback channels
1919 on MADICARD
1920 - playback mixer matrix: [channelout+64] [output] [value]
1921 - input(thru) mixer matrix: [channelin] [output] [value]
1922 (better do 2 kontrols for seperation ?)
1923*/
1924
1925#define HDSPM_MIXER(xname, xindex) \
1926{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
1927 .name = xname, \
1928 .index = xindex, \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001929 .device = 0, \
Takashi Iwai763f3562005-06-03 11:25:34 +02001930 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1931 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
1932 .info = snd_hdspm_info_mixer, \
1933 .get = snd_hdspm_get_mixer, \
1934 .put = snd_hdspm_put_mixer \
1935}
1936
Takashi Iwai98274f02005-11-17 14:52:34 +01001937static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
1938 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02001939{
1940 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1941 uinfo->count = 3;
1942 uinfo->value.integer.min = 0;
1943 uinfo->value.integer.max = 65535;
1944 uinfo->value.integer.step = 1;
1945 return 0;
1946}
1947
Takashi Iwai98274f02005-11-17 14:52:34 +01001948static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
1949 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001950{
Takashi Iwai98274f02005-11-17 14:52:34 +01001951 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001952 int source;
1953 int destination;
1954
1955 source = ucontrol->value.integer.value[0];
1956 if (source < 0)
1957 source = 0;
1958 else if (source >= 2 * HDSPM_MAX_CHANNELS)
1959 source = 2 * HDSPM_MAX_CHANNELS - 1;
1960
1961 destination = ucontrol->value.integer.value[1];
1962 if (destination < 0)
1963 destination = 0;
1964 else if (destination >= HDSPM_MAX_CHANNELS)
1965 destination = HDSPM_MAX_CHANNELS - 1;
1966
1967 spin_lock_irq(&hdspm->lock);
1968 if (source >= HDSPM_MAX_CHANNELS)
1969 ucontrol->value.integer.value[2] =
1970 hdspm_read_pb_gain(hdspm, destination,
1971 source - HDSPM_MAX_CHANNELS);
1972 else
1973 ucontrol->value.integer.value[2] =
1974 hdspm_read_in_gain(hdspm, destination, source);
1975
1976 spin_unlock_irq(&hdspm->lock);
1977
1978 return 0;
1979}
1980
Takashi Iwai98274f02005-11-17 14:52:34 +01001981static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
1982 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02001983{
Takashi Iwai98274f02005-11-17 14:52:34 +01001984 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02001985 int change;
1986 int source;
1987 int destination;
1988 int gain;
1989
1990 if (!snd_hdspm_use_is_exclusive(hdspm))
1991 return -EBUSY;
1992
1993 source = ucontrol->value.integer.value[0];
1994 destination = ucontrol->value.integer.value[1];
1995
1996 if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
1997 return -1;
1998 if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
1999 return -1;
2000
2001 gain = ucontrol->value.integer.value[2];
2002
2003 spin_lock_irq(&hdspm->lock);
2004
2005 if (source >= HDSPM_MAX_CHANNELS)
2006 change = gain != hdspm_read_pb_gain(hdspm, destination,
2007 source -
2008 HDSPM_MAX_CHANNELS);
2009 else
2010 change =
2011 gain != hdspm_read_in_gain(hdspm, destination, source);
2012
2013 if (change) {
2014 if (source >= HDSPM_MAX_CHANNELS)
2015 hdspm_write_pb_gain(hdspm, destination,
2016 source - HDSPM_MAX_CHANNELS,
2017 gain);
2018 else
2019 hdspm_write_in_gain(hdspm, destination, source,
2020 gain);
2021 }
2022 spin_unlock_irq(&hdspm->lock);
2023
2024 return change;
2025}
2026
2027/* The simple mixer control(s) provide gain control for the
2028 basic 1:1 mappings of playback streams to output
2029 streams.
2030*/
2031
2032#define HDSPM_PLAYBACK_MIXER \
2033{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2034 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
2035 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2036 .info = snd_hdspm_info_playback_mixer, \
2037 .get = snd_hdspm_get_playback_mixer, \
2038 .put = snd_hdspm_put_playback_mixer \
2039}
2040
Takashi Iwai98274f02005-11-17 14:52:34 +01002041static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
2042 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002043{
2044 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2045 uinfo->count = 1;
2046 uinfo->value.integer.min = 0;
2047 uinfo->value.integer.max = 65536;
2048 uinfo->value.integer.step = 1;
2049 return 0;
2050}
2051
Takashi Iwai98274f02005-11-17 14:52:34 +01002052static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
2053 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002054{
Takashi Iwai98274f02005-11-17 14:52:34 +01002055 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002056 int channel;
2057 int mapped_channel;
2058
2059 channel = ucontrol->id.index - 1;
2060
2061 snd_assert(channel >= 0
2062 || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
2063
2064 if ((mapped_channel = hdspm->channel_map[channel]) < 0)
2065 return -EINVAL;
2066
2067 spin_lock_irq(&hdspm->lock);
2068 ucontrol->value.integer.value[0] =
2069 hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
2070 spin_unlock_irq(&hdspm->lock);
2071
2072 /* snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n",
2073 ucontrol->id.index, channel, mapped_channel, ucontrol->value.integer.value[0]);
2074 */
2075
2076 return 0;
2077}
2078
Takashi Iwai98274f02005-11-17 14:52:34 +01002079static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
2080 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002081{
Takashi Iwai98274f02005-11-17 14:52:34 +01002082 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002083 int change;
2084 int channel;
2085 int mapped_channel;
2086 int gain;
2087
2088 if (!snd_hdspm_use_is_exclusive(hdspm))
2089 return -EBUSY;
2090
2091 channel = ucontrol->id.index - 1;
2092
2093 snd_assert(channel >= 0
2094 || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
2095
2096 if ((mapped_channel = hdspm->channel_map[channel]) < 0)
2097 return -EINVAL;
2098
2099 gain = ucontrol->value.integer.value[0];
2100
2101 spin_lock_irq(&hdspm->lock);
2102 change =
2103 gain != hdspm_read_pb_gain(hdspm, mapped_channel,
2104 mapped_channel);
2105 if (change)
2106 hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,
2107 gain);
2108 spin_unlock_irq(&hdspm->lock);
2109 return change;
2110}
2111
2112#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002113{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002114 .name = xname, \
2115 .index = xindex, \
2116 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2117 .info = snd_hdspm_info_sync_check, \
2118 .get = snd_hdspm_get_wc_sync_check \
2119}
2120
Takashi Iwai98274f02005-11-17 14:52:34 +01002121static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
2122 struct snd_ctl_elem_info *uinfo)
Takashi Iwai763f3562005-06-03 11:25:34 +02002123{
2124 static char *texts[] = { "No Lock", "Lock", "Sync" };
2125 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2126 uinfo->count = 1;
2127 uinfo->value.enumerated.items = 3;
2128 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2129 uinfo->value.enumerated.item =
2130 uinfo->value.enumerated.items - 1;
2131 strcpy(uinfo->value.enumerated.name,
2132 texts[uinfo->value.enumerated.item]);
2133 return 0;
2134}
2135
Takashi Iwai98274f02005-11-17 14:52:34 +01002136static int hdspm_wc_sync_check(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002137{
2138 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2139 if (status2 & HDSPM_wcLock) {
2140 if (status2 & HDSPM_wcSync)
2141 return 2;
2142 else
2143 return 1;
2144 }
2145 return 0;
2146}
2147
Takashi Iwai98274f02005-11-17 14:52:34 +01002148static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol,
2149 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai763f3562005-06-03 11:25:34 +02002150{
Takashi Iwai98274f02005-11-17 14:52:34 +01002151 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002152
2153 ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
2154 return 0;
2155}
2156
2157
2158#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002159{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
Takashi Iwai763f3562005-06-03 11:25:34 +02002160 .name = xname, \
2161 .index = xindex, \
2162 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2163 .info = snd_hdspm_info_sync_check, \
2164 .get = snd_hdspm_get_madisync_sync_check \
2165}
2166
Takashi Iwai98274f02005-11-17 14:52:34 +01002167static int hdspm_madisync_sync_check(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002168{
2169 int status = hdspm_read(hdspm, HDSPM_statusRegister);
2170 if (status & HDSPM_madiLock) {
2171 if (status & HDSPM_madiSync)
2172 return 2;
2173 else
2174 return 1;
2175 }
2176 return 0;
2177}
2178
Takashi Iwai98274f02005-11-17 14:52:34 +01002179static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol,
2180 struct snd_ctl_elem_value *
Takashi Iwai763f3562005-06-03 11:25:34 +02002181 ucontrol)
2182{
Takashi Iwai98274f02005-11-17 14:52:34 +01002183 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
Takashi Iwai763f3562005-06-03 11:25:34 +02002184
2185 ucontrol->value.enumerated.item[0] =
2186 hdspm_madisync_sync_check(hdspm);
2187 return 0;
2188}
2189
2190
2191
2192
Takashi Iwai98274f02005-11-17 14:52:34 +01002193static struct snd_kcontrol_new snd_hdspm_controls[] = {
Takashi Iwai763f3562005-06-03 11:25:34 +02002194
2195 HDSPM_MIXER("Mixer", 0),
2196/* 'Sample Clock Source' complies with the alsa control naming scheme */
2197 HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
2198
2199 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2200 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
2201 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
2202 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2203/* 'External Rate' complies with the alsa control naming scheme */
2204 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2205 HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2206 HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),
2207 HDSPM_LINE_OUT("Line Out", 0),
2208 HDSPM_TX_64("TX 64 channels mode", 0),
2209 HDSPM_C_TMS("Clear Track Marker", 0),
2210 HDSPM_SAFE_MODE("Safe Mode", 0),
2211 HDSPM_INPUT_SELECT("Input Select", 0),
2212};
2213
Takashi Iwai98274f02005-11-17 14:52:34 +01002214static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
Takashi Iwai763f3562005-06-03 11:25:34 +02002215
2216
Takashi Iwai98274f02005-11-17 14:52:34 +01002217static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002218{
2219 int i;
2220
2221 for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {
2222 if (hdspm->system_sample_rate > 48000) {
2223 hdspm->playback_mixer_ctls[i]->vd[0].access =
2224 SNDRV_CTL_ELEM_ACCESS_INACTIVE |
2225 SNDRV_CTL_ELEM_ACCESS_READ |
2226 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
2227 } else {
2228 hdspm->playback_mixer_ctls[i]->vd[0].access =
2229 SNDRV_CTL_ELEM_ACCESS_READWRITE |
2230 SNDRV_CTL_ELEM_ACCESS_VOLATILE;
2231 }
2232 snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
2233 SNDRV_CTL_EVENT_MASK_INFO,
2234 &hdspm->playback_mixer_ctls[i]->id);
2235 }
2236
2237 return 0;
2238}
2239
2240
Takashi Iwai98274f02005-11-17 14:52:34 +01002241static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002242{
2243 unsigned int idx, limit;
2244 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01002245 struct snd_kcontrol *kctl;
Takashi Iwai763f3562005-06-03 11:25:34 +02002246
2247 /* add control list first */
2248
2249 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) {
2250 if ((err =
2251 snd_ctl_add(card, kctl =
2252 snd_ctl_new1(&snd_hdspm_controls[idx],
2253 hdspm))) < 0) {
2254 return err;
2255 }
2256 }
2257
2258 /* Channel playback mixer as default control
Alexey Dobriyan7f927fc2006-03-28 01:56:53 -08002259 Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer
Takashi Iwai763f3562005-06-03 11:25:34 +02002260 they are accesible via special IOCTL on hwdep
2261 and the mixer 2dimensional mixer control */
2262
2263 snd_hdspm_playback_mixer.name = "Chn";
2264 limit = HDSPM_MAX_CHANNELS;
2265
2266 /* The index values are one greater than the channel ID so that alsamixer
2267 will display them correctly. We want to use the index for fast lookup
2268 of the relevant channel, but if we use it at all, most ALSA software
2269 does the wrong thing with it ...
2270 */
2271
2272 for (idx = 0; idx < limit; ++idx) {
2273 snd_hdspm_playback_mixer.index = idx + 1;
2274 if ((err = snd_ctl_add(card,
2275 kctl =
2276 snd_ctl_new1
2277 (&snd_hdspm_playback_mixer,
2278 hdspm)))) {
2279 return err;
2280 }
2281 hdspm->playback_mixer_ctls[idx] = kctl;
2282 }
2283
2284 return 0;
2285}
2286
2287/*------------------------------------------------------------
2288 /proc interface
2289 ------------------------------------------------------------*/
2290
2291static void
Takashi Iwai98274f02005-11-17 14:52:34 +01002292snd_hdspm_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer)
Takashi Iwai763f3562005-06-03 11:25:34 +02002293{
Takashi Iwai98274f02005-11-17 14:52:34 +01002294 struct hdspm *hdspm = (struct hdspm *) entry->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02002295 unsigned int status;
2296 unsigned int status2;
2297 char *pref_sync_ref;
2298 char *autosync_ref;
2299 char *system_clock_mode;
2300 char *clock_source;
2301 char *insel;
2302 char *syncref;
2303 int x, x2;
2304
2305 status = hdspm_read(hdspm, HDSPM_statusRegister);
2306 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2307
2308 snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
2309 hdspm->card_name, hdspm->card->number + 1,
2310 hdspm->firmware_rev,
2311 (status2 & HDSPM_version0) |
2312 (status2 & HDSPM_version1) | (status2 &
2313 HDSPM_version2));
2314
2315 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
2316 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
2317
2318 snd_iprintf(buffer, "--- System ---\n");
2319
2320 snd_iprintf(buffer,
2321 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
2322 status & HDSPM_audioIRQPending,
2323 (status & HDSPM_midi0IRQPending) ? 1 : 0,
2324 (status & HDSPM_midi1IRQPending) ? 1 : 0,
2325 hdspm->irq_count);
2326 snd_iprintf(buffer,
2327 "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
2328 ((status & HDSPM_BufferID) ? 1 : 0),
2329 (status & HDSPM_BufferPositionMask),
2330 (status & HDSPM_BufferPositionMask) % (2 *
2331 (int)hdspm->
2332 period_bytes),
2333 ((status & HDSPM_BufferPositionMask) -
2334 64) % (2 * (int)hdspm->period_bytes),
2335 (long) hdspm_hw_pointer(hdspm) * 4);
2336
2337 snd_iprintf(buffer,
2338 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
2339 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
2340 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
2341 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
2342 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
2343 snd_iprintf(buffer,
2344 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n",
2345 hdspm->control_register, hdspm->control2_register,
2346 status, status2);
2347
2348 snd_iprintf(buffer, "--- Settings ---\n");
2349
2350 x = 1 << (6 +
2351 hdspm_decode_latency(hdspm->
2352 control_register &
2353 HDSPM_LatencyMask));
2354
2355 snd_iprintf(buffer,
2356 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
2357 x, (unsigned long) hdspm->period_bytes);
2358
2359 snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
2360 (hdspm->
2361 control_register & HDSPM_LineOut) ? "on " : "off",
2362 (hdspm->precise_ptr) ? "on" : "off");
2363
2364 switch (hdspm->control_register & HDSPM_InputMask) {
2365 case HDSPM_InputOptical:
2366 insel = "Optical";
2367 break;
2368 case HDSPM_InputCoaxial:
2369 insel = "Coaxial";
2370 break;
2371 default:
2372 insel = "Unkown";
2373 }
2374
2375 switch (hdspm->control_register & HDSPM_SyncRefMask) {
2376 case HDSPM_SyncRef_Word:
2377 syncref = "WordClock";
2378 break;
2379 case HDSPM_SyncRef_MADI:
2380 syncref = "MADI";
2381 break;
2382 default:
2383 syncref = "Unkown";
2384 }
2385 snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel,
2386 syncref);
2387
2388 snd_iprintf(buffer,
2389 "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n",
2390 (hdspm->
2391 control_register & HDSPM_clr_tms) ? "on" : "off",
2392 (hdspm->
2393 control_register & HDSPM_TX_64ch) ? "64" : "56",
2394 (hdspm->
2395 control_register & HDSPM_AutoInp) ? "on" : "off");
2396
2397 switch (hdspm_clock_source(hdspm)) {
2398 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
2399 clock_source = "AutoSync";
2400 break;
2401 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
2402 clock_source = "Internal 32 kHz";
2403 break;
2404 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
2405 clock_source = "Internal 44.1 kHz";
2406 break;
2407 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
2408 clock_source = "Internal 48 kHz";
2409 break;
2410 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
2411 clock_source = "Internal 64 kHz";
2412 break;
2413 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
2414 clock_source = "Internal 88.2 kHz";
2415 break;
2416 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
2417 clock_source = "Internal 96 kHz";
2418 break;
2419 default:
2420 clock_source = "Error";
2421 }
2422 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
2423 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
2424 system_clock_mode = "Slave";
2425 } else {
2426 system_clock_mode = "Master";
2427 }
2428 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
2429
2430 switch (hdspm_pref_sync_ref(hdspm)) {
2431 case HDSPM_SYNC_FROM_WORD:
2432 pref_sync_ref = "Word Clock";
2433 break;
2434 case HDSPM_SYNC_FROM_MADI:
2435 pref_sync_ref = "MADI Sync";
2436 break;
2437 default:
2438 pref_sync_ref = "XXXX Clock";
2439 break;
2440 }
2441 snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
2442 pref_sync_ref);
2443
2444 snd_iprintf(buffer, "System Clock Frequency: %d\n",
2445 hdspm->system_sample_rate);
2446
2447
2448 snd_iprintf(buffer, "--- Status:\n");
2449
2450 x = status & HDSPM_madiSync;
2451 x2 = status2 & HDSPM_wcSync;
2452
2453 snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
2454 (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
2455 "NoLock",
2456 (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
2457 "NoLock");
2458
2459 switch (hdspm_autosync_ref(hdspm)) {
2460 case HDSPM_AUTOSYNC_FROM_WORD:
2461 autosync_ref = "Word Clock";
2462 break;
2463 case HDSPM_AUTOSYNC_FROM_MADI:
2464 autosync_ref = "MADI Sync";
2465 break;
2466 case HDSPM_AUTOSYNC_FROM_NONE:
2467 autosync_ref = "Input not valid";
2468 break;
2469 default:
2470 autosync_ref = "---";
2471 break;
2472 }
2473 snd_iprintf(buffer,
2474 "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
2475 autosync_ref, hdspm_external_sample_rate(hdspm),
2476 (status & HDSPM_madiFreqMask) >> 22,
2477 (status2 & HDSPM_wcFreqMask) >> 5);
2478
2479 snd_iprintf(buffer, "Input: %s, Mode=%s\n",
2480 (status & HDSPM_AB_int) ? "Coax" : "Optical",
2481 (status & HDSPM_RX_64ch) ? "64 channels" :
2482 "56 channels");
2483
2484 snd_iprintf(buffer, "\n");
2485}
2486
Takashi Iwai98274f02005-11-17 14:52:34 +01002487static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002488{
Takashi Iwai98274f02005-11-17 14:52:34 +01002489 struct snd_info_entry *entry;
Takashi Iwai763f3562005-06-03 11:25:34 +02002490
2491 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
Takashi Iwaibf850202006-04-28 15:13:41 +02002492 snd_info_set_text_ops(entry, hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02002493 snd_hdspm_proc_read);
2494}
2495
2496/*------------------------------------------------------------
2497 hdspm intitialize
2498 ------------------------------------------------------------*/
2499
Takashi Iwai98274f02005-11-17 14:52:34 +01002500static int snd_hdspm_set_defaults(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02002501{
2502 unsigned int i;
2503
2504 /* ASSUMPTION: hdspm->lock is either held, or there is no need to
2505 hold it (e.g. during module initalization).
2506 */
2507
2508 /* set defaults: */
2509
2510 hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
2511 hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
2512 HDSPM_InputCoaxial | /* Input Coax not Optical */
2513 HDSPM_SyncRef_MADI | /* Madi is syncclock */
2514 HDSPM_LineOut | /* Analog output in */
2515 HDSPM_TX_64ch | /* transmit in 64ch mode */
2516 HDSPM_AutoInp; /* AutoInput chossing (takeover) */
2517
2518 /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
2519 /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
2520 /* ! HDSPM_clr_tms = do not clear bits in track marks */
2521
2522 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2523
2524#ifdef SNDRV_BIG_ENDIAN
2525 hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
2526#else
2527 hdspm->control2_register = 0;
2528#endif
2529
2530 hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
2531 hdspm_compute_period_size(hdspm);
2532
2533 /* silence everything */
2534
2535 all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
2536
2537 if (line_outs_monitor[hdspm->dev]) {
2538
2539 snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n");
2540
2541 for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
2542 if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
2543 return -EIO;
2544 }
2545 }
2546
2547 /* set a default rate so that the channel map is set up. */
2548 hdspm->channel_map = channel_map_madi_ss;
2549 hdspm_set_rate(hdspm, 44100, 1);
2550
2551 return 0;
2552}
2553
2554
2555/*------------------------------------------------------------
2556 interupt
2557 ------------------------------------------------------------*/
2558
David Howells7d12e782006-10-05 14:55:46 +01002559static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
Takashi Iwai763f3562005-06-03 11:25:34 +02002560{
Takashi Iwai98274f02005-11-17 14:52:34 +01002561 struct hdspm *hdspm = (struct hdspm *) dev_id;
Takashi Iwai763f3562005-06-03 11:25:34 +02002562 unsigned int status;
2563 int audio;
2564 int midi0;
2565 int midi1;
2566 unsigned int midi0status;
2567 unsigned int midi1status;
2568 int schedule = 0;
2569
2570 status = hdspm_read(hdspm, HDSPM_statusRegister);
2571
2572 audio = status & HDSPM_audioIRQPending;
2573 midi0 = status & HDSPM_midi0IRQPending;
2574 midi1 = status & HDSPM_midi1IRQPending;
2575
2576 if (!audio && !midi0 && !midi1)
2577 return IRQ_NONE;
2578
2579 hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
2580 hdspm->irq_count++;
2581
2582 midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff;
2583 midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff;
2584
2585 if (audio) {
2586
2587 if (hdspm->capture_substream)
2588 snd_pcm_period_elapsed(hdspm->pcm->
2589 streams
2590 [SNDRV_PCM_STREAM_CAPTURE].
2591 substream);
2592
2593 if (hdspm->playback_substream)
2594 snd_pcm_period_elapsed(hdspm->pcm->
2595 streams
2596 [SNDRV_PCM_STREAM_PLAYBACK].
2597 substream);
2598 }
2599
2600 if (midi0 && midi0status) {
2601 /* we disable interrupts for this input until processing is done */
2602 hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
2603 hdspm_write(hdspm, HDSPM_controlRegister,
2604 hdspm->control_register);
2605 hdspm->midi[0].pending = 1;
2606 schedule = 1;
2607 }
2608 if (midi1 && midi1status) {
2609 /* we disable interrupts for this input until processing is done */
2610 hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
2611 hdspm_write(hdspm, HDSPM_controlRegister,
2612 hdspm->control_register);
2613 hdspm->midi[1].pending = 1;
2614 schedule = 1;
2615 }
2616 if (schedule)
2617 tasklet_hi_schedule(&hdspm->midi_tasklet);
2618 return IRQ_HANDLED;
2619}
2620
2621/*------------------------------------------------------------
2622 pcm interface
2623 ------------------------------------------------------------*/
2624
2625
Takashi Iwai98274f02005-11-17 14:52:34 +01002626static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream *
Takashi Iwai763f3562005-06-03 11:25:34 +02002627 substream)
2628{
Takashi Iwai98274f02005-11-17 14:52:34 +01002629 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02002630 return hdspm_hw_pointer(hdspm);
2631}
2632
Takashi Iwai98274f02005-11-17 14:52:34 +01002633static char *hdspm_channel_buffer_location(struct hdspm * hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02002634 int stream, int channel)
2635{
2636 int mapped_channel;
2637
2638 snd_assert(channel >= 0
2639 || channel < HDSPM_MAX_CHANNELS, return NULL);
2640
2641 if ((mapped_channel = hdspm->channel_map[channel]) < 0)
2642 return NULL;
2643
2644 if (stream == SNDRV_PCM_STREAM_CAPTURE) {
2645 return hdspm->capture_buffer +
2646 mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
2647 } else {
2648 return hdspm->playback_buffer +
2649 mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
2650 }
2651}
2652
2653
2654/* dont know why need it ??? */
Takashi Iwai98274f02005-11-17 14:52:34 +01002655static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02002656 int channel, snd_pcm_uframes_t pos,
2657 void __user *src, snd_pcm_uframes_t count)
2658{
Takashi Iwai98274f02005-11-17 14:52:34 +01002659 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02002660 char *channel_buf;
2661
2662 snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
2663 return -EINVAL);
2664
2665 channel_buf = hdspm_channel_buffer_location(hdspm,
2666 substream->pstr->
2667 stream, channel);
2668
2669 snd_assert(channel_buf != NULL, return -EIO);
2670
2671 return copy_from_user(channel_buf + pos * 4, src, count * 4);
2672}
2673
Takashi Iwai98274f02005-11-17 14:52:34 +01002674static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02002675 int channel, snd_pcm_uframes_t pos,
2676 void __user *dst, snd_pcm_uframes_t count)
2677{
Takashi Iwai98274f02005-11-17 14:52:34 +01002678 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02002679 char *channel_buf;
2680
2681 snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
2682 return -EINVAL);
2683
2684 channel_buf = hdspm_channel_buffer_location(hdspm,
2685 substream->pstr->
2686 stream, channel);
2687 snd_assert(channel_buf != NULL, return -EIO);
2688 return copy_to_user(dst, channel_buf + pos * 4, count * 4);
2689}
2690
Takashi Iwai98274f02005-11-17 14:52:34 +01002691static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02002692 int channel, snd_pcm_uframes_t pos,
2693 snd_pcm_uframes_t count)
2694{
Takashi Iwai98274f02005-11-17 14:52:34 +01002695 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02002696 char *channel_buf;
2697
2698 channel_buf =
2699 hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
2700 channel);
2701 snd_assert(channel_buf != NULL, return -EIO);
2702 memset(channel_buf + pos * 4, 0, count * 4);
2703 return 0;
2704}
2705
Takashi Iwai98274f02005-11-17 14:52:34 +01002706static int snd_hdspm_reset(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002707{
Takashi Iwai98274f02005-11-17 14:52:34 +01002708 struct snd_pcm_runtime *runtime = substream->runtime;
2709 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
2710 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02002711
2712 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2713 other = hdspm->capture_substream;
2714 else
2715 other = hdspm->playback_substream;
2716
2717 if (hdspm->running)
2718 runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
2719 else
2720 runtime->status->hw_ptr = 0;
2721 if (other) {
2722 struct list_head *pos;
Takashi Iwai98274f02005-11-17 14:52:34 +01002723 struct snd_pcm_substream *s;
2724 struct snd_pcm_runtime *oruntime = other->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02002725 snd_pcm_group_for_each(pos, substream) {
2726 s = snd_pcm_group_substream_entry(pos);
2727 if (s == other) {
2728 oruntime->status->hw_ptr =
2729 runtime->status->hw_ptr;
2730 break;
2731 }
2732 }
2733 }
2734 return 0;
2735}
2736
Takashi Iwai98274f02005-11-17 14:52:34 +01002737static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
2738 struct snd_pcm_hw_params *params)
Takashi Iwai763f3562005-06-03 11:25:34 +02002739{
Takashi Iwai98274f02005-11-17 14:52:34 +01002740 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02002741 int err;
2742 int i;
2743 pid_t this_pid;
2744 pid_t other_pid;
2745 struct snd_sg_buf *sgbuf;
2746
2747
2748 spin_lock_irq(&hdspm->lock);
2749
2750 if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
2751 this_pid = hdspm->playback_pid;
2752 other_pid = hdspm->capture_pid;
2753 } else {
2754 this_pid = hdspm->capture_pid;
2755 other_pid = hdspm->playback_pid;
2756 }
2757
2758 if ((other_pid > 0) && (this_pid != other_pid)) {
2759
2760 /* The other stream is open, and not by the same
2761 task as this one. Make sure that the parameters
2762 that matter are the same.
2763 */
2764
2765 if (params_rate(params) != hdspm->system_sample_rate) {
2766 spin_unlock_irq(&hdspm->lock);
2767 _snd_pcm_hw_param_setempty(params,
2768 SNDRV_PCM_HW_PARAM_RATE);
2769 return -EBUSY;
2770 }
2771
2772 if (params_period_size(params) != hdspm->period_bytes / 4) {
2773 spin_unlock_irq(&hdspm->lock);
2774 _snd_pcm_hw_param_setempty(params,
2775 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
2776 return -EBUSY;
2777 }
2778
2779 }
2780 /* We're fine. */
2781 spin_unlock_irq(&hdspm->lock);
2782
2783 /* how to make sure that the rate matches an externally-set one ? */
2784
2785 spin_lock_irq(&hdspm->lock);
2786 if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) {
2787 spin_unlock_irq(&hdspm->lock);
2788 _snd_pcm_hw_param_setempty(params,
2789 SNDRV_PCM_HW_PARAM_RATE);
2790 return err;
2791 }
2792 spin_unlock_irq(&hdspm->lock);
2793
2794 if ((err =
2795 hdspm_set_interrupt_interval(hdspm,
2796 params_period_size(params))) <
2797 0) {
2798 _snd_pcm_hw_param_setempty(params,
2799 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
2800 return err;
2801 }
2802
2803 /* Memory allocation, takashi's method, dont know if we should spinlock */
2804 /* malloc all buffer even if not enabled to get sure */
2805 /* malloc only needed bytes */
2806 err =
2807 snd_pcm_lib_malloc_pages(substream,
2808 HDSPM_CHANNEL_BUFFER_BYTES *
2809 params_channels(params));
2810 if (err < 0)
2811 return err;
2812
2813 sgbuf = snd_pcm_substream_sgbuf(substream);
2814
2815 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
2816
2817 hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut,
2818 params_channels(params));
2819
2820 for (i = 0; i < params_channels(params); ++i)
2821 snd_hdspm_enable_out(hdspm, i, 1);
2822
2823 hdspm->playback_buffer =
2824 (unsigned char *) substream->runtime->dma_area;
2825 } else {
2826 hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
2827 params_channels(params));
2828
2829 for (i = 0; i < params_channels(params); ++i)
2830 snd_hdspm_enable_in(hdspm, i, 1);
2831
2832 hdspm->capture_buffer =
2833 (unsigned char *) substream->runtime->dma_area;
2834 }
2835 return 0;
2836}
2837
Takashi Iwai98274f02005-11-17 14:52:34 +01002838static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002839{
2840 int i;
Takashi Iwai98274f02005-11-17 14:52:34 +01002841 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02002842
2843 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
2844
2845 /* params_channels(params) should be enough,
2846 but to get sure in case of error */
2847 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
2848 snd_hdspm_enable_out(hdspm, i, 0);
2849
2850 hdspm->playback_buffer = NULL;
2851 } else {
2852 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
2853 snd_hdspm_enable_in(hdspm, i, 0);
2854
2855 hdspm->capture_buffer = NULL;
2856
2857 }
2858
2859 snd_pcm_lib_free_pages(substream);
2860
2861 return 0;
2862}
2863
Takashi Iwai98274f02005-11-17 14:52:34 +01002864static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
2865 struct snd_pcm_channel_info * info)
Takashi Iwai763f3562005-06-03 11:25:34 +02002866{
Takashi Iwai98274f02005-11-17 14:52:34 +01002867 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02002868 int mapped_channel;
2869
2870 snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL);
2871
2872 if ((mapped_channel = hdspm->channel_map[info->channel]) < 0)
2873 return -EINVAL;
2874
2875 info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
2876 info->first = 0;
2877 info->step = 32;
2878 return 0;
2879}
2880
Takashi Iwai98274f02005-11-17 14:52:34 +01002881static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
Takashi Iwai763f3562005-06-03 11:25:34 +02002882 unsigned int cmd, void *arg)
2883{
2884 switch (cmd) {
2885 case SNDRV_PCM_IOCTL1_RESET:
2886 {
2887 return snd_hdspm_reset(substream);
2888 }
2889
2890 case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
2891 {
Takashi Iwai98274f02005-11-17 14:52:34 +01002892 struct snd_pcm_channel_info *info = arg;
Takashi Iwai763f3562005-06-03 11:25:34 +02002893 return snd_hdspm_channel_info(substream, info);
2894 }
2895 default:
2896 break;
2897 }
2898
2899 return snd_pcm_lib_ioctl(substream, cmd, arg);
2900}
2901
Takashi Iwai98274f02005-11-17 14:52:34 +01002902static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
Takashi Iwai763f3562005-06-03 11:25:34 +02002903{
Takashi Iwai98274f02005-11-17 14:52:34 +01002904 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
2905 struct snd_pcm_substream *other;
Takashi Iwai763f3562005-06-03 11:25:34 +02002906 int running;
2907
2908 spin_lock(&hdspm->lock);
2909 running = hdspm->running;
2910 switch (cmd) {
2911 case SNDRV_PCM_TRIGGER_START:
2912 running |= 1 << substream->stream;
2913 break;
2914 case SNDRV_PCM_TRIGGER_STOP:
2915 running &= ~(1 << substream->stream);
2916 break;
2917 default:
2918 snd_BUG();
2919 spin_unlock(&hdspm->lock);
2920 return -EINVAL;
2921 }
2922 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2923 other = hdspm->capture_substream;
2924 else
2925 other = hdspm->playback_substream;
2926
2927 if (other) {
2928 struct list_head *pos;
Takashi Iwai98274f02005-11-17 14:52:34 +01002929 struct snd_pcm_substream *s;
Takashi Iwai763f3562005-06-03 11:25:34 +02002930 snd_pcm_group_for_each(pos, substream) {
2931 s = snd_pcm_group_substream_entry(pos);
2932 if (s == other) {
2933 snd_pcm_trigger_done(s, substream);
2934 if (cmd == SNDRV_PCM_TRIGGER_START)
2935 running |= 1 << s->stream;
2936 else
2937 running &= ~(1 << s->stream);
2938 goto _ok;
2939 }
2940 }
2941 if (cmd == SNDRV_PCM_TRIGGER_START) {
2942 if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
2943 && substream->stream ==
2944 SNDRV_PCM_STREAM_CAPTURE)
2945 hdspm_silence_playback(hdspm);
2946 } else {
2947 if (running &&
2948 substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2949 hdspm_silence_playback(hdspm);
2950 }
2951 } else {
2952 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
2953 hdspm_silence_playback(hdspm);
2954 }
2955 _ok:
2956 snd_pcm_trigger_done(substream, substream);
2957 if (!hdspm->running && running)
2958 hdspm_start_audio(hdspm);
2959 else if (hdspm->running && !running)
2960 hdspm_stop_audio(hdspm);
2961 hdspm->running = running;
2962 spin_unlock(&hdspm->lock);
2963
2964 return 0;
2965}
2966
Takashi Iwai98274f02005-11-17 14:52:34 +01002967static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02002968{
2969 return 0;
2970}
2971
2972static unsigned int period_sizes[] =
2973 { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
2974
Takashi Iwai98274f02005-11-17 14:52:34 +01002975static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02002976 .info = (SNDRV_PCM_INFO_MMAP |
2977 SNDRV_PCM_INFO_MMAP_VALID |
2978 SNDRV_PCM_INFO_NONINTERLEAVED |
2979 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
2980 .formats = SNDRV_PCM_FMTBIT_S32_LE,
2981 .rates = (SNDRV_PCM_RATE_32000 |
2982 SNDRV_PCM_RATE_44100 |
2983 SNDRV_PCM_RATE_48000 |
2984 SNDRV_PCM_RATE_64000 |
2985 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
2986 .rate_min = 32000,
2987 .rate_max = 96000,
2988 .channels_min = 1,
2989 .channels_max = HDSPM_MAX_CHANNELS,
2990 .buffer_bytes_max =
2991 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
2992 .period_bytes_min = (64 * 4),
2993 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
2994 .periods_min = 2,
2995 .periods_max = 2,
2996 .fifo_size = 0
2997};
2998
Takashi Iwai98274f02005-11-17 14:52:34 +01002999static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003000 .info = (SNDRV_PCM_INFO_MMAP |
3001 SNDRV_PCM_INFO_MMAP_VALID |
3002 SNDRV_PCM_INFO_NONINTERLEAVED |
3003 SNDRV_PCM_INFO_SYNC_START),
3004 .formats = SNDRV_PCM_FMTBIT_S32_LE,
3005 .rates = (SNDRV_PCM_RATE_32000 |
3006 SNDRV_PCM_RATE_44100 |
3007 SNDRV_PCM_RATE_48000 |
3008 SNDRV_PCM_RATE_64000 |
3009 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
3010 .rate_min = 32000,
3011 .rate_max = 96000,
3012 .channels_min = 1,
3013 .channels_max = HDSPM_MAX_CHANNELS,
3014 .buffer_bytes_max =
3015 HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
3016 .period_bytes_min = (64 * 4),
3017 .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
3018 .periods_min = 2,
3019 .periods_max = 2,
3020 .fifo_size = 0
3021};
3022
Takashi Iwai98274f02005-11-17 14:52:34 +01003023static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003024 .count = ARRAY_SIZE(period_sizes),
3025 .list = period_sizes,
3026 .mask = 0
3027};
3028
3029
Takashi Iwai98274f02005-11-17 14:52:34 +01003030static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params,
3031 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02003032{
Takashi Iwai98274f02005-11-17 14:52:34 +01003033 struct hdspm *hdspm = rule->private;
3034 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02003035 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01003036 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02003037 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
3038
3039 if (r->min > 48000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003040 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003041 .min = 1,
3042 .max = hdspm->ds_channels,
3043 .integer = 1,
3044 };
3045 return snd_interval_refine(c, &t);
3046 } else if (r->max < 64000) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003047 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003048 .min = 1,
3049 .max = hdspm->ss_channels,
3050 .integer = 1,
3051 };
3052 return snd_interval_refine(c, &t);
3053 }
3054 return 0;
3055}
3056
Takashi Iwai98274f02005-11-17 14:52:34 +01003057static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
3058 struct snd_pcm_hw_rule * rule)
Takashi Iwai763f3562005-06-03 11:25:34 +02003059{
Takashi Iwai98274f02005-11-17 14:52:34 +01003060 struct hdspm *hdspm = rule->private;
3061 struct snd_interval *c =
Takashi Iwai763f3562005-06-03 11:25:34 +02003062 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
Takashi Iwai98274f02005-11-17 14:52:34 +01003063 struct snd_interval *r =
Takashi Iwai763f3562005-06-03 11:25:34 +02003064 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
3065
3066 if (c->min <= hdspm->ss_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003067 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003068 .min = 32000,
3069 .max = 48000,
3070 .integer = 1,
3071 };
3072 return snd_interval_refine(r, &t);
3073 } else if (c->max > hdspm->ss_channels) {
Takashi Iwai98274f02005-11-17 14:52:34 +01003074 struct snd_interval t = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003075 .min = 64000,
3076 .max = 96000,
3077 .integer = 1,
3078 };
3079
3080 return snd_interval_refine(r, &t);
3081 }
3082 return 0;
3083}
3084
Takashi Iwai98274f02005-11-17 14:52:34 +01003085static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003086{
Takashi Iwai98274f02005-11-17 14:52:34 +01003087 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3088 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02003089
3090 snd_printdd("Open device substream %d\n", substream->stream);
3091
3092 spin_lock_irq(&hdspm->lock);
3093
3094 snd_pcm_set_sync(substream);
3095
3096 runtime->hw = snd_hdspm_playback_subinfo;
3097
3098 if (hdspm->capture_substream == NULL)
3099 hdspm_stop_audio(hdspm);
3100
3101 hdspm->playback_pid = current->pid;
3102 hdspm->playback_substream = substream;
3103
3104 spin_unlock_irq(&hdspm->lock);
3105
3106 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
3107
3108 snd_pcm_hw_constraint_list(runtime, 0,
3109 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
3110 &hw_constraints_period_sizes);
3111
3112 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
3113 snd_hdspm_hw_rule_channels_rate, hdspm,
3114 SNDRV_PCM_HW_PARAM_RATE, -1);
3115
3116 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
3117 snd_hdspm_hw_rule_rate_channels, hdspm,
3118 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
3119
3120 return 0;
3121}
3122
Takashi Iwai98274f02005-11-17 14:52:34 +01003123static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003124{
Takashi Iwai98274f02005-11-17 14:52:34 +01003125 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003126
3127 spin_lock_irq(&hdspm->lock);
3128
3129 hdspm->playback_pid = -1;
3130 hdspm->playback_substream = NULL;
3131
3132 spin_unlock_irq(&hdspm->lock);
3133
3134 return 0;
3135}
3136
3137
Takashi Iwai98274f02005-11-17 14:52:34 +01003138static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003139{
Takashi Iwai98274f02005-11-17 14:52:34 +01003140 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
3141 struct snd_pcm_runtime *runtime = substream->runtime;
Takashi Iwai763f3562005-06-03 11:25:34 +02003142
3143 spin_lock_irq(&hdspm->lock);
3144 snd_pcm_set_sync(substream);
3145 runtime->hw = snd_hdspm_capture_subinfo;
3146
3147 if (hdspm->playback_substream == NULL)
3148 hdspm_stop_audio(hdspm);
3149
3150 hdspm->capture_pid = current->pid;
3151 hdspm->capture_substream = substream;
3152
3153 spin_unlock_irq(&hdspm->lock);
3154
3155 snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
3156 snd_pcm_hw_constraint_list(runtime, 0,
3157 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
3158 &hw_constraints_period_sizes);
3159
3160 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
3161 snd_hdspm_hw_rule_channels_rate, hdspm,
3162 SNDRV_PCM_HW_PARAM_RATE, -1);
3163
3164 snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
3165 snd_hdspm_hw_rule_rate_channels, hdspm,
3166 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
3167 return 0;
3168}
3169
Takashi Iwai98274f02005-11-17 14:52:34 +01003170static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
Takashi Iwai763f3562005-06-03 11:25:34 +02003171{
Takashi Iwai98274f02005-11-17 14:52:34 +01003172 struct hdspm *hdspm = snd_pcm_substream_chip(substream);
Takashi Iwai763f3562005-06-03 11:25:34 +02003173
3174 spin_lock_irq(&hdspm->lock);
3175
3176 hdspm->capture_pid = -1;
3177 hdspm->capture_substream = NULL;
3178
3179 spin_unlock_irq(&hdspm->lock);
3180 return 0;
3181}
3182
Takashi Iwai98274f02005-11-17 14:52:34 +01003183static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file)
Takashi Iwai763f3562005-06-03 11:25:34 +02003184{
3185 /* we have nothing to initialize but the call is required */
3186 return 0;
3187}
3188
3189
Takashi Iwai98274f02005-11-17 14:52:34 +01003190static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
Takashi Iwai763f3562005-06-03 11:25:34 +02003191 unsigned int cmd, unsigned long arg)
3192{
Takashi Iwai98274f02005-11-17 14:52:34 +01003193 struct hdspm *hdspm = (struct hdspm *) hw->private_data;
3194 struct hdspm_mixer_ioctl mixer;
3195 struct hdspm_config_info info;
3196 struct hdspm_version hdspm_version;
3197 struct hdspm_peak_rms_ioctl rms;
Takashi Iwai763f3562005-06-03 11:25:34 +02003198
3199 switch (cmd) {
3200
3201
3202 case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
3203 if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
3204 return -EFAULT;
3205 /* maybe there is a chance to memorymap in future so dont touch just copy */
3206 if(copy_to_user_fromio((void __user *)rms.peak,
3207 hdspm->iobase+HDSPM_MADI_peakrmsbase,
Takashi Iwai98274f02005-11-17 14:52:34 +01003208 sizeof(struct hdspm_peak_rms)) != 0 )
Takashi Iwai763f3562005-06-03 11:25:34 +02003209 return -EFAULT;
3210
3211 break;
3212
3213
3214 case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
3215
3216 spin_lock_irq(&hdspm->lock);
3217 info.pref_sync_ref =
3218 (unsigned char) hdspm_pref_sync_ref(hdspm);
3219 info.wordclock_sync_check =
3220 (unsigned char) hdspm_wc_sync_check(hdspm);
3221
3222 info.system_sample_rate = hdspm->system_sample_rate;
3223 info.autosync_sample_rate =
3224 hdspm_external_sample_rate(hdspm);
3225 info.system_clock_mode =
3226 (unsigned char) hdspm_system_clock_mode(hdspm);
3227 info.clock_source =
3228 (unsigned char) hdspm_clock_source(hdspm);
3229 info.autosync_ref =
3230 (unsigned char) hdspm_autosync_ref(hdspm);
3231 info.line_out = (unsigned char) hdspm_line_out(hdspm);
3232 info.passthru = 0;
3233 spin_unlock_irq(&hdspm->lock);
3234 if (copy_to_user((void __user *) arg, &info, sizeof(info)))
3235 return -EFAULT;
3236 break;
3237
3238 case SNDRV_HDSPM_IOCTL_GET_VERSION:
3239 hdspm_version.firmware_rev = hdspm->firmware_rev;
3240 if (copy_to_user((void __user *) arg, &hdspm_version,
3241 sizeof(hdspm_version)))
3242 return -EFAULT;
3243 break;
3244
3245 case SNDRV_HDSPM_IOCTL_GET_MIXER:
3246 if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
3247 return -EFAULT;
3248 if (copy_to_user
Takashi Iwai98274f02005-11-17 14:52:34 +01003249 ((void __user *)mixer.mixer, hdspm->mixer, sizeof(struct hdspm_mixer)))
Takashi Iwai763f3562005-06-03 11:25:34 +02003250 return -EFAULT;
3251 break;
3252
3253 default:
3254 return -EINVAL;
3255 }
3256 return 0;
3257}
3258
Takashi Iwai98274f02005-11-17 14:52:34 +01003259static struct snd_pcm_ops snd_hdspm_playback_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003260 .open = snd_hdspm_playback_open,
3261 .close = snd_hdspm_playback_release,
3262 .ioctl = snd_hdspm_ioctl,
3263 .hw_params = snd_hdspm_hw_params,
3264 .hw_free = snd_hdspm_hw_free,
3265 .prepare = snd_hdspm_prepare,
3266 .trigger = snd_hdspm_trigger,
3267 .pointer = snd_hdspm_hw_pointer,
3268 .copy = snd_hdspm_playback_copy,
3269 .silence = snd_hdspm_hw_silence,
3270 .page = snd_pcm_sgbuf_ops_page,
3271};
3272
Takashi Iwai98274f02005-11-17 14:52:34 +01003273static struct snd_pcm_ops snd_hdspm_capture_ops = {
Takashi Iwai763f3562005-06-03 11:25:34 +02003274 .open = snd_hdspm_capture_open,
3275 .close = snd_hdspm_capture_release,
3276 .ioctl = snd_hdspm_ioctl,
3277 .hw_params = snd_hdspm_hw_params,
3278 .hw_free = snd_hdspm_hw_free,
3279 .prepare = snd_hdspm_prepare,
3280 .trigger = snd_hdspm_trigger,
3281 .pointer = snd_hdspm_hw_pointer,
3282 .copy = snd_hdspm_capture_copy,
3283 .page = snd_pcm_sgbuf_ops_page,
3284};
3285
Takashi Iwai98274f02005-11-17 14:52:34 +01003286static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
3287 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003288{
Takashi Iwai98274f02005-11-17 14:52:34 +01003289 struct snd_hwdep *hw;
Takashi Iwai763f3562005-06-03 11:25:34 +02003290 int err;
3291
3292 if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0)
3293 return err;
3294
3295 hdspm->hwdep = hw;
3296 hw->private_data = hdspm;
3297 strcpy(hw->name, "HDSPM hwdep interface");
3298
3299 hw->ops.open = snd_hdspm_hwdep_dummy_op;
3300 hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
3301 hw->ops.release = snd_hdspm_hwdep_dummy_op;
3302
3303 return 0;
3304}
3305
3306
3307/*------------------------------------------------------------
3308 memory interface
3309 ------------------------------------------------------------*/
Takashi Iwai98274f02005-11-17 14:52:34 +01003310static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003311{
3312 int err;
Takashi Iwai98274f02005-11-17 14:52:34 +01003313 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02003314 size_t wanted;
3315
3316 pcm = hdspm->pcm;
3317
3318 wanted = HDSPM_DMA_AREA_BYTES + 4096; /* dont know why, but it works */
3319
3320 if ((err =
3321 snd_pcm_lib_preallocate_pages_for_all(pcm,
3322 SNDRV_DMA_TYPE_DEV_SG,
3323 snd_dma_pci_data(hdspm->pci),
3324 wanted,
3325 wanted)) < 0) {
Andrew Mortone2eba3e2006-01-20 14:07:13 +01003326 snd_printdd("Could not preallocate %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02003327
3328 return err;
3329 } else
Andrew Mortone2eba3e2006-01-20 14:07:13 +01003330 snd_printdd(" Preallocated %zd Bytes\n", wanted);
Takashi Iwai763f3562005-06-03 11:25:34 +02003331
3332 return 0;
3333}
3334
Takashi Iwai98274f02005-11-17 14:52:34 +01003335static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
Takashi Iwai763f3562005-06-03 11:25:34 +02003336 unsigned int reg, int channels)
3337{
3338 int i;
3339 for (i = 0; i < (channels * 16); i++)
3340 hdspm_write(hdspm, reg + 4 * i,
3341 snd_pcm_sgbuf_get_addr(sgbuf,
3342 (size_t) 4096 * i));
3343}
3344
3345/* ------------- ALSA Devices ---------------------------- */
Takashi Iwai98274f02005-11-17 14:52:34 +01003346static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
3347 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003348{
Takashi Iwai98274f02005-11-17 14:52:34 +01003349 struct snd_pcm *pcm;
Takashi Iwai763f3562005-06-03 11:25:34 +02003350 int err;
3351
3352 if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0)
3353 return err;
3354
3355 hdspm->pcm = pcm;
3356 pcm->private_data = hdspm;
3357 strcpy(pcm->name, hdspm->card_name);
3358
3359 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
3360 &snd_hdspm_playback_ops);
3361 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
3362 &snd_hdspm_capture_ops);
3363
3364 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
3365
3366 if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0)
3367 return err;
3368
3369 return 0;
3370}
3371
Takashi Iwai98274f02005-11-17 14:52:34 +01003372static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003373{
3374 snd_hdspm_flush_midi_input(hdspm, 0);
3375 snd_hdspm_flush_midi_input(hdspm, 1);
3376}
3377
Takashi Iwai98274f02005-11-17 14:52:34 +01003378static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
3379 struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003380{
3381 int err;
3382
3383 snd_printdd("Create card...\n");
3384 if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0)
3385 return err;
3386
3387 if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0)
3388 return err;
3389
3390 if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0)
3391 return err;
3392
3393 if ((err = snd_hdspm_create_controls(card, hdspm)) < 0)
3394 return err;
3395
3396 if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0)
3397 return err;
3398
3399 snd_printdd("proc init...\n");
3400 snd_hdspm_proc_init(hdspm);
3401
3402 hdspm->system_sample_rate = -1;
3403 hdspm->last_external_sample_rate = -1;
3404 hdspm->last_internal_sample_rate = -1;
3405 hdspm->playback_pid = -1;
3406 hdspm->capture_pid = -1;
3407 hdspm->capture_substream = NULL;
3408 hdspm->playback_substream = NULL;
3409
3410 snd_printdd("Set defaults...\n");
3411 if ((err = snd_hdspm_set_defaults(hdspm)) < 0)
3412 return err;
3413
3414 snd_printdd("Update mixer controls...\n");
3415 hdspm_update_simple_mixer_controls(hdspm);
3416
3417 snd_printdd("Initializeing complete ???\n");
3418
3419 if ((err = snd_card_register(card)) < 0) {
3420 snd_printk(KERN_ERR "HDSPM: error registering card\n");
3421 return err;
3422 }
3423
3424 snd_printdd("... yes now\n");
3425
3426 return 0;
3427}
3428
Takashi Iwai98274f02005-11-17 14:52:34 +01003429static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdspm,
Takashi Iwai763f3562005-06-03 11:25:34 +02003430 int precise_ptr, int enable_monitor)
3431{
3432 struct pci_dev *pci = hdspm->pci;
3433 int err;
3434 int i;
3435
3436 unsigned long io_extent;
3437
3438 hdspm->irq = -1;
3439 hdspm->irq_count = 0;
3440
3441 hdspm->midi[0].rmidi = NULL;
3442 hdspm->midi[1].rmidi = NULL;
3443 hdspm->midi[0].input = NULL;
3444 hdspm->midi[1].input = NULL;
3445 hdspm->midi[0].output = NULL;
3446 hdspm->midi[1].output = NULL;
3447 spin_lock_init(&hdspm->midi[0].lock);
3448 spin_lock_init(&hdspm->midi[1].lock);
3449 hdspm->iobase = NULL;
3450 hdspm->control_register = 0;
3451 hdspm->control2_register = 0;
3452
3453 hdspm->playback_buffer = NULL;
3454 hdspm->capture_buffer = NULL;
3455
3456 for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
3457 hdspm->playback_mixer_ctls[i] = NULL;
3458 hdspm->mixer = NULL;
3459
3460 hdspm->card = card;
3461
3462 spin_lock_init(&hdspm->lock);
3463
3464 tasklet_init(&hdspm->midi_tasklet,
3465 hdspm_midi_tasklet, (unsigned long) hdspm);
3466
3467 pci_read_config_word(hdspm->pci,
3468 PCI_CLASS_REVISION, &hdspm->firmware_rev);
3469
3470 strcpy(card->driver, "HDSPM");
3471 strcpy(card->mixername, "Xilinx FPGA");
3472 hdspm->card_name = "RME HDSPM MADI";
3473
3474 if ((err = pci_enable_device(pci)) < 0)
3475 return err;
3476
3477 pci_set_master(hdspm->pci);
3478
3479 if ((err = pci_request_regions(pci, "hdspm")) < 0)
3480 return err;
3481
3482 hdspm->port = pci_resource_start(pci, 0);
3483 io_extent = pci_resource_len(pci, 0);
3484
3485 snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
3486 hdspm->port, hdspm->port + io_extent - 1);
3487
3488
3489 if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) {
3490 snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n",
3491 hdspm->port, hdspm->port + io_extent - 1);
3492 return -EBUSY;
3493 }
3494 snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
3495 (unsigned long)hdspm->iobase, hdspm->port,
3496 hdspm->port + io_extent - 1);
3497
3498 if (request_irq(pci->irq, snd_hdspm_interrupt,
Thomas Gleixner65ca68b2006-07-01 19:29:46 -07003499 IRQF_DISABLED | IRQF_SHARED, "hdspm",
Takashi Iwai763f3562005-06-03 11:25:34 +02003500 (void *) hdspm)) {
3501 snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
3502 return -EBUSY;
3503 }
3504
3505 snd_printdd("use IRQ %d\n", pci->irq);
3506
3507 hdspm->irq = pci->irq;
3508 hdspm->precise_ptr = precise_ptr;
3509
3510 hdspm->monitor_outs = enable_monitor;
3511
Andrew Mortone2eba3e2006-01-20 14:07:13 +01003512 snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
Takashi Iwai98274f02005-11-17 14:52:34 +01003513 sizeof(struct hdspm_mixer));
3514 if ((hdspm->mixer = kmalloc(sizeof(struct hdspm_mixer), GFP_KERNEL))
Takashi Iwai763f3562005-06-03 11:25:34 +02003515 == NULL) {
3516 snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n",
Takashi Iwai98274f02005-11-17 14:52:34 +01003517 (int)sizeof(struct hdspm_mixer));
Takashi Iwai763f3562005-06-03 11:25:34 +02003518 return err;
3519 }
3520
3521 hdspm->ss_channels = MADI_SS_CHANNELS;
3522 hdspm->ds_channels = MADI_DS_CHANNELS;
3523 hdspm->qs_channels = MADI_QS_CHANNELS;
3524
3525 snd_printdd("create alsa devices.\n");
3526 if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0)
3527 return err;
3528
3529 snd_hdspm_initialize_midi_flush(hdspm);
3530
3531 return 0;
3532}
3533
Takashi Iwai98274f02005-11-17 14:52:34 +01003534static int snd_hdspm_free(struct hdspm * hdspm)
Takashi Iwai763f3562005-06-03 11:25:34 +02003535{
3536
3537 if (hdspm->port) {
3538
3539 /* stop th audio, and cancel all interrupts */
3540 hdspm->control_register &=
3541 ~(HDSPM_Start | HDSPM_AudioInterruptEnable
3542 | HDSPM_Midi0InterruptEnable |
3543 HDSPM_Midi1InterruptEnable);
3544 hdspm_write(hdspm, HDSPM_controlRegister,
3545 hdspm->control_register);
3546 }
3547
3548 if (hdspm->irq >= 0)
3549 free_irq(hdspm->irq, (void *) hdspm);
3550
3551
Jesper Juhlfc584222005-10-24 15:11:28 +02003552 kfree(hdspm->mixer);
Takashi Iwai763f3562005-06-03 11:25:34 +02003553
3554 if (hdspm->iobase)
3555 iounmap(hdspm->iobase);
3556
Takashi Iwai763f3562005-06-03 11:25:34 +02003557 if (hdspm->port)
3558 pci_release_regions(hdspm->pci);
3559
3560 pci_disable_device(hdspm->pci);
3561 return 0;
3562}
3563
Takashi Iwai98274f02005-11-17 14:52:34 +01003564static void snd_hdspm_card_free(struct snd_card *card)
Takashi Iwai763f3562005-06-03 11:25:34 +02003565{
Takashi Iwai98274f02005-11-17 14:52:34 +01003566 struct hdspm *hdspm = (struct hdspm *) card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02003567
3568 if (hdspm)
3569 snd_hdspm_free(hdspm);
3570}
3571
3572static int __devinit snd_hdspm_probe(struct pci_dev *pci,
3573 const struct pci_device_id *pci_id)
3574{
3575 static int dev;
Takashi Iwai98274f02005-11-17 14:52:34 +01003576 struct hdspm *hdspm;
3577 struct snd_card *card;
Takashi Iwai763f3562005-06-03 11:25:34 +02003578 int err;
3579
3580 if (dev >= SNDRV_CARDS)
3581 return -ENODEV;
3582 if (!enable[dev]) {
3583 dev++;
3584 return -ENOENT;
3585 }
3586
3587 if (!(card = snd_card_new(index[dev], id[dev],
Takashi Iwai98274f02005-11-17 14:52:34 +01003588 THIS_MODULE, sizeof(struct hdspm))))
Takashi Iwai763f3562005-06-03 11:25:34 +02003589 return -ENOMEM;
3590
Takashi Iwai98274f02005-11-17 14:52:34 +01003591 hdspm = (struct hdspm *) card->private_data;
Takashi Iwai763f3562005-06-03 11:25:34 +02003592 card->private_free = snd_hdspm_card_free;
3593 hdspm->dev = dev;
3594 hdspm->pci = pci;
3595
3596 if ((err =
3597 snd_hdspm_create(card, hdspm, precise_ptr[dev],
3598 enable_monitor[dev])) < 0) {
3599 snd_card_free(card);
3600 return err;
3601 }
3602
3603 strcpy(card->shortname, "HDSPM MADI");
3604 sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
3605 hdspm->port, hdspm->irq);
3606
3607 if ((err = snd_card_register(card)) < 0) {
3608 snd_card_free(card);
3609 return err;
3610 }
3611
3612 pci_set_drvdata(pci, card);
3613
3614 dev++;
3615 return 0;
3616}
3617
3618static void __devexit snd_hdspm_remove(struct pci_dev *pci)
3619{
3620 snd_card_free(pci_get_drvdata(pci));
3621 pci_set_drvdata(pci, NULL);
3622}
3623
3624static struct pci_driver driver = {
3625 .name = "RME Hammerfall DSP MADI",
Takashi Iwai763f3562005-06-03 11:25:34 +02003626 .id_table = snd_hdspm_ids,
3627 .probe = snd_hdspm_probe,
3628 .remove = __devexit_p(snd_hdspm_remove),
3629};
3630
3631
3632static int __init alsa_card_hdspm_init(void)
3633{
3634 return pci_register_driver(&driver);
3635}
3636
3637static void __exit alsa_card_hdspm_exit(void)
3638{
3639 pci_unregister_driver(&driver);
3640}
3641
3642module_init(alsa_card_hdspm_init)
3643module_exit(alsa_card_hdspm_exit)