diff options
author | Takashi Iwai <tiwai@suse.de> | 2018-06-04 05:41:48 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2018-06-04 05:42:27 -0400 |
commit | cdbc653a04ee692a7105a96e8dd6055d9971d45c (patch) | |
tree | c1282680b3115edfd693a27bc6758208534ac557 /sound/firewire/dice | |
parent | 009f8c90f571d87855914dbc20e6c0ea2a3b19ae (diff) | |
parent | ceec4684085a9e4dc60439d84ab47ce260444804 (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/Makefile | 3 | ||||
-rw-r--r-- | sound/firewire/dice/dice-alesis.c | 52 | ||||
-rw-r--r-- | sound/firewire/dice/dice-extension.c | 172 | ||||
-rw-r--r-- | sound/firewire/dice/dice-interface.h | 9 | ||||
-rw-r--r-- | sound/firewire/dice/dice-midi.c | 23 | ||||
-rw-r--r-- | sound/firewire/dice/dice-mytek.c | 46 | ||||
-rw-r--r-- | sound/firewire/dice/dice-pcm.c | 233 | ||||
-rw-r--r-- | sound/firewire/dice/dice-proc.c | 80 | ||||
-rw-r--r-- | sound/firewire/dice/dice-stream.c | 283 | ||||
-rw-r--r-- | sound/firewire/dice/dice-tcelectronic.c | 104 | ||||
-rw-r--r-- | sound/firewire/dice/dice-transaction.c | 49 | ||||
-rw-r--r-- | sound/firewire/dice/dice.c | 156 | ||||
-rw-r--r-- | sound/firewire/dice/dice.h | 25 |
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 @@ | |||
1 | snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \ | 1 | snd-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 | ||
3 | obj-$(CONFIG_SND_DICE) += snd-dice.o | 4 | obj-$(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 | |||
10 | static const unsigned int | ||
11 | alesis_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 | |||
16 | static const unsigned int | ||
17 | alesis_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 | |||
22 | int 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, ®, | ||
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 | |||
50 | static 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 | |||
59 | static 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 | |||
84 | static 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 | ®, 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 | |||
140 | int 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); | ||
169 | end: | ||
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 | ®, 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 | ®, 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 | |||
10 | struct 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 | |||
15 | static 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 | |||
28 | int 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 | ||
12 | static 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 | |||
50 | static 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 | |||
12 | static int limit_channels_and_rates(struct snd_dice *dice, | 88 | static 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 | ®, 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 | ®, 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, | |||
95 | static int pcm_open(struct snd_pcm_substream *substream) | 165 | static 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); |
109 | end: | 218 | end: |
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, ®, | ||
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, ®, | ||
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 | ||
246 | void snd_dice_create_proc(struct snd_dice *dice) | 246 | static 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 | |||
280 | static 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 | |||
296 | void 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 | ||
33 | int 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 | */ |
37 | static int ensure_phase_lock(struct snd_dice *dice) | 65 | static 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 | ®, sizeof(reg)); | 93 | ®, 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 | ||
321 | static 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; | ||
375 | error: | ||
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; |
348 | error: | 436 | restart: |
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 | ||
571 | int 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 | |||
487 | static void dice_lock_changed(struct snd_dice *dice) | 634 | static 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 | |||
10 | struct 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 | |||
16 | static 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 | |||
22 | static 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 | |||
28 | static 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 | |||
34 | static 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 | |||
40 | static 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 | |||
46 | static 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 | |||
52 | static 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 | |||
58 | int 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) | |||
265 | static int get_subaddrs(struct snd_dice *dice) | 265 | static 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; | ||
331 | end: | 338 | end: |
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 | */ | ||
27 | static 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 | ||
53 | static int check_dice_category(struct fw_unit *unit) | 28 | static 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 | ||
242 | static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) | 213 | static 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 | ||
315 | static const struct ieee1394_device_id dice_id_table[] = { | 296 | static 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 | ||
66 | enum 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 | |||
73 | struct snd_dice; | ||
74 | typedef int (*snd_dice_detect_formats_t)(struct snd_dice *dice); | ||
75 | |||
66 | struct snd_dice { | 76 | struct 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 | ||
105 | enum snd_dice_addr_type { | 118 | enum 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 |
191 | extern const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT]; | 204 | extern const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT]; |
192 | 205 | ||
206 | int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate, | ||
207 | enum snd_dice_rate_mode *mode); | ||
193 | int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate); | 208 | int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate); |
194 | void snd_dice_stream_stop_duplex(struct snd_dice *dice); | 209 | void snd_dice_stream_stop_duplex(struct snd_dice *dice); |
195 | int snd_dice_stream_init_duplex(struct snd_dice *dice); | 210 | int snd_dice_stream_init_duplex(struct snd_dice *dice); |
196 | void snd_dice_stream_destroy_duplex(struct snd_dice *dice); | 211 | void snd_dice_stream_destroy_duplex(struct snd_dice *dice); |
197 | void snd_dice_stream_update_duplex(struct snd_dice *dice); | 212 | void snd_dice_stream_update_duplex(struct snd_dice *dice); |
213 | int snd_dice_stream_detect_current_formats(struct snd_dice *dice); | ||
198 | 214 | ||
199 | int snd_dice_stream_lock_try(struct snd_dice *dice); | 215 | int snd_dice_stream_lock_try(struct snd_dice *dice); |
200 | void snd_dice_stream_lock_release(struct snd_dice *dice); | 216 | void snd_dice_stream_lock_release(struct snd_dice *dice); |
@@ -207,4 +223,9 @@ void snd_dice_create_proc(struct snd_dice *dice); | |||
207 | 223 | ||
208 | int snd_dice_create_midi(struct snd_dice *dice); | 224 | int snd_dice_create_midi(struct snd_dice *dice); |
209 | 225 | ||
226 | int snd_dice_detect_tcelectronic_formats(struct snd_dice *dice); | ||
227 | int snd_dice_detect_alesis_formats(struct snd_dice *dice); | ||
228 | int snd_dice_detect_extension_formats(struct snd_dice *dice); | ||
229 | int snd_dice_detect_mytek_formats(struct snd_dice *dice); | ||
230 | |||
210 | #endif | 231 | #endif |