aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire/dice
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-06-04 05:41:48 -0400
committerTakashi Iwai <tiwai@suse.de>2018-06-04 05:42:27 -0400
commitcdbc653a04ee692a7105a96e8dd6055d9971d45c (patch)
treec1282680b3115edfd693a27bc6758208534ac557 /sound/firewire/dice
parent009f8c90f571d87855914dbc20e6c0ea2a3b19ae (diff)
parentceec4684085a9e4dc60439d84ab47ce260444804 (diff)
Merge branch 'for-next' into for-linus
4.18-rc1 merge material. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/dice')
-rw-r--r--sound/firewire/dice/Makefile3
-rw-r--r--sound/firewire/dice/dice-alesis.c52
-rw-r--r--sound/firewire/dice/dice-extension.c172
-rw-r--r--sound/firewire/dice/dice-interface.h9
-rw-r--r--sound/firewire/dice/dice-midi.c23
-rw-r--r--sound/firewire/dice/dice-mytek.c46
-rw-r--r--sound/firewire/dice/dice-pcm.c233
-rw-r--r--sound/firewire/dice/dice-proc.c80
-rw-r--r--sound/firewire/dice/dice-stream.c283
-rw-r--r--sound/firewire/dice/dice-tcelectronic.c104
-rw-r--r--sound/firewire/dice/dice-transaction.c49
-rw-r--r--sound/firewire/dice/dice.c156
-rw-r--r--sound/firewire/dice/dice.h25
13 files changed, 999 insertions, 236 deletions
diff --git a/sound/firewire/dice/Makefile b/sound/firewire/dice/Makefile
index 55b4be9b0034..37062a233f6a 100644
--- a/sound/firewire/dice/Makefile
+++ b/sound/firewire/dice/Makefile
@@ -1,3 +1,4 @@
1snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \ 1snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \
2 dice-pcm.o dice-hwdep.o dice.o 2 dice-pcm.o dice-hwdep.o dice.o dice-tcelectronic.o \
3 dice-alesis.o dice-extension.o dice-mytek.o
3obj-$(CONFIG_SND_DICE) += snd-dice.o 4obj-$(CONFIG_SND_DICE) += snd-dice.o
diff --git a/sound/firewire/dice/dice-alesis.c b/sound/firewire/dice/dice-alesis.c
new file mode 100644
index 000000000000..b2efb1c71a98
--- /dev/null
+++ b/sound/firewire/dice/dice-alesis.c
@@ -0,0 +1,52 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * dice-alesis.c - a part of driver for DICE based devices
4 *
5 * Copyright (c) 2018 Takashi Sakamoto
6 */
7
8#include "dice.h"
9
10static const unsigned int
11alesis_io14_tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT] = {
12 {6, 6, 4}, /* Tx0 = Analog + S/PDIF. */
13 {8, 4, 0}, /* Tx1 = ADAT1. */
14};
15
16static const unsigned int
17alesis_io26_tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT] = {
18 {10, 10, 8}, /* Tx0 = Analog + S/PDIF. */
19 {16, 8, 0}, /* Tx1 = ADAT1 + ADAT2. */
20};
21
22int snd_dice_detect_alesis_formats(struct snd_dice *dice)
23{
24 __be32 reg;
25 u32 data;
26 int i;
27 int err;
28
29 err = snd_dice_transaction_read_tx(dice, TX_NUMBER_AUDIO, &reg,
30 sizeof(reg));
31 if (err < 0)
32 return err;
33 data = be32_to_cpu(reg);
34
35 if (data == 4 || data == 6) {
36 memcpy(dice->tx_pcm_chs, alesis_io14_tx_pcm_chs,
37 MAX_STREAMS * SND_DICE_RATE_MODE_COUNT *
38 sizeof(unsigned int));
39 } else {
40 memcpy(dice->rx_pcm_chs, alesis_io26_tx_pcm_chs,
41 MAX_STREAMS * SND_DICE_RATE_MODE_COUNT *
42 sizeof(unsigned int));
43 }
44
45 for (i = 0; i < SND_DICE_RATE_MODE_COUNT; ++i)
46 dice->rx_pcm_chs[0][i] = 8;
47
48 dice->tx_midi_ports[0] = 1;
49 dice->rx_midi_ports[0] = 1;
50
51 return 0;
52}
diff --git a/sound/firewire/dice/dice-extension.c b/sound/firewire/dice/dice-extension.c
new file mode 100644
index 000000000000..a63fcbc875ad
--- /dev/null
+++ b/sound/firewire/dice/dice-extension.c
@@ -0,0 +1,172 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * dice-extension.c - a part of driver for DICE based devices
4 *
5 * Copyright (c) 2018 Takashi Sakamoto
6 */
7
8#include "dice.h"
9
10/* For TCD2210/2220, TCAT defines extension of application protocol. */
11
12#define DICE_EXT_APP_SPACE 0xffffe0200000uLL
13
14#define DICE_EXT_APP_CAPS_OFFSET 0x00
15#define DICE_EXT_APP_CAPS_SIZE 0x04
16#define DICE_EXT_APP_CMD_OFFSET 0x08
17#define DICE_EXT_APP_CMD_SIZE 0x0c
18#define DICE_EXT_APP_MIXER_OFFSET 0x10
19#define DICE_EXT_APP_MIXER_SIZE 0x14
20#define DICE_EXT_APP_PEAK_OFFSET 0x18
21#define DICE_EXT_APP_PEAK_SIZE 0x1c
22#define DICE_EXT_APP_ROUTER_OFFSET 0x20
23#define DICE_EXT_APP_ROUTER_SIZE 0x24
24#define DICE_EXT_APP_STREAM_OFFSET 0x28
25#define DICE_EXT_APP_STREAM_SIZE 0x2c
26#define DICE_EXT_APP_CURRENT_OFFSET 0x30
27#define DICE_EXT_APP_CURRENT_SIZE 0x34
28#define DICE_EXT_APP_STANDALONE_OFFSET 0x38
29#define DICE_EXT_APP_STANDALONE_SIZE 0x3c
30#define DICE_EXT_APP_APPLICATION_OFFSET 0x40
31#define DICE_EXT_APP_APPLICATION_SIZE 0x44
32
33#define EXT_APP_STREAM_TX_NUMBER 0x0000
34#define EXT_APP_STREAM_RX_NUMBER 0x0004
35#define EXT_APP_STREAM_ENTRIES 0x0008
36#define EXT_APP_STREAM_ENTRY_SIZE 0x010c
37#define EXT_APP_NUMBER_AUDIO 0x0000
38#define EXT_APP_NUMBER_MIDI 0x0004
39#define EXT_APP_NAMES 0x0008
40#define EXT_APP_NAMES_SIZE 256
41#define EXT_APP_AC3 0x0108
42
43#define EXT_APP_CONFIG_LOW_ROUTER 0x0000
44#define EXT_APP_CONFIG_LOW_STREAM 0x1000
45#define EXT_APP_CONFIG_MIDDLE_ROUTER 0x2000
46#define EXT_APP_CONFIG_MIDDLE_STREAM 0x3000
47#define EXT_APP_CONFIG_HIGH_ROUTER 0x4000
48#define EXT_APP_CONFIG_HIGH_STREAM 0x5000
49
50static inline int read_transaction(struct snd_dice *dice, u64 section_addr,
51 u32 offset, void *buf, size_t len)
52{
53 return snd_fw_transaction(dice->unit,
54 len == 4 ? TCODE_READ_QUADLET_REQUEST :
55 TCODE_READ_BLOCK_REQUEST,
56 section_addr + offset, buf, len, 0);
57}
58
59static int read_stream_entries(struct snd_dice *dice, u64 section_addr,
60 u32 base_offset, unsigned int stream_count,
61 unsigned int mode,
62 unsigned int pcm_channels[MAX_STREAMS][3],
63 unsigned int midi_ports[MAX_STREAMS])
64{
65 u32 entry_offset;
66 __be32 reg[2];
67 int err;
68 int i;
69
70 for (i = 0; i < stream_count; ++i) {
71 entry_offset = base_offset + i * EXT_APP_STREAM_ENTRY_SIZE;
72 err = read_transaction(dice, section_addr,
73 entry_offset + EXT_APP_NUMBER_AUDIO,
74 reg, sizeof(reg));
75 if (err < 0)
76 return err;
77 pcm_channels[i][mode] = be32_to_cpu(reg[0]);
78 midi_ports[i] = max(midi_ports[i], be32_to_cpu(reg[1]));
79 }
80
81 return 0;
82}
83
84static int detect_stream_formats(struct snd_dice *dice, u64 section_addr)
85{
86 u32 base_offset;
87 __be32 reg[2];
88 unsigned int stream_count;
89 int mode;
90 int err = 0;
91
92 for (mode = 0; mode < SND_DICE_RATE_MODE_COUNT; ++mode) {
93 unsigned int cap;
94
95 /*
96 * Some models report stream formats at highest mode, however
97 * they don't support the mode. Check clock capabilities.
98 */
99 if (mode == 2) {
100 cap = CLOCK_CAP_RATE_176400 | CLOCK_CAP_RATE_192000;
101 } else if (mode == 1) {
102 cap = CLOCK_CAP_RATE_88200 | CLOCK_CAP_RATE_96000;
103 } else {
104 cap = CLOCK_CAP_RATE_32000 | CLOCK_CAP_RATE_44100 |
105 CLOCK_CAP_RATE_48000;
106 }
107 if (!(cap & dice->clock_caps))
108 continue;
109
110 base_offset = 0x2000 * mode + 0x1000;
111
112 err = read_transaction(dice, section_addr,
113 base_offset + EXT_APP_STREAM_TX_NUMBER,
114 &reg, sizeof(reg));
115 if (err < 0)
116 break;
117
118 base_offset += EXT_APP_STREAM_ENTRIES;
119 stream_count = be32_to_cpu(reg[0]);
120 err = read_stream_entries(dice, section_addr, base_offset,
121 stream_count, mode,
122 dice->tx_pcm_chs,
123 dice->tx_midi_ports);
124 if (err < 0)
125 break;
126
127 base_offset += stream_count * EXT_APP_STREAM_ENTRY_SIZE;
128 stream_count = be32_to_cpu(reg[1]);
129 err = read_stream_entries(dice, section_addr, base_offset,
130 stream_count,
131 mode, dice->rx_pcm_chs,
132 dice->rx_midi_ports);
133 if (err < 0)
134 break;
135 }
136
137 return err;
138}
139
140int snd_dice_detect_extension_formats(struct snd_dice *dice)
141{
142 __be32 *pointers;
143 unsigned int i;
144 u64 section_addr;
145 int err;
146
147 pointers = kmalloc_array(9, sizeof(__be32) * 2, GFP_KERNEL);
148 if (pointers == NULL)
149 return -ENOMEM;
150
151 err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
152 DICE_EXT_APP_SPACE, pointers,
153 9 * sizeof(__be32) * 2, 0);
154 if (err < 0)
155 goto end;
156
157 /* Check two of them for offset have the same value or not. */
158 for (i = 0; i < 9; ++i) {
159 int j;
160
161 for (j = i + 1; j < 9; ++j) {
162 if (pointers[i * 2] == pointers[j * 2])
163 goto end;
164 }
165 }
166
167 section_addr = DICE_EXT_APP_SPACE + be32_to_cpu(pointers[12]) * 4;
168 err = detect_stream_formats(dice, section_addr);
169end:
170 kfree(pointers);
171 return err;
172}
diff --git a/sound/firewire/dice/dice-interface.h b/sound/firewire/dice/dice-interface.h
index 15a484b05298..9cad3d608229 100644
--- a/sound/firewire/dice/dice-interface.h
+++ b/sound/firewire/dice/dice-interface.h
@@ -175,13 +175,18 @@
175#define GLOBAL_SAMPLE_RATE 0x05c 175#define GLOBAL_SAMPLE_RATE 0x05c
176 176
177/* 177/*
178 * Some old firmware versions do not have the following global registers.
179 * Windows drivers produced by TCAT lost backward compatibility in its
180 * early release because they can handle firmware only which supports the
181 * following registers.
182 */
183
184/*
178 * The version of the DICE driver specification that this device conforms to; 185 * The version of the DICE driver specification that this device conforms to;
179 * read-only. 186 * read-only.
180 */ 187 */
181#define GLOBAL_VERSION 0x060 188#define GLOBAL_VERSION 0x060
182 189
183/* Some old firmware versions do not have the following global registers: */
184
185/* 190/*
186 * Supported sample rates and clock sources; read-only. 191 * Supported sample rates and clock sources; read-only.
187 */ 192 */
diff --git a/sound/firewire/dice/dice-midi.c b/sound/firewire/dice/dice-midi.c
index 8ff6da3c51f7..84eca8a51a02 100644
--- a/sound/firewire/dice/dice-midi.c
+++ b/sound/firewire/dice/dice-midi.c
@@ -101,27 +101,18 @@ int snd_dice_create_midi(struct snd_dice *dice)
101 .close = midi_close, 101 .close = midi_close,
102 .trigger = midi_playback_trigger, 102 .trigger = midi_playback_trigger,
103 }; 103 };
104 __be32 reg;
105 struct snd_rawmidi *rmidi; 104 struct snd_rawmidi *rmidi;
106 struct snd_rawmidi_str *str; 105 struct snd_rawmidi_str *str;
107 unsigned int midi_in_ports, midi_out_ports; 106 unsigned int midi_in_ports, midi_out_ports;
107 int i;
108 int err; 108 int err;
109 109
110 /* 110 midi_in_ports = 0;
111 * Use the number of MIDI conformant data channel at current sampling 111 midi_out_ports = 0;
112 * transfer frequency. 112 for (i = 0; i < MAX_STREAMS; ++i) {
113 */ 113 midi_in_ports = max(midi_in_ports, dice->tx_midi_ports[i]);
114 err = snd_dice_transaction_read_tx(dice, TX_NUMBER_MIDI, 114 midi_out_ports = max(midi_out_ports, dice->rx_midi_ports[i]);
115 &reg, sizeof(reg)); 115 }
116 if (err < 0)
117 return err;
118 midi_in_ports = be32_to_cpu(reg);
119
120 err = snd_dice_transaction_read_rx(dice, RX_NUMBER_MIDI,
121 &reg, sizeof(reg));
122 if (err < 0)
123 return err;
124 midi_out_ports = be32_to_cpu(reg);
125 116
126 if (midi_in_ports + midi_out_ports == 0) 117 if (midi_in_ports + midi_out_ports == 0)
127 return 0; 118 return 0;
diff --git a/sound/firewire/dice/dice-mytek.c b/sound/firewire/dice/dice-mytek.c
new file mode 100644
index 000000000000..eb7d5492d10b
--- /dev/null
+++ b/sound/firewire/dice/dice-mytek.c
@@ -0,0 +1,46 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * dice-mytek.c - a part of driver for DICE based devices
4 *
5 * Copyright (c) 2018 Melvin Vermeeren
6 */
7
8#include "dice.h"
9
10struct dice_mytek_spec {
11 unsigned int tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
12 unsigned int rx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
13};
14
15static const struct dice_mytek_spec stereo_192_dsd_dac = {
16 /* AES, TOSLINK, SPDIF, ADAT inputs on device */
17 .tx_pcm_chs = {{8, 8, 8}, {0, 0, 0} },
18 /* PCM 44.1-192, native DSD64/DSD128 to device */
19 .rx_pcm_chs = {{4, 4, 4}, {0, 0, 0} }
20};
21
22/*
23 * Mytek has a few other firewire-capable devices, though newer models appear
24 * to lack the port more often than not. As I don't have access to any of them
25 * they are missing here. An example is the Mytek 8x192 ADDA, which is DICE.
26 */
27
28int snd_dice_detect_mytek_formats(struct snd_dice *dice)
29{
30 int i;
31 const struct dice_mytek_spec *dev;
32
33 dev = &stereo_192_dsd_dac;
34
35 memcpy(dice->tx_pcm_chs, dev->tx_pcm_chs,
36 MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int));
37 memcpy(dice->rx_pcm_chs, dev->rx_pcm_chs,
38 MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int));
39
40 for (i = 0; i < MAX_STREAMS; ++i) {
41 dice->tx_midi_ports[i] = 0;
42 dice->rx_midi_ports[i] = 0;
43 }
44
45 return 0;
46}
diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c
index 7cb9e9713ac3..80351b29fe0d 100644
--- a/sound/firewire/dice/dice-pcm.c
+++ b/sound/firewire/dice/dice-pcm.c
@@ -9,43 +9,115 @@
9 9
10#include "dice.h" 10#include "dice.h"
11 11
12static int dice_rate_constraint(struct snd_pcm_hw_params *params,
13 struct snd_pcm_hw_rule *rule)
14{
15 struct snd_pcm_substream *substream = rule->private;
16 struct snd_dice *dice = substream->private_data;
17 unsigned int index = substream->pcm->device;
18
19 const struct snd_interval *c =
20 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
21 struct snd_interval *r =
22 hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
23 struct snd_interval rates = {
24 .min = UINT_MAX, .max = 0, .integer = 1
25 };
26 unsigned int *pcm_channels;
27 enum snd_dice_rate_mode mode;
28 unsigned int i, rate;
29
30 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
31 pcm_channels = dice->tx_pcm_chs[index];
32 else
33 pcm_channels = dice->rx_pcm_chs[index];
34
35 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
36 rate = snd_dice_rates[i];
37 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
38 continue;
39
40 if (!snd_interval_test(c, pcm_channels[mode]))
41 continue;
42
43 rates.min = min(rates.min, rate);
44 rates.max = max(rates.max, rate);
45 }
46
47 return snd_interval_refine(r, &rates);
48}
49
50static int dice_channels_constraint(struct snd_pcm_hw_params *params,
51 struct snd_pcm_hw_rule *rule)
52{
53 struct snd_pcm_substream *substream = rule->private;
54 struct snd_dice *dice = substream->private_data;
55 unsigned int index = substream->pcm->device;
56
57 const struct snd_interval *r =
58 hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
59 struct snd_interval *c =
60 hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
61 struct snd_interval channels = {
62 .min = UINT_MAX, .max = 0, .integer = 1
63 };
64 unsigned int *pcm_channels;
65 enum snd_dice_rate_mode mode;
66 unsigned int i, rate;
67
68 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
69 pcm_channels = dice->tx_pcm_chs[index];
70 else
71 pcm_channels = dice->rx_pcm_chs[index];
72
73 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
74 rate = snd_dice_rates[i];
75 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
76 continue;
77
78 if (!snd_interval_test(r, rate))
79 continue;
80
81 channels.min = min(channels.min, pcm_channels[mode]);
82 channels.max = max(channels.max, pcm_channels[mode]);
83 }
84
85 return snd_interval_refine(c, &channels);
86}
87
12static int limit_channels_and_rates(struct snd_dice *dice, 88static int limit_channels_and_rates(struct snd_dice *dice,
13 struct snd_pcm_runtime *runtime, 89 struct snd_pcm_runtime *runtime,
14 enum amdtp_stream_direction dir, 90 enum amdtp_stream_direction dir,
15 unsigned int index, unsigned int size) 91 unsigned int index)
16{ 92{
17 struct snd_pcm_hardware *hw = &runtime->hw; 93 struct snd_pcm_hardware *hw = &runtime->hw;
18 struct amdtp_stream *stream; 94 unsigned int *pcm_channels;
19 unsigned int rate; 95 unsigned int i;
20 __be32 reg; 96
21 int err; 97 if (dir == AMDTP_IN_STREAM)
22 98 pcm_channels = dice->tx_pcm_chs[index];
23 /* 99 else
24 * Retrieve current Multi Bit Linear Audio data channel and limit to 100 pcm_channels = dice->rx_pcm_chs[index];
25 * it. 101
26 */ 102 hw->channels_min = UINT_MAX;
27 if (dir == AMDTP_IN_STREAM) { 103 hw->channels_max = 0;
28 stream = &dice->tx_stream[index]; 104
29 err = snd_dice_transaction_read_tx(dice, 105 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
30 size * index + TX_NUMBER_AUDIO, 106 enum snd_dice_rate_mode mode;
31 &reg, sizeof(reg)); 107 unsigned int rate, channels;
32 } else { 108
33 stream = &dice->rx_stream[index]; 109 rate = snd_dice_rates[i];
34 err = snd_dice_transaction_read_rx(dice, 110 if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
35 size * index + RX_NUMBER_AUDIO, 111 continue;
36 &reg, sizeof(reg)); 112 hw->rates |= snd_pcm_rate_to_rate_bit(rate);
113
114 channels = pcm_channels[mode];
115 if (channels == 0)
116 continue;
117 hw->channels_min = min(hw->channels_min, channels);
118 hw->channels_max = max(hw->channels_max, channels);
37 } 119 }
38 if (err < 0)
39 return err;
40 120
41 hw->channels_min = hw->channels_max = be32_to_cpu(reg);
42
43 /* Retrieve current sampling transfer frequency and limit to it. */
44 err = snd_dice_transaction_get_rate(dice, &rate);
45 if (err < 0)
46 return err;
47
48 hw->rates = snd_pcm_rate_to_rate_bit(rate);
49 snd_pcm_limit_hw_rates(runtime); 121 snd_pcm_limit_hw_rates(runtime);
50 122
51 return 0; 123 return 0;
@@ -56,36 +128,34 @@ static int init_hw_info(struct snd_dice *dice,
56{ 128{
57 struct snd_pcm_runtime *runtime = substream->runtime; 129 struct snd_pcm_runtime *runtime = substream->runtime;
58 struct snd_pcm_hardware *hw = &runtime->hw; 130 struct snd_pcm_hardware *hw = &runtime->hw;
131 unsigned int index = substream->pcm->device;
59 enum amdtp_stream_direction dir; 132 enum amdtp_stream_direction dir;
60 struct amdtp_stream *stream; 133 struct amdtp_stream *stream;
61 __be32 reg[2];
62 unsigned int count, size;
63 int err; 134 int err;
64 135
65 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 136 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
66 hw->formats = AM824_IN_PCM_FORMAT_BITS; 137 hw->formats = AM824_IN_PCM_FORMAT_BITS;
67 dir = AMDTP_IN_STREAM; 138 dir = AMDTP_IN_STREAM;
68 stream = &dice->tx_stream[substream->pcm->device]; 139 stream = &dice->tx_stream[index];
69 err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg,
70 sizeof(reg));
71 } else { 140 } else {
72 hw->formats = AM824_OUT_PCM_FORMAT_BITS; 141 hw->formats = AM824_OUT_PCM_FORMAT_BITS;
73 dir = AMDTP_OUT_STREAM; 142 dir = AMDTP_OUT_STREAM;
74 stream = &dice->rx_stream[substream->pcm->device]; 143 stream = &dice->rx_stream[index];
75 err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg,
76 sizeof(reg));
77 } 144 }
78 145
146 err = limit_channels_and_rates(dice, substream->runtime, dir,
147 index);
79 if (err < 0) 148 if (err < 0)
80 return err; 149 return err;
81 150
82 count = min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS); 151 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
83 if (substream->pcm->device >= count) 152 dice_rate_constraint, substream,
84 return -ENXIO; 153 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
85 154 if (err < 0)
86 size = be32_to_cpu(reg[1]) * 4; 155 return err;
87 err = limit_channels_and_rates(dice, substream->runtime, dir, 156 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
88 substream->pcm->device, size); 157 dice_channels_constraint, substream,
158 SNDRV_PCM_HW_PARAM_RATE, -1);
89 if (err < 0) 159 if (err < 0)
90 return err; 160 return err;
91 161
@@ -95,6 +165,8 @@ static int init_hw_info(struct snd_dice *dice,
95static int pcm_open(struct snd_pcm_substream *substream) 165static int pcm_open(struct snd_pcm_substream *substream)
96{ 166{
97 struct snd_dice *dice = substream->private_data; 167 struct snd_dice *dice = substream->private_data;
168 unsigned int source;
169 bool internal;
98 int err; 170 int err;
99 171
100 err = snd_dice_stream_lock_try(dice); 172 err = snd_dice_stream_lock_try(dice);
@@ -105,6 +177,43 @@ static int pcm_open(struct snd_pcm_substream *substream)
105 if (err < 0) 177 if (err < 0)
106 goto err_locked; 178 goto err_locked;
107 179
180 err = snd_dice_transaction_get_clock_source(dice, &source);
181 if (err < 0)
182 goto err_locked;
183 switch (source) {
184 case CLOCK_SOURCE_AES1:
185 case CLOCK_SOURCE_AES2:
186 case CLOCK_SOURCE_AES3:
187 case CLOCK_SOURCE_AES4:
188 case CLOCK_SOURCE_AES_ANY:
189 case CLOCK_SOURCE_ADAT:
190 case CLOCK_SOURCE_TDIF:
191 case CLOCK_SOURCE_WC:
192 internal = false;
193 break;
194 default:
195 internal = true;
196 break;
197 }
198
199 /*
200 * When source of clock is not internal or any PCM streams are running,
201 * available sampling rate is limited at current sampling rate.
202 */
203 if (!internal ||
204 amdtp_stream_pcm_running(&dice->tx_stream[0]) ||
205 amdtp_stream_pcm_running(&dice->tx_stream[1]) ||
206 amdtp_stream_pcm_running(&dice->rx_stream[0]) ||
207 amdtp_stream_pcm_running(&dice->rx_stream[1])) {
208 unsigned int rate;
209
210 err = snd_dice_transaction_get_rate(dice, &rate);
211 if (err < 0)
212 goto err_locked;
213 substream->runtime->hw.rate_min = rate;
214 substream->runtime->hw.rate_max = rate;
215 }
216
108 snd_pcm_set_sync(substream); 217 snd_pcm_set_sync(substream);
109end: 218end:
110 return err; 219 return err;
@@ -318,37 +427,19 @@ int snd_dice_create_pcm(struct snd_dice *dice)
318 .page = snd_pcm_lib_get_vmalloc_page, 427 .page = snd_pcm_lib_get_vmalloc_page,
319 .mmap = snd_pcm_lib_mmap_vmalloc, 428 .mmap = snd_pcm_lib_mmap_vmalloc,
320 }; 429 };
321 __be32 reg;
322 struct snd_pcm *pcm; 430 struct snd_pcm *pcm;
323 unsigned int i, max_capture, max_playback, capture, playback; 431 unsigned int capture, playback;
432 int i, j;
324 int err; 433 int err;
325 434
326 /* Check whether PCM substreams are required. */
327 if (dice->force_two_pcms) {
328 max_capture = max_playback = 2;
329 } else {
330 max_capture = max_playback = 0;
331 err = snd_dice_transaction_read_tx(dice, TX_NUMBER, &reg,
332 sizeof(reg));
333 if (err < 0)
334 return err;
335 max_capture = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);
336
337 err = snd_dice_transaction_read_rx(dice, RX_NUMBER, &reg,
338 sizeof(reg));
339 if (err < 0)
340 return err;
341 max_playback = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);
342 }
343
344 for (i = 0; i < MAX_STREAMS; i++) { 435 for (i = 0; i < MAX_STREAMS; i++) {
345 capture = playback = 0; 436 capture = playback = 0;
346 if (i < max_capture) 437 for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j) {
347 capture = 1; 438 if (dice->tx_pcm_chs[i][j] > 0)
348 if (i < max_playback) 439 capture = 1;
349 playback = 1; 440 if (dice->rx_pcm_chs[i][j] > 0)
350 if (capture == 0 && playback == 0) 441 playback = 1;
351 break; 442 }
352 443
353 err = snd_pcm_new(dice->card, "DICE", i, playback, capture, 444 err = snd_pcm_new(dice->card, "DICE", i, playback, capture,
354 &pcm); 445 &pcm);
diff --git a/sound/firewire/dice/dice-proc.c b/sound/firewire/dice/dice-proc.c
index f5c1d1bced59..bb870fc73f99 100644
--- a/sound/firewire/dice/dice-proc.c
+++ b/sound/firewire/dice/dice-proc.c
@@ -148,12 +148,12 @@ static void dice_proc_read(struct snd_info_entry *entry,
148 >> CLOCK_RATE_SHIFT)); 148 >> CLOCK_RATE_SHIFT));
149 snd_iprintf(buffer, " ext status: %08x\n", buf.global.extended_status); 149 snd_iprintf(buffer, " ext status: %08x\n", buf.global.extended_status);
150 snd_iprintf(buffer, " sample rate: %u\n", buf.global.sample_rate); 150 snd_iprintf(buffer, " sample rate: %u\n", buf.global.sample_rate);
151 snd_iprintf(buffer, " version: %u.%u.%u.%u\n",
152 (buf.global.version >> 24) & 0xff,
153 (buf.global.version >> 16) & 0xff,
154 (buf.global.version >> 8) & 0xff,
155 (buf.global.version >> 0) & 0xff);
156 if (quadlets >= 90) { 151 if (quadlets >= 90) {
152 snd_iprintf(buffer, " version: %u.%u.%u.%u\n",
153 (buf.global.version >> 24) & 0xff,
154 (buf.global.version >> 16) & 0xff,
155 (buf.global.version >> 8) & 0xff,
156 (buf.global.version >> 0) & 0xff);
157 snd_iprintf(buffer, " clock caps:"); 157 snd_iprintf(buffer, " clock caps:");
158 for (i = 0; i <= 6; ++i) 158 for (i = 0; i <= 6; ++i)
159 if (buf.global.clock_caps & (1 << i)) 159 if (buf.global.clock_caps & (1 << i))
@@ -243,10 +243,74 @@ static void dice_proc_read(struct snd_info_entry *entry,
243 } 243 }
244} 244}
245 245
246void snd_dice_create_proc(struct snd_dice *dice) 246static void dice_proc_read_formation(struct snd_info_entry *entry,
247 struct snd_info_buffer *buffer)
248{
249 static const char *const rate_labels[] = {
250 [SND_DICE_RATE_MODE_LOW] = "low",
251 [SND_DICE_RATE_MODE_MIDDLE] = "middle",
252 [SND_DICE_RATE_MODE_HIGH] = "high",
253 };
254 struct snd_dice *dice = entry->private_data;
255 int i, j;
256
257 snd_iprintf(buffer, "Output stream from unit:\n");
258 for (i = 0; i < SND_DICE_RATE_MODE_COUNT; ++i)
259 snd_iprintf(buffer, "\t%s", rate_labels[i]);
260 snd_iprintf(buffer, "\tMIDI\n");
261 for (i = 0; i < MAX_STREAMS; ++i) {
262 snd_iprintf(buffer, "Tx %u:", i);
263 for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j)
264 snd_iprintf(buffer, "\t%u", dice->tx_pcm_chs[i][j]);
265 snd_iprintf(buffer, "\t%u\n", dice->tx_midi_ports[i]);
266 }
267
268 snd_iprintf(buffer, "Input stream to unit:\n");
269 for (i = 0; i < SND_DICE_RATE_MODE_COUNT; ++i)
270 snd_iprintf(buffer, "\t%s", rate_labels[i]);
271 snd_iprintf(buffer, "\n");
272 for (i = 0; i < MAX_STREAMS; ++i) {
273 snd_iprintf(buffer, "Rx %u:", i);
274 for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j)
275 snd_iprintf(buffer, "\t%u", dice->rx_pcm_chs[i][j]);
276 snd_iprintf(buffer, "\t%u\n", dice->rx_midi_ports[i]);
277 }
278}
279
280static void add_node(struct snd_dice *dice, struct snd_info_entry *root,
281 const char *name,
282 void (*op)(struct snd_info_entry *entry,
283 struct snd_info_buffer *buffer))
247{ 284{
248 struct snd_info_entry *entry; 285 struct snd_info_entry *entry;
249 286
250 if (!snd_card_proc_new(dice->card, "dice", &entry)) 287 entry = snd_info_create_card_entry(dice->card, name, root);
251 snd_info_set_text_ops(entry, dice, dice_proc_read); 288 if (!entry)
289 return;
290
291 snd_info_set_text_ops(entry, dice, op);
292 if (snd_info_register(entry) < 0)
293 snd_info_free_entry(entry);
294}
295
296void snd_dice_create_proc(struct snd_dice *dice)
297{
298 struct snd_info_entry *root;
299
300 /*
301 * All nodes are automatically removed at snd_card_disconnect(),
302 * by following to link list.
303 */
304 root = snd_info_create_card_entry(dice->card, "firewire",
305 dice->card->proc_root);
306 if (!root)
307 return;
308 root->mode = S_IFDIR | 0555;
309 if (snd_info_register(root) < 0) {
310 snd_info_free_entry(root);
311 return;
312 }
313
314 add_node(dice, root, "dice", dice_proc_read);
315 add_node(dice, root, "formation", dice_proc_read_formation);
252} 316}
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c
index 928a255bfc35..c3c892c5c7ff 100644
--- a/sound/firewire/dice/dice-stream.c
+++ b/sound/firewire/dice/dice-stream.c
@@ -30,13 +30,43 @@ const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
30 [6] = 192000, 30 [6] = 192000,
31}; 31};
32 32
33int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
34 enum snd_dice_rate_mode *mode)
35{
36 /* Corresponding to each entry in snd_dice_rates. */
37 static const enum snd_dice_rate_mode modes[] = {
38 [0] = SND_DICE_RATE_MODE_LOW,
39 [1] = SND_DICE_RATE_MODE_LOW,
40 [2] = SND_DICE_RATE_MODE_LOW,
41 [3] = SND_DICE_RATE_MODE_MIDDLE,
42 [4] = SND_DICE_RATE_MODE_MIDDLE,
43 [5] = SND_DICE_RATE_MODE_HIGH,
44 [6] = SND_DICE_RATE_MODE_HIGH,
45 };
46 int i;
47
48 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
49 if (!(dice->clock_caps & BIT(i)))
50 continue;
51 if (snd_dice_rates[i] != rate)
52 continue;
53
54 *mode = modes[i];
55 return 0;
56 }
57
58 return -EINVAL;
59}
60
33/* 61/*
34 * This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE 62 * This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE
35 * to GLOBAL_STATUS. Especially, just after powering on, these are different. 63 * to GLOBAL_STATUS. Especially, just after powering on, these are different.
36 */ 64 */
37static int ensure_phase_lock(struct snd_dice *dice) 65static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate)
38{ 66{
39 __be32 reg, nominal; 67 __be32 reg, nominal;
68 u32 data;
69 int i;
40 int err; 70 int err;
41 71
42 err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT, 72 err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
@@ -44,9 +74,21 @@ static int ensure_phase_lock(struct snd_dice *dice)
44 if (err < 0) 74 if (err < 0)
45 return err; 75 return err;
46 76
77 data = be32_to_cpu(reg);
78
79 data &= ~CLOCK_RATE_MASK;
80 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
81 if (snd_dice_rates[i] == rate)
82 break;
83 }
84 if (i == ARRAY_SIZE(snd_dice_rates))
85 return -EINVAL;
86 data |= i << CLOCK_RATE_SHIFT;
87
47 if (completion_done(&dice->clock_accepted)) 88 if (completion_done(&dice->clock_accepted))
48 reinit_completion(&dice->clock_accepted); 89 reinit_completion(&dice->clock_accepted);
49 90
91 reg = cpu_to_be32(data);
50 err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT, 92 err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
51 &reg, sizeof(reg)); 93 &reg, sizeof(reg));
52 if (err < 0) 94 if (err < 0)
@@ -192,6 +234,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
192 unsigned int rate, struct reg_params *params) 234 unsigned int rate, struct reg_params *params)
193{ 235{
194 __be32 reg[2]; 236 __be32 reg[2];
237 enum snd_dice_rate_mode mode;
195 unsigned int i, pcm_chs, midi_ports; 238 unsigned int i, pcm_chs, midi_ports;
196 struct amdtp_stream *streams; 239 struct amdtp_stream *streams;
197 struct fw_iso_resources *resources; 240 struct fw_iso_resources *resources;
@@ -206,12 +249,23 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
206 resources = dice->rx_resources; 249 resources = dice->rx_resources;
207 } 250 }
208 251
252 err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
253 if (err < 0)
254 return err;
255
209 for (i = 0; i < params->count; i++) { 256 for (i = 0; i < params->count; i++) {
257 unsigned int pcm_cache;
258 unsigned int midi_cache;
259
210 if (dir == AMDTP_IN_STREAM) { 260 if (dir == AMDTP_IN_STREAM) {
261 pcm_cache = dice->tx_pcm_chs[i][mode];
262 midi_cache = dice->tx_midi_ports[i];
211 err = snd_dice_transaction_read_tx(dice, 263 err = snd_dice_transaction_read_tx(dice,
212 params->size * i + TX_NUMBER_AUDIO, 264 params->size * i + TX_NUMBER_AUDIO,
213 reg, sizeof(reg)); 265 reg, sizeof(reg));
214 } else { 266 } else {
267 pcm_cache = dice->rx_pcm_chs[i][mode];
268 midi_cache = dice->rx_midi_ports[i];
215 err = snd_dice_transaction_read_rx(dice, 269 err = snd_dice_transaction_read_rx(dice,
216 params->size * i + RX_NUMBER_AUDIO, 270 params->size * i + RX_NUMBER_AUDIO,
217 reg, sizeof(reg)); 271 reg, sizeof(reg));
@@ -221,6 +275,14 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
221 pcm_chs = be32_to_cpu(reg[0]); 275 pcm_chs = be32_to_cpu(reg[0]);
222 midi_ports = be32_to_cpu(reg[1]); 276 midi_ports = be32_to_cpu(reg[1]);
223 277
278 /* These are important for developer of this driver. */
279 if (pcm_chs != pcm_cache || midi_ports != midi_cache) {
280 dev_info(&dice->unit->device,
281 "cache mismatch: pcm: %u:%u, midi: %u:%u\n",
282 pcm_chs, pcm_cache, midi_ports, midi_cache);
283 return -EPROTO;
284 }
285
224 err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports); 286 err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports);
225 if (err < 0) 287 if (err < 0)
226 return err; 288 return err;
@@ -256,6 +318,68 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
256 return err; 318 return err;
257} 319}
258 320
321static int start_duplex_streams(struct snd_dice *dice, unsigned int rate)
322{
323 struct reg_params tx_params, rx_params;
324 int i;
325 int err;
326
327 err = get_register_params(dice, &tx_params, &rx_params);
328 if (err < 0)
329 return err;
330
331 /* Stop transmission. */
332 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
333 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
334 snd_dice_transaction_clear_enable(dice);
335 release_resources(dice);
336
337 err = ensure_phase_lock(dice, rate);
338 if (err < 0) {
339 dev_err(&dice->unit->device, "fail to ensure phase lock\n");
340 return err;
341 }
342
343 /* Likely to have changed stream formats. */
344 err = get_register_params(dice, &tx_params, &rx_params);
345 if (err < 0)
346 return err;
347
348 /* Start both streams. */
349 err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
350 if (err < 0)
351 goto error;
352 err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
353 if (err < 0)
354 goto error;
355
356 err = snd_dice_transaction_set_enable(dice);
357 if (err < 0) {
358 dev_err(&dice->unit->device, "fail to enable interface\n");
359 goto error;
360 }
361
362 for (i = 0; i < MAX_STREAMS; i++) {
363 if ((i < tx_params.count &&
364 !amdtp_stream_wait_callback(&dice->tx_stream[i],
365 CALLBACK_TIMEOUT)) ||
366 (i < rx_params.count &&
367 !amdtp_stream_wait_callback(&dice->rx_stream[i],
368 CALLBACK_TIMEOUT))) {
369 err = -ETIMEDOUT;
370 goto error;
371 }
372 }
373
374 return 0;
375error:
376 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
377 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
378 snd_dice_transaction_clear_enable(dice);
379 release_resources(dice);
380 return err;
381}
382
259/* 383/*
260 * MEMO: After this function, there're two states of streams: 384 * MEMO: After this function, there're two states of streams:
261 * - None streams are running. 385 * - None streams are running.
@@ -265,17 +389,13 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
265{ 389{
266 unsigned int curr_rate; 390 unsigned int curr_rate;
267 unsigned int i; 391 unsigned int i;
268 struct reg_params tx_params, rx_params; 392 enum snd_dice_rate_mode mode;
269 bool need_to_start;
270 int err; 393 int err;
271 394
272 if (dice->substreams_counter == 0) 395 if (dice->substreams_counter == 0)
273 return -EIO; 396 return -EIO;
274 397
275 err = get_register_params(dice, &tx_params, &rx_params); 398 /* Check sampling transmission frequency. */
276 if (err < 0)
277 return err;
278
279 err = snd_dice_transaction_get_rate(dice, &curr_rate); 399 err = snd_dice_transaction_get_rate(dice, &curr_rate);
280 if (err < 0) { 400 if (err < 0) {
281 dev_err(&dice->unit->device, 401 dev_err(&dice->unit->device,
@@ -285,72 +405,36 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
285 if (rate == 0) 405 if (rate == 0)
286 rate = curr_rate; 406 rate = curr_rate;
287 if (rate != curr_rate) 407 if (rate != curr_rate)
288 return -EINVAL; 408 goto restart;
289 409
290 /* Judge to need to restart streams. */ 410 /* Check error of packet streaming. */
291 for (i = 0; i < MAX_STREAMS; i++) { 411 for (i = 0; i < MAX_STREAMS; ++i) {
292 if (i < tx_params.count) { 412 if (amdtp_streaming_error(&dice->tx_stream[i]))
293 if (amdtp_streaming_error(&dice->tx_stream[i]) || 413 break;
294 !amdtp_stream_running(&dice->tx_stream[i])) 414 if (amdtp_streaming_error(&dice->rx_stream[i]))
295 break; 415 break;
296 }
297 if (i < rx_params.count) {
298 if (amdtp_streaming_error(&dice->rx_stream[i]) ||
299 !amdtp_stream_running(&dice->rx_stream[i]))
300 break;
301 }
302 } 416 }
303 need_to_start = (i < MAX_STREAMS); 417 if (i < MAX_STREAMS)
304 418 goto restart;
305 if (need_to_start) {
306 /* Stop transmission. */
307 snd_dice_transaction_clear_enable(dice);
308 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
309 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
310 release_resources(dice);
311
312 err = ensure_phase_lock(dice);
313 if (err < 0) {
314 dev_err(&dice->unit->device,
315 "fail to ensure phase lock\n");
316 return err;
317 }
318 419
319 /* Start both streams. */ 420 /* Check required streams are running or not. */
320 err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params); 421 err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
321 if (err < 0) 422 if (err < 0)
322 goto error; 423 return err;
323 err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params); 424 for (i = 0; i < MAX_STREAMS; ++i) {
324 if (err < 0) 425 if (dice->tx_pcm_chs[i][mode] > 0 &&
325 goto error; 426 !amdtp_stream_running(&dice->tx_stream[i]))
326 427 break;
327 err = snd_dice_transaction_set_enable(dice); 428 if (dice->rx_pcm_chs[i][mode] > 0 &&
328 if (err < 0) { 429 !amdtp_stream_running(&dice->rx_stream[i]))
329 dev_err(&dice->unit->device, 430 break;
330 "fail to enable interface\n");
331 goto error;
332 }
333
334 for (i = 0; i < MAX_STREAMS; i++) {
335 if ((i < tx_params.count &&
336 !amdtp_stream_wait_callback(&dice->tx_stream[i],
337 CALLBACK_TIMEOUT)) ||
338 (i < rx_params.count &&
339 !amdtp_stream_wait_callback(&dice->rx_stream[i],
340 CALLBACK_TIMEOUT))) {
341 err = -ETIMEDOUT;
342 goto error;
343 }
344 }
345 } 431 }
432 if (i < MAX_STREAMS)
433 goto restart;
346 434
347 return err; 435 return 0;
348error: 436restart:
349 snd_dice_transaction_clear_enable(dice); 437 return start_duplex_streams(dice, rate);
350 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
351 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
352 release_resources(dice);
353 return err;
354} 438}
355 439
356/* 440/*
@@ -484,6 +568,69 @@ void snd_dice_stream_update_duplex(struct snd_dice *dice)
484 } 568 }
485} 569}
486 570
571int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
572{
573 unsigned int rate;
574 enum snd_dice_rate_mode mode;
575 __be32 reg[2];
576 struct reg_params tx_params, rx_params;
577 int i;
578 int err;
579
580 /* If extended protocol is available, detect detail spec. */
581 err = snd_dice_detect_extension_formats(dice);
582 if (err >= 0)
583 return err;
584
585 /*
586 * Available stream format is restricted at current mode of sampling
587 * clock.
588 */
589 err = snd_dice_transaction_get_rate(dice, &rate);
590 if (err < 0)
591 return err;
592
593 err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
594 if (err < 0)
595 return err;
596
597 /*
598 * Just after owning the unit (GLOBAL_OWNER), the unit can return
599 * invalid stream formats. Selecting clock parameters have an effect
600 * for the unit to refine it.
601 */
602 err = ensure_phase_lock(dice, rate);
603 if (err < 0)
604 return err;
605
606 err = get_register_params(dice, &tx_params, &rx_params);
607 if (err < 0)
608 return err;
609
610 for (i = 0; i < tx_params.count; ++i) {
611 err = snd_dice_transaction_read_tx(dice,
612 tx_params.size * i + TX_NUMBER_AUDIO,
613 reg, sizeof(reg));
614 if (err < 0)
615 return err;
616 dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
617 dice->tx_midi_ports[i] = max_t(unsigned int,
618 be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);
619 }
620 for (i = 0; i < rx_params.count; ++i) {
621 err = snd_dice_transaction_read_rx(dice,
622 rx_params.size * i + RX_NUMBER_AUDIO,
623 reg, sizeof(reg));
624 if (err < 0)
625 return err;
626 dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
627 dice->rx_midi_ports[i] = max_t(unsigned int,
628 be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);
629 }
630
631 return 0;
632}
633
487static void dice_lock_changed(struct snd_dice *dice) 634static void dice_lock_changed(struct snd_dice *dice)
488{ 635{
489 dice->dev_lock_changed = true; 636 dice->dev_lock_changed = true;
diff --git a/sound/firewire/dice/dice-tcelectronic.c b/sound/firewire/dice/dice-tcelectronic.c
new file mode 100644
index 000000000000..a8875d24ba2a
--- /dev/null
+++ b/sound/firewire/dice/dice-tcelectronic.c
@@ -0,0 +1,104 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * dice-tc_electronic.c - a part of driver for DICE based devices
4 *
5 * Copyright (c) 2018 Takashi Sakamoto
6 */
7
8#include "dice.h"
9
10struct dice_tc_spec {
11 unsigned int tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
12 unsigned int rx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
13 bool has_midi;
14};
15
16static const struct dice_tc_spec desktop_konnekt6 = {
17 .tx_pcm_chs = {{6, 6, 2}, {0, 0, 0} },
18 .rx_pcm_chs = {{6, 6, 4}, {0, 0, 0} },
19 .has_midi = false,
20};
21
22static const struct dice_tc_spec impact_twin = {
23 .tx_pcm_chs = {{14, 10, 6}, {0, 0, 0} },
24 .rx_pcm_chs = {{14, 10, 6}, {0, 0, 0} },
25 .has_midi = true,
26};
27
28static const struct dice_tc_spec konnekt_8 = {
29 .tx_pcm_chs = {{4, 4, 3}, {0, 0, 0} },
30 .rx_pcm_chs = {{4, 4, 3}, {0, 0, 0} },
31 .has_midi = true,
32};
33
34static const struct dice_tc_spec konnekt_24d = {
35 .tx_pcm_chs = {{16, 16, 6}, {0, 0, 0} },
36 .rx_pcm_chs = {{16, 16, 6}, {0, 0, 0} },
37 .has_midi = true,
38};
39
40static const struct dice_tc_spec konnekt_live = {
41 .tx_pcm_chs = {{16, 16, 16}, {0, 0, 0} },
42 .rx_pcm_chs = {{16, 16, 16}, {0, 0, 0} },
43 .has_midi = true,
44};
45
46static const struct dice_tc_spec studio_konnekt_48 = {
47 .tx_pcm_chs = {{16, 16, 8}, {16, 16, 7} },
48 .rx_pcm_chs = {{16, 16, 8}, {14, 14, 7} },
49 .has_midi = true,
50};
51
52static const struct dice_tc_spec digital_konnekt_x32 = {
53 .tx_pcm_chs = {{16, 16, 4}, {0, 0, 0} },
54 .rx_pcm_chs = {{16, 16, 4}, {0, 0, 0} },
55 .has_midi = false,
56};
57
58int snd_dice_detect_tcelectronic_formats(struct snd_dice *dice)
59{
60 static const struct {
61 u32 model_id;
62 const struct dice_tc_spec *spec;
63 } *entry, entries[] = {
64 {0x00000020, &konnekt_24d},
65 {0x00000021, &konnekt_8},
66 {0x00000022, &studio_konnekt_48},
67 {0x00000023, &konnekt_live},
68 {0x00000024, &desktop_konnekt6},
69 {0x00000027, &impact_twin},
70 {0x00000030, &digital_konnekt_x32},
71 };
72 struct fw_csr_iterator it;
73 int key, val, model_id;
74 int i;
75
76 model_id = 0;
77 fw_csr_iterator_init(&it, dice->unit->directory);
78 while (fw_csr_iterator_next(&it, &key, &val)) {
79 if (key == CSR_MODEL) {
80 model_id = val;
81 break;
82 }
83 }
84
85 for (i = 0; i < ARRAY_SIZE(entries); ++i) {
86 entry = entries + i;
87 if (entry->model_id == model_id)
88 break;
89 }
90 if (i == ARRAY_SIZE(entries))
91 return -ENODEV;
92
93 memcpy(dice->tx_pcm_chs, entry->spec->tx_pcm_chs,
94 MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int));
95 memcpy(dice->rx_pcm_chs, entry->spec->rx_pcm_chs,
96 MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int));
97
98 if (entry->spec->has_midi) {
99 dice->tx_midi_ports[0] = 1;
100 dice->rx_midi_ports[0] = 1;
101 }
102
103 return 0;
104}
diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c
index 0f0350320ae8..b7e138b5abcf 100644
--- a/sound/firewire/dice/dice-transaction.c
+++ b/sound/firewire/dice/dice-transaction.c
@@ -265,7 +265,7 @@ int snd_dice_transaction_reinit(struct snd_dice *dice)
265static int get_subaddrs(struct snd_dice *dice) 265static int get_subaddrs(struct snd_dice *dice)
266{ 266{
267 static const int min_values[10] = { 267 static const int min_values[10] = {
268 10, 0x64 / 4, 268 10, 0x60 / 4,
269 10, 0x18 / 4, 269 10, 0x18 / 4,
270 10, 0x18 / 4, 270 10, 0x18 / 4,
271 0, 0, 271 0, 0,
@@ -301,33 +301,40 @@ static int get_subaddrs(struct snd_dice *dice)
301 } 301 }
302 } 302 }
303 303
304 /* 304 if (be32_to_cpu(pointers[1]) > 0x18) {
305 * Check that the implemented DICE driver specification major version 305 /*
306 * number matches. 306 * Check that the implemented DICE driver specification major
307 */ 307 * version number matches.
308 err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, 308 */
309 DICE_PRIVATE_SPACE + 309 err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
310 be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION, 310 DICE_PRIVATE_SPACE +
311 &version, sizeof(version), 0); 311 be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
312 if (err < 0) 312 &version, sizeof(version), 0);
313 goto end; 313 if (err < 0)
314 goto end;
314 315
315 if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) { 316 if ((version & cpu_to_be32(0xff000000)) !=
316 dev_err(&dice->unit->device, 317 cpu_to_be32(0x01000000)) {
317 "unknown DICE version: 0x%08x\n", be32_to_cpu(version)); 318 dev_err(&dice->unit->device,
318 err = -ENODEV; 319 "unknown DICE version: 0x%08x\n",
319 goto end; 320 be32_to_cpu(version));
321 err = -ENODEV;
322 goto end;
323 }
324
325 /* Set up later. */
326 dice->clock_caps = 1;
320 } 327 }
321 328
322 dice->global_offset = be32_to_cpu(pointers[0]) * 4; 329 dice->global_offset = be32_to_cpu(pointers[0]) * 4;
323 dice->tx_offset = be32_to_cpu(pointers[2]) * 4; 330 dice->tx_offset = be32_to_cpu(pointers[2]) * 4;
324 dice->rx_offset = be32_to_cpu(pointers[4]) * 4; 331 dice->rx_offset = be32_to_cpu(pointers[4]) * 4;
325 dice->sync_offset = be32_to_cpu(pointers[6]) * 4;
326 dice->rsrv_offset = be32_to_cpu(pointers[8]) * 4;
327 332
328 /* Set up later. */ 333 /* Old firmware doesn't support these fields. */
329 if (be32_to_cpu(pointers[1]) * 4 >= GLOBAL_CLOCK_CAPABILITIES + 4) 334 if (pointers[7])
330 dice->clock_caps = 1; 335 dice->sync_offset = be32_to_cpu(pointers[6]) * 4;
336 if (pointers[9])
337 dice->rsrv_offset = be32_to_cpu(pointers[8]) * 4;
331end: 338end:
332 kfree(pointers); 339 kfree(pointers);
333 return err; 340 return err;
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c
index 96bb01b6b751..774eb2205668 100644
--- a/sound/firewire/dice/dice.c
+++ b/sound/firewire/dice/dice.c
@@ -15,40 +15,15 @@ MODULE_LICENSE("GPL v2");
15#define OUI_LOUD 0x000ff2 15#define OUI_LOUD 0x000ff2
16#define OUI_FOCUSRITE 0x00130e 16#define OUI_FOCUSRITE 0x00130e
17#define OUI_TCELECTRONIC 0x000166 17#define OUI_TCELECTRONIC 0x000166
18#define OUI_ALESIS 0x000595
19#define OUI_MAUDIO 0x000d6c
20#define OUI_MYTEK 0x001ee8
18 21
19#define DICE_CATEGORY_ID 0x04 22#define DICE_CATEGORY_ID 0x04
20#define WEISS_CATEGORY_ID 0x00 23#define WEISS_CATEGORY_ID 0x00
21#define LOUD_CATEGORY_ID 0x10 24#define LOUD_CATEGORY_ID 0x10
22 25
23/* 26#define MODEL_ALESIS_IO_BOTH 0x000001
24 * Some models support several isochronous channels, while these streams are not
25 * always available. In this case, add the model name to this list.
26 */
27static bool force_two_pcm_support(struct fw_unit *unit)
28{
29 static const char *const models[] = {
30 /* TC Electronic models. */
31 "StudioKonnekt48",
32 /* Focusrite models. */
33 "SAFFIRE_PRO_40",
34 "LIQUID_SAFFIRE_56",
35 "SAFFIRE_PRO_40_1",
36 };
37 char model[32];
38 unsigned int i;
39 int err;
40
41 err = fw_csr_string(unit->directory, CSR_MODEL, model, sizeof(model));
42 if (err < 0)
43 return false;
44
45 for (i = 0; i < ARRAY_SIZE(models); i++) {
46 if (strcmp(models[i], model) == 0)
47 break;
48 }
49
50 return i < ARRAY_SIZE(models);
51}
52 27
53static int check_dice_category(struct fw_unit *unit) 28static int check_dice_category(struct fw_unit *unit)
54{ 29{
@@ -75,11 +50,6 @@ static int check_dice_category(struct fw_unit *unit)
75 } 50 }
76 } 51 }
77 52
78 if (vendor == OUI_FOCUSRITE || vendor == OUI_TCELECTRONIC) {
79 if (force_two_pcm_support(unit))
80 return 0;
81 }
82
83 if (vendor == OUI_WEISS) 53 if (vendor == OUI_WEISS)
84 category = WEISS_CATEGORY_ID; 54 category = WEISS_CATEGORY_ID;
85 else if (vendor == OUI_LOUD) 55 else if (vendor == OUI_LOUD)
@@ -186,9 +156,6 @@ static void do_registration(struct work_struct *work)
186 if (err < 0) 156 if (err < 0)
187 return; 157 return;
188 158
189 if (force_two_pcm_support(dice->unit))
190 dice->force_two_pcms = true;
191
192 err = snd_dice_transaction_init(dice); 159 err = snd_dice_transaction_init(dice);
193 if (err < 0) 160 if (err < 0)
194 goto error; 161 goto error;
@@ -199,6 +166,10 @@ static void do_registration(struct work_struct *work)
199 166
200 dice_card_strings(dice); 167 dice_card_strings(dice);
201 168
169 err = dice->detect_formats(dice);
170 if (err < 0)
171 goto error;
172
202 err = snd_dice_stream_init_duplex(dice); 173 err = snd_dice_stream_init_duplex(dice);
203 if (err < 0) 174 if (err < 0)
204 goto error; 175 goto error;
@@ -239,14 +210,17 @@ error:
239 "Sound card registration failed: %d\n", err); 210 "Sound card registration failed: %d\n", err);
240} 211}
241 212
242static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) 213static int dice_probe(struct fw_unit *unit,
214 const struct ieee1394_device_id *entry)
243{ 215{
244 struct snd_dice *dice; 216 struct snd_dice *dice;
245 int err; 217 int err;
246 218
247 err = check_dice_category(unit); 219 if (!entry->driver_data) {
248 if (err < 0) 220 err = check_dice_category(unit);
249 return -ENODEV; 221 if (err < 0)
222 return -ENODEV;
223 }
250 224
251 /* Allocate this independent of sound card instance. */ 225 /* Allocate this independent of sound card instance. */
252 dice = kzalloc(sizeof(struct snd_dice), GFP_KERNEL); 226 dice = kzalloc(sizeof(struct snd_dice), GFP_KERNEL);
@@ -256,6 +230,13 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
256 dice->unit = fw_unit_get(unit); 230 dice->unit = fw_unit_get(unit);
257 dev_set_drvdata(&unit->device, dice); 231 dev_set_drvdata(&unit->device, dice);
258 232
233 if (!entry->driver_data) {
234 dice->detect_formats = snd_dice_stream_detect_current_formats;
235 } else {
236 dice->detect_formats =
237 (snd_dice_detect_formats_t)entry->driver_data;
238 }
239
259 spin_lock_init(&dice->lock); 240 spin_lock_init(&dice->lock);
260 mutex_init(&dice->mutex); 241 mutex_init(&dice->mutex);
261 init_completion(&dice->clock_accepted); 242 init_completion(&dice->clock_accepted);
@@ -313,16 +294,97 @@ static void dice_bus_reset(struct fw_unit *unit)
313#define DICE_INTERFACE 0x000001 294#define DICE_INTERFACE 0x000001
314 295
315static const struct ieee1394_device_id dice_id_table[] = { 296static const struct ieee1394_device_id dice_id_table[] = {
297 /* M-Audio Profire 2626 has a different value in version field. */
316 { 298 {
317 .match_flags = IEEE1394_MATCH_VERSION, 299 .match_flags = IEEE1394_MATCH_VENDOR_ID |
318 .version = DICE_INTERFACE, 300 IEEE1394_MATCH_MODEL_ID,
301 .vendor_id = OUI_MAUDIO,
302 .model_id = 0x000010,
303 .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
319 }, 304 },
320 /* M-Audio Profire 610/2626 has a different value in version field. */ 305 /* M-Audio Profire 610 has a different value in version field. */
321 { 306 {
322 .match_flags = IEEE1394_MATCH_VENDOR_ID | 307 .match_flags = IEEE1394_MATCH_VENDOR_ID |
323 IEEE1394_MATCH_SPECIFIER_ID, 308 IEEE1394_MATCH_MODEL_ID,
324 .vendor_id = 0x000d6c, 309 .vendor_id = OUI_MAUDIO,
325 .specifier_id = 0x000d6c, 310 .model_id = 0x000011,
311 .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
312 },
313 /* TC Electronic Konnekt 24D. */
314 {
315 .match_flags = IEEE1394_MATCH_VENDOR_ID |
316 IEEE1394_MATCH_MODEL_ID,
317 .vendor_id = OUI_TCELECTRONIC,
318 .model_id = 0x000020,
319 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
320 },
321 /* TC Electronic Konnekt 8. */
322 {
323 .match_flags = IEEE1394_MATCH_VENDOR_ID |
324 IEEE1394_MATCH_MODEL_ID,
325 .vendor_id = OUI_TCELECTRONIC,
326 .model_id = 0x000021,
327 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
328 },
329 /* TC Electronic Studio Konnekt 48. */
330 {
331 .match_flags = IEEE1394_MATCH_VENDOR_ID |
332 IEEE1394_MATCH_MODEL_ID,
333 .vendor_id = OUI_TCELECTRONIC,
334 .model_id = 0x000022,
335 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
336 },
337 /* TC Electronic Konnekt Live. */
338 {
339 .match_flags = IEEE1394_MATCH_VENDOR_ID |
340 IEEE1394_MATCH_MODEL_ID,
341 .vendor_id = OUI_TCELECTRONIC,
342 .model_id = 0x000023,
343 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
344 },
345 /* TC Electronic Desktop Konnekt 6. */
346 {
347 .match_flags = IEEE1394_MATCH_VENDOR_ID |
348 IEEE1394_MATCH_MODEL_ID,
349 .vendor_id = OUI_TCELECTRONIC,
350 .model_id = 0x000024,
351 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
352 },
353 /* TC Electronic Impact Twin. */
354 {
355 .match_flags = IEEE1394_MATCH_VENDOR_ID |
356 IEEE1394_MATCH_MODEL_ID,
357 .vendor_id = OUI_TCELECTRONIC,
358 .model_id = 0x000027,
359 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
360 },
361 /* TC Electronic Digital Konnekt x32. */
362 {
363 .match_flags = IEEE1394_MATCH_VENDOR_ID |
364 IEEE1394_MATCH_MODEL_ID,
365 .vendor_id = OUI_TCELECTRONIC,
366 .model_id = 0x000030,
367 .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
368 },
369 /* Alesis iO14/iO26. */
370 {
371 .match_flags = IEEE1394_MATCH_VENDOR_ID |
372 IEEE1394_MATCH_MODEL_ID,
373 .vendor_id = OUI_ALESIS,
374 .model_id = MODEL_ALESIS_IO_BOTH,
375 .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_formats,
376 },
377 /* Mytek Stereo 192 DSD-DAC. */
378 {
379 .match_flags = IEEE1394_MATCH_VENDOR_ID |
380 IEEE1394_MATCH_MODEL_ID,
381 .vendor_id = OUI_MYTEK,
382 .model_id = 0x000002,
383 .driver_data = (kernel_ulong_t)snd_dice_detect_mytek_formats,
384 },
385 {
386 .match_flags = IEEE1394_MATCH_VERSION,
387 .version = DICE_INTERFACE,
326 }, 388 },
327 { } 389 { }
328}; 390};
diff --git a/sound/firewire/dice/dice.h b/sound/firewire/dice/dice.h
index da00e75e09d4..83353a3559e8 100644
--- a/sound/firewire/dice/dice.h
+++ b/sound/firewire/dice/dice.h
@@ -63,6 +63,16 @@
63 */ 63 */
64#define MAX_STREAMS 2 64#define MAX_STREAMS 2
65 65
66enum snd_dice_rate_mode {
67 SND_DICE_RATE_MODE_LOW = 0,
68 SND_DICE_RATE_MODE_MIDDLE,
69 SND_DICE_RATE_MODE_HIGH,
70 SND_DICE_RATE_MODE_COUNT,
71};
72
73struct snd_dice;
74typedef int (*snd_dice_detect_formats_t)(struct snd_dice *dice);
75
66struct snd_dice { 76struct snd_dice {
67 struct snd_card *card; 77 struct snd_card *card;
68 struct fw_unit *unit; 78 struct fw_unit *unit;
@@ -80,6 +90,11 @@ struct snd_dice {
80 unsigned int rsrv_offset; 90 unsigned int rsrv_offset;
81 91
82 unsigned int clock_caps; 92 unsigned int clock_caps;
93 unsigned int tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
94 unsigned int rx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
95 unsigned int tx_midi_ports[MAX_STREAMS];
96 unsigned int rx_midi_ports[MAX_STREAMS];
97 snd_dice_detect_formats_t detect_formats;
83 98
84 struct fw_address_handler notification_handler; 99 struct fw_address_handler notification_handler;
85 int owner_generation; 100 int owner_generation;
@@ -98,8 +113,6 @@ struct snd_dice {
98 bool global_enabled; 113 bool global_enabled;
99 struct completion clock_accepted; 114 struct completion clock_accepted;
100 unsigned int substreams_counter; 115 unsigned int substreams_counter;
101
102 bool force_two_pcms;
103}; 116};
104 117
105enum snd_dice_addr_type { 118enum snd_dice_addr_type {
@@ -190,11 +203,14 @@ void snd_dice_transaction_destroy(struct snd_dice *dice);
190#define SND_DICE_RATES_COUNT 7 203#define SND_DICE_RATES_COUNT 7
191extern const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT]; 204extern const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT];
192 205
206int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
207 enum snd_dice_rate_mode *mode);
193int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate); 208int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate);
194void snd_dice_stream_stop_duplex(struct snd_dice *dice); 209void snd_dice_stream_stop_duplex(struct snd_dice *dice);
195int snd_dice_stream_init_duplex(struct snd_dice *dice); 210int snd_dice_stream_init_duplex(struct snd_dice *dice);
196void snd_dice_stream_destroy_duplex(struct snd_dice *dice); 211void snd_dice_stream_destroy_duplex(struct snd_dice *dice);
197void snd_dice_stream_update_duplex(struct snd_dice *dice); 212void snd_dice_stream_update_duplex(struct snd_dice *dice);
213int snd_dice_stream_detect_current_formats(struct snd_dice *dice);
198 214
199int snd_dice_stream_lock_try(struct snd_dice *dice); 215int snd_dice_stream_lock_try(struct snd_dice *dice);
200void snd_dice_stream_lock_release(struct snd_dice *dice); 216void snd_dice_stream_lock_release(struct snd_dice *dice);
@@ -207,4 +223,9 @@ void snd_dice_create_proc(struct snd_dice *dice);
207 223
208int snd_dice_create_midi(struct snd_dice *dice); 224int snd_dice_create_midi(struct snd_dice *dice);
209 225
226int snd_dice_detect_tcelectronic_formats(struct snd_dice *dice);
227int snd_dice_detect_alesis_formats(struct snd_dice *dice);
228int snd_dice_detect_extension_formats(struct snd_dice *dice);
229int snd_dice_detect_mytek_formats(struct snd_dice *dice);
230
210#endif 231#endif