blob: f99e00083141ec551cfce818dcf6196ed8b94b11 [file] [log] [blame]
Thomas Gleixnerda607e12019-05-29 16:57:59 -07001// SPDX-License-Identifier: GPL-2.0-only
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +09002/*
3 * dice_stream.c - a part of driver for DICE based devices
4 *
5 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
6 * Copyright (c) 2014 Takashi Sakamoto <o-takashi@sakamocchi.jp>
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +09007 */
8
9#include "dice.h"
10
Takashi Sakamotobdaedca2021-05-20 13:01:54 +090011#define READY_TIMEOUT_MS 200
Takashi Sakamoto41319eb2021-06-01 17:17:51 +090012#define NOTIFICATION_TIMEOUT_MS 100
Takashi Sakamoto288a8d02014-12-09 00:10:35 +090013
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +090014struct reg_params {
15 unsigned int count;
16 unsigned int size;
17};
18
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +090019const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
20 /* mode 0 */
21 [0] = 32000,
22 [1] = 44100,
23 [2] = 48000,
24 /* mode 1 */
25 [3] = 88200,
26 [4] = 96000,
27 /* mode 2 */
28 [5] = 176400,
29 [6] = 192000,
30};
31
Takashi Sakamotob60152f2018-05-02 19:16:42 +090032int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
33 enum snd_dice_rate_mode *mode)
34{
35 /* Corresponding to each entry in snd_dice_rates. */
36 static const enum snd_dice_rate_mode modes[] = {
37 [0] = SND_DICE_RATE_MODE_LOW,
38 [1] = SND_DICE_RATE_MODE_LOW,
39 [2] = SND_DICE_RATE_MODE_LOW,
40 [3] = SND_DICE_RATE_MODE_MIDDLE,
41 [4] = SND_DICE_RATE_MODE_MIDDLE,
42 [5] = SND_DICE_RATE_MODE_HIGH,
43 [6] = SND_DICE_RATE_MODE_HIGH,
44 };
45 int i;
46
47 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
48 if (!(dice->clock_caps & BIT(i)))
49 continue;
50 if (snd_dice_rates[i] != rate)
51 continue;
52
53 *mode = modes[i];
54 return 0;
55 }
56
57 return -EINVAL;
58}
59
Takashi Sakamoto41319eb2021-06-01 17:17:51 +090060static int select_clock(struct snd_dice *dice, unsigned int rate)
Takashi Sakamotodfabc0e2016-02-08 22:54:20 +090061{
Takashi Sakamoto41319eb2021-06-01 17:17:51 +090062 __be32 reg;
Takashi Sakamotoafa617f2018-05-02 19:16:48 +090063 u32 data;
64 int i;
Takashi Sakamotodfabc0e2016-02-08 22:54:20 +090065 int err;
66
67 err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
68 &reg, sizeof(reg));
69 if (err < 0)
70 return err;
71
Takashi Sakamotoafa617f2018-05-02 19:16:48 +090072 data = be32_to_cpu(reg);
73
74 data &= ~CLOCK_RATE_MASK;
75 for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
76 if (snd_dice_rates[i] == rate)
77 break;
78 }
79 if (i == ARRAY_SIZE(snd_dice_rates))
80 return -EINVAL;
81 data |= i << CLOCK_RATE_SHIFT;
82
Takashi Sakamotodfabc0e2016-02-08 22:54:20 +090083 if (completion_done(&dice->clock_accepted))
84 reinit_completion(&dice->clock_accepted);
85
Takashi Sakamotoafa617f2018-05-02 19:16:48 +090086 reg = cpu_to_be32(data);
Takashi Sakamotodfabc0e2016-02-08 22:54:20 +090087 err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
88 &reg, sizeof(reg));
89 if (err < 0)
90 return err;
91
92 if (wait_for_completion_timeout(&dice->clock_accepted,
Takashi Sakamoto41319eb2021-06-01 17:17:51 +090093 msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0)
94 return -ETIMEDOUT;
Takashi Sakamotodfabc0e2016-02-08 22:54:20 +090095
96 return 0;
97}
98
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +090099static int get_register_params(struct snd_dice *dice,
100 struct reg_params *tx_params,
101 struct reg_params *rx_params)
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900102{
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900103 __be32 reg[2];
104 int err;
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900105
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900106 err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg));
107 if (err < 0)
108 return err;
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900109 tx_params->count =
110 min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
111 tx_params->size = be32_to_cpu(reg[1]) * 4;
Takashi Sakamoto288a8d02014-12-09 00:10:35 +0900112
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900113 err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg));
114 if (err < 0)
115 return err;
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900116 rx_params->count =
117 min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
118 rx_params->size = be32_to_cpu(reg[1]) * 4;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900119
120 return 0;
121}
122
123static void release_resources(struct snd_dice *dice)
124{
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900125 int i;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900126
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900127 for (i = 0; i < MAX_STREAMS; ++i) {
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900128 fw_iso_resources_free(&dice->tx_resources[i]);
129 fw_iso_resources_free(&dice->rx_resources[i]);
130 }
131}
132
133static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900134 struct reg_params *params)
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900135{
136 __be32 reg;
137 unsigned int i;
138
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900139 for (i = 0; i < params->count; i++) {
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900140 reg = cpu_to_be32((u32)-1);
141 if (dir == AMDTP_IN_STREAM) {
142 snd_dice_transaction_write_tx(dice,
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900143 params->size * i + TX_ISOCHRONOUS,
144 &reg, sizeof(reg));
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900145 } else {
146 snd_dice_transaction_write_rx(dice,
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900147 params->size * i + RX_ISOCHRONOUS,
148 &reg, sizeof(reg));
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900149 }
150 }
Takashi Sakamoto288a8d02014-12-09 00:10:35 +0900151}
152
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900153static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream,
154 struct fw_iso_resources *resources, unsigned int rate,
155 unsigned int pcm_chs, unsigned int midi_ports)
Takashi Sakamoto288a8d02014-12-09 00:10:35 +0900156{
Takashi Sakamoto27ec83b2015-09-19 11:21:50 +0900157 bool double_pcm_frames;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900158 unsigned int i;
Takashi Sakamoto288a8d02014-12-09 00:10:35 +0900159 int err;
160
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900161 // At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
162 // one data block of AMDTP packet. Thus sampling transfer frequency is
163 // a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
164 // transferred on AMDTP packets at 96 kHz. Two successive samples of a
165 // channel are stored consecutively in the packet. This quirk is called
166 // as 'Dual Wire'.
167 // For this quirk, blocking mode is required and PCM buffer size should
168 // be aligned to SYT_INTERVAL.
Takashi Sakamoto9f079c12021-05-18 10:25:10 +0900169 double_pcm_frames = (rate > 96000 && !dice->disable_double_pcm_frames);
Takashi Sakamoto27ec83b2015-09-19 11:21:50 +0900170 if (double_pcm_frames) {
Takashi Sakamoto288a8d02014-12-09 00:10:35 +0900171 rate /= 2;
172 pcm_chs *= 2;
Takashi Sakamoto288a8d02014-12-09 00:10:35 +0900173 }
174
Takashi Sakamoto51c29fd2015-09-19 11:21:56 +0900175 err = amdtp_am824_set_parameters(stream, rate, pcm_chs, midi_ports,
176 double_pcm_frames);
Takashi Sakamoto547e6312015-09-19 11:21:49 +0900177 if (err < 0)
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900178 return err;
Takashi Sakamoto547e6312015-09-19 11:21:49 +0900179
Takashi Sakamoto27ec83b2015-09-19 11:21:50 +0900180 if (double_pcm_frames) {
Takashi Sakamoto288a8d02014-12-09 00:10:35 +0900181 pcm_chs /= 2;
182
183 for (i = 0; i < pcm_chs; i++) {
Takashi Sakamotof65be912015-09-19 11:21:58 +0900184 amdtp_am824_set_pcm_position(stream, i, i * 2);
185 amdtp_am824_set_pcm_position(stream, i + pcm_chs,
186 i * 2 + 1);
Takashi Sakamoto288a8d02014-12-09 00:10:35 +0900187 }
188 }
189
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900190 return fw_iso_resources_allocate(resources,
191 amdtp_stream_get_max_payload(stream),
192 fw_parent_device(dice->unit)->max_speed);
193}
194
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900195static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
196 enum amdtp_stream_direction dir,
197 struct reg_params *params)
198{
199 enum snd_dice_rate_mode mode;
200 int i;
201 int err;
202
203 err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
204 if (err < 0)
205 return err;
206
207 for (i = 0; i < params->count; ++i) {
208 __be32 reg[2];
209 struct amdtp_stream *stream;
210 struct fw_iso_resources *resources;
211 unsigned int pcm_cache;
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900212 unsigned int pcm_chs;
213 unsigned int midi_ports;
214
215 if (dir == AMDTP_IN_STREAM) {
216 stream = &dice->tx_stream[i];
217 resources = &dice->tx_resources[i];
218
219 pcm_cache = dice->tx_pcm_chs[i][mode];
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900220 err = snd_dice_transaction_read_tx(dice,
221 params->size * i + TX_NUMBER_AUDIO,
222 reg, sizeof(reg));
223 } else {
224 stream = &dice->rx_stream[i];
225 resources = &dice->rx_resources[i];
226
227 pcm_cache = dice->rx_pcm_chs[i][mode];
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900228 err = snd_dice_transaction_read_rx(dice,
229 params->size * i + RX_NUMBER_AUDIO,
230 reg, sizeof(reg));
231 }
232 if (err < 0)
233 return err;
234 pcm_chs = be32_to_cpu(reg[0]);
235 midi_ports = be32_to_cpu(reg[1]);
236
237 // These are important for developer of this driver.
Takashi Sakamotoa9f47fc2020-01-13 17:46:29 +0900238 if (pcm_chs != pcm_cache) {
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900239 dev_info(&dice->unit->device,
Takashi Sakamotoa9f47fc2020-01-13 17:46:29 +0900240 "cache mismatch: pcm: %u:%u, midi: %u\n",
241 pcm_chs, pcm_cache, midi_ports);
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900242 return -EPROTO;
243 }
244
245 err = keep_resources(dice, stream, resources, rate, pcm_chs,
246 midi_ports);
247 if (err < 0)
248 return err;
249 }
250
251 return 0;
252}
253
Takashi Sakamotob3480632019-06-11 22:21:14 +0900254static void finish_session(struct snd_dice *dice, struct reg_params *tx_params,
255 struct reg_params *rx_params)
256{
257 stop_streams(dice, AMDTP_IN_STREAM, tx_params);
258 stop_streams(dice, AMDTP_OUT_STREAM, rx_params);
259
260 snd_dice_transaction_clear_enable(dice);
261}
262
Takashi Sakamoto94c81012019-10-07 20:05:20 +0900263int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate,
Takashi Sakamotoecb40fd2019-10-18 00:54:17 +0900264 unsigned int events_per_period,
265 unsigned int events_per_buffer)
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900266{
267 unsigned int curr_rate;
268 int err;
269
270 // Check sampling transmission frequency.
271 err = snd_dice_transaction_get_rate(dice, &curr_rate);
272 if (err < 0)
273 return err;
274 if (rate == 0)
275 rate = curr_rate;
276
277 if (dice->substreams_counter == 0 || curr_rate != rate) {
278 struct reg_params tx_params, rx_params;
279
Takashi Sakamotoe9f21122019-08-04 15:21:33 +0900280 amdtp_domain_stop(&dice->domain);
281
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900282 err = get_register_params(dice, &tx_params, &rx_params);
283 if (err < 0)
284 return err;
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900285 finish_session(dice, &tx_params, &rx_params);
286
287 release_resources(dice);
288
289 // Just after owning the unit (GLOBAL_OWNER), the unit can
290 // return invalid stream formats. Selecting clock parameters
291 // have an effect for the unit to refine it.
Takashi Sakamoto41319eb2021-06-01 17:17:51 +0900292 err = select_clock(dice, rate);
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900293 if (err < 0)
294 return err;
295
296 // After changing sampling transfer frequency, the value of
297 // register can be changed.
298 err = get_register_params(dice, &tx_params, &rx_params);
299 if (err < 0)
300 return err;
301
302 err = keep_dual_resources(dice, rate, AMDTP_IN_STREAM,
303 &tx_params);
304 if (err < 0)
305 goto error;
306
307 err = keep_dual_resources(dice, rate, AMDTP_OUT_STREAM,
308 &rx_params);
309 if (err < 0)
310 goto error;
Takashi Sakamoto94c81012019-10-07 20:05:20 +0900311
312 err = amdtp_domain_set_events_per_period(&dice->domain,
Takashi Sakamotoecb40fd2019-10-18 00:54:17 +0900313 events_per_period, events_per_buffer);
Takashi Sakamoto94c81012019-10-07 20:05:20 +0900314 if (err < 0)
315 goto error;
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900316 }
317
318 return 0;
319error:
320 release_resources(dice);
321 return err;
322}
323
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900324static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900325 unsigned int rate, struct reg_params *params)
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900326{
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900327 unsigned int max_speed = fw_parent_device(dice->unit)->max_speed;
328 int i;
329 int err;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900330
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900331 for (i = 0; i < params->count; i++) {
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900332 struct amdtp_stream *stream;
333 struct fw_iso_resources *resources;
334 __be32 reg;
Takashi Sakamotoafa617f2018-05-02 19:16:48 +0900335
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900336 if (dir == AMDTP_IN_STREAM) {
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900337 stream = dice->tx_stream + i;
338 resources = dice->tx_resources + i;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900339 } else {
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900340 stream = dice->rx_stream + i;
341 resources = dice->rx_resources + i;
Takashi Sakamotoafa617f2018-05-02 19:16:48 +0900342 }
343
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900344 reg = cpu_to_be32(resources->channel);
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900345 if (dir == AMDTP_IN_STREAM) {
346 err = snd_dice_transaction_write_tx(dice,
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900347 params->size * i + TX_ISOCHRONOUS,
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900348 &reg, sizeof(reg));
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900349 } else {
350 err = snd_dice_transaction_write_rx(dice,
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900351 params->size * i + RX_ISOCHRONOUS,
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900352 &reg, sizeof(reg));
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900353 }
354 if (err < 0)
355 return err;
356
Takashi Sakamotob0e159f2017-01-03 12:44:43 +0900357 if (dir == AMDTP_IN_STREAM) {
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900358 reg = cpu_to_be32(max_speed);
Takashi Sakamotob0e159f2017-01-03 12:44:43 +0900359 err = snd_dice_transaction_write_tx(dice,
360 params->size * i + TX_SPEED,
Takashi Sakamotoc738aed2019-06-11 22:21:15 +0900361 &reg, sizeof(reg));
Takashi Sakamotob0e159f2017-01-03 12:44:43 +0900362 if (err < 0)
363 return err;
364 }
365
Takashi Sakamotoe9f21122019-08-04 15:21:33 +0900366 err = amdtp_domain_add_stream(&dice->domain, stream,
367 resources->channel, max_speed);
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900368 if (err < 0)
369 return err;
370 }
371
Takashi Sakamotoc72d3a02019-06-13 12:35:22 +0900372 return 0;
Takashi Sakamoto288a8d02014-12-09 00:10:35 +0900373}
374
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900375/*
376 * MEMO: After this function, there're two states of streams:
377 * - None streams are running.
378 * - All streams are running.
379 */
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900380int snd_dice_stream_start_duplex(struct snd_dice *dice)
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900381{
Takashi Sakamotod5553022019-06-11 22:21:17 +0900382 unsigned int generation = dice->rx_resources[0].generation;
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900383 struct reg_params tx_params, rx_params;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900384 unsigned int i;
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900385 unsigned int rate;
Takashi Sakamotoec592fd2018-05-02 19:16:46 +0900386 enum snd_dice_rate_mode mode;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900387 int err;
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900388
389 if (dice->substreams_counter == 0)
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900390 return -EIO;
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900391
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900392 err = get_register_params(dice, &tx_params, &rx_params);
393 if (err < 0)
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900394 return err;
Takashi Sakamoto288a8d02014-12-09 00:10:35 +0900395
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900396 // Check error of packet streaming.
Takashi Sakamotoec592fd2018-05-02 19:16:46 +0900397 for (i = 0; i < MAX_STREAMS; ++i) {
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900398 if (amdtp_streaming_error(&dice->tx_stream[i]) ||
399 amdtp_streaming_error(&dice->rx_stream[i])) {
Takashi Sakamotoe9f21122019-08-04 15:21:33 +0900400 amdtp_domain_stop(&dice->domain);
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900401 finish_session(dice, &tx_params, &rx_params);
Takashi Sakamotoec592fd2018-05-02 19:16:46 +0900402 break;
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900403 }
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900404 }
Takashi Sakamotoec592fd2018-05-02 19:16:46 +0900405
Takashi Sakamotod5553022019-06-11 22:21:17 +0900406 if (generation != fw_parent_device(dice->unit)->card->generation) {
407 for (i = 0; i < MAX_STREAMS; ++i) {
408 if (i < tx_params.count)
409 fw_iso_resources_update(dice->tx_resources + i);
410 if (i < rx_params.count)
411 fw_iso_resources_update(dice->rx_resources + i);
412 }
413 }
414
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900415 // Check required streams are running or not.
416 err = snd_dice_transaction_get_rate(dice, &rate);
417 if (err < 0)
418 return err;
Takashi Sakamotoec592fd2018-05-02 19:16:46 +0900419 err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
420 if (err < 0)
421 return err;
422 for (i = 0; i < MAX_STREAMS; ++i) {
423 if (dice->tx_pcm_chs[i][mode] > 0 &&
424 !amdtp_stream_running(&dice->tx_stream[i]))
425 break;
426 if (dice->rx_pcm_chs[i][mode] > 0 &&
427 !amdtp_stream_running(&dice->rx_stream[i]))
428 break;
429 }
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900430 if (i < MAX_STREAMS) {
431 // Start both streams.
432 err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
433 if (err < 0)
434 goto error;
435
436 err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
437 if (err < 0)
438 goto error;
439
440 err = snd_dice_transaction_set_enable(dice);
441 if (err < 0) {
442 dev_err(&dice->unit->device,
443 "fail to enable interface\n");
444 goto error;
445 }
446
Takashi Sakamoto4121f622021-06-01 17:17:52 +0900447 // MEMO: The device immediately starts packet transmission when enabled. Some
448 // devices are strictly to generate any discontinuity in the sequence of tx packet
449 // when they receives invalid sequence of presentation time in CIP header. The
450 // sequence replay for media clock recovery can suppress the behaviour.
451 err = amdtp_domain_start(&dice->domain, 0, true, false);
Takashi Sakamotoe9f21122019-08-04 15:21:33 +0900452 if (err < 0)
453 goto error;
454
Takashi Sakamotobdaedca2021-05-20 13:01:54 +0900455 if (!amdtp_domain_wait_ready(&dice->domain, READY_TIMEOUT_MS)) {
456 err = -ETIMEDOUT;
457 goto error;
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900458 }
459 }
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900460
Takashi Sakamoto20b94542018-05-02 19:16:47 +0900461 return 0;
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900462error:
Takashi Sakamotoe9f21122019-08-04 15:21:33 +0900463 amdtp_domain_stop(&dice->domain);
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900464 finish_session(dice, &tx_params, &rx_params);
465 return err;
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900466}
467
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900468/*
469 * MEMO: After this function, there're two states of streams:
470 * - None streams are running.
471 * - All streams are running.
472 */
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900473void snd_dice_stream_stop_duplex(struct snd_dice *dice)
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900474{
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900475 struct reg_params tx_params, rx_params;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900476
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900477 if (dice->substreams_counter == 0) {
Takashi Sakamotodd7b8362021-03-12 18:34:07 +0900478 if (get_register_params(dice, &tx_params, &rx_params) >= 0)
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900479 finish_session(dice, &tx_params, &rx_params);
Takashi Sakamoto740680f2019-06-18 22:26:19 +0900480
Takashi Sakamotodd7b8362021-03-12 18:34:07 +0900481 amdtp_domain_stop(&dice->domain);
Takashi Sakamoto740680f2019-06-18 22:26:19 +0900482 release_resources(dice);
Takashi Sakamoto3cd2c2d2019-06-11 22:21:16 +0900483 }
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900484}
485
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900486static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir,
487 unsigned int index)
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900488{
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900489 struct amdtp_stream *stream;
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900490 struct fw_iso_resources *resources;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900491 int err;
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900492
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900493 if (dir == AMDTP_IN_STREAM) {
494 stream = &dice->tx_stream[index];
495 resources = &dice->tx_resources[index];
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900496 } else {
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900497 stream = &dice->rx_stream[index];
498 resources = &dice->rx_resources[index];
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900499 }
500
501 err = fw_iso_resources_init(resources, dice->unit);
502 if (err < 0)
503 goto end;
504 resources->channels_mask = 0x00000000ffffffffuLL;
505
Takashi Sakamoto59558152015-09-19 11:21:55 +0900506 err = amdtp_am824_init(stream, dice->unit, dir, CIP_BLOCKING);
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900507 if (err < 0) {
508 amdtp_stream_destroy(stream);
509 fw_iso_resources_destroy(resources);
510 }
511end:
512 return err;
513}
514
Takashi Sakamotod23c2cc2015-02-21 23:54:59 +0900515/*
516 * This function should be called before starting streams or after stopping
517 * streams.
518 */
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900519static void destroy_stream(struct snd_dice *dice,
520 enum amdtp_stream_direction dir,
521 unsigned int index)
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900522{
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900523 struct amdtp_stream *stream;
Takashi Sakamotod23c2cc2015-02-21 23:54:59 +0900524 struct fw_iso_resources *resources;
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900525
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900526 if (dir == AMDTP_IN_STREAM) {
527 stream = &dice->tx_stream[index];
528 resources = &dice->tx_resources[index];
529 } else {
530 stream = &dice->rx_stream[index];
531 resources = &dice->rx_resources[index];
532 }
Takashi Sakamotod23c2cc2015-02-21 23:54:59 +0900533
534 amdtp_stream_destroy(stream);
535 fw_iso_resources_destroy(resources);
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900536}
537
538int snd_dice_stream_init_duplex(struct snd_dice *dice)
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900539{
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900540 int i, err;
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900541
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900542 for (i = 0; i < MAX_STREAMS; i++) {
543 err = init_stream(dice, AMDTP_IN_STREAM, i);
544 if (err < 0) {
545 for (; i >= 0; i--)
Takashi Sakamoto0f925662018-04-26 22:00:29 +0900546 destroy_stream(dice, AMDTP_IN_STREAM, i);
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900547 goto end;
548 }
549 }
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900550
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900551 for (i = 0; i < MAX_STREAMS; i++) {
552 err = init_stream(dice, AMDTP_OUT_STREAM, i);
553 if (err < 0) {
554 for (; i >= 0; i--)
555 destroy_stream(dice, AMDTP_OUT_STREAM, i);
556 for (i = 0; i < MAX_STREAMS; i++)
557 destroy_stream(dice, AMDTP_IN_STREAM, i);
Takashi Sakamoto6e26d192019-08-29 23:37:19 +0900558 goto end;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900559 }
560 }
Takashi Sakamotoe9f21122019-08-04 15:21:33 +0900561
562 err = amdtp_domain_init(&dice->domain);
563 if (err < 0) {
564 for (i = 0; i < MAX_STREAMS; ++i) {
565 destroy_stream(dice, AMDTP_OUT_STREAM, i);
566 destroy_stream(dice, AMDTP_IN_STREAM, i);
567 }
568 }
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900569end:
570 return err;
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900571}
572
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900573void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900574{
Takashi Sakamoto6b94fb12016-03-28 08:29:32 +0900575 unsigned int i;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900576
Takashi Sakamoto6b94fb12016-03-28 08:29:32 +0900577 for (i = 0; i < MAX_STREAMS; i++) {
578 destroy_stream(dice, AMDTP_IN_STREAM, i);
579 destroy_stream(dice, AMDTP_OUT_STREAM, i);
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900580 }
Takashi Sakamotoe9f21122019-08-04 15:21:33 +0900581
582 amdtp_domain_destroy(&dice->domain);
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900583}
584
Takashi Sakamoto9a028432014-12-09 00:10:36 +0900585void snd_dice_stream_update_duplex(struct snd_dice *dice)
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900586{
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900587 struct reg_params tx_params, rx_params;
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900588
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900589 /*
590 * On a bus reset, the DICE firmware disables streaming and then goes
591 * off contemplating its own navel for hundreds of milliseconds before
592 * it can react to any of our attempts to reenable streaming. This
593 * means that we lose synchronization anyway, so we force our streams
594 * to stop so that the application can restart them in an orderly
595 * manner.
596 */
597 dice->global_enabled = false;
598
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900599 if (get_register_params(dice, &tx_params, &rx_params) == 0) {
Takashi Sakamotoe9f21122019-08-04 15:21:33 +0900600 amdtp_domain_stop(&dice->domain);
601
Takashi Sakamoto8cc1a8a2016-03-10 21:44:28 +0900602 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
603 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
Takashi Sakamoto436b5ab2016-03-07 22:35:43 +0900604 }
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900605}
606
Takashi Sakamotob60152f2018-05-02 19:16:42 +0900607int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
608{
609 unsigned int rate;
610 enum snd_dice_rate_mode mode;
611 __be32 reg[2];
612 struct reg_params tx_params, rx_params;
613 int i;
614 int err;
615
Takashi Sakamoto58579c02018-05-02 19:16:45 +0900616 /* If extended protocol is available, detect detail spec. */
617 err = snd_dice_detect_extension_formats(dice);
618 if (err >= 0)
619 return err;
620
Takashi Sakamotob60152f2018-05-02 19:16:42 +0900621 /*
622 * Available stream format is restricted at current mode of sampling
623 * clock.
624 */
625 err = snd_dice_transaction_get_rate(dice, &rate);
626 if (err < 0)
627 return err;
628
629 err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
630 if (err < 0)
631 return err;
632
633 /*
634 * Just after owning the unit (GLOBAL_OWNER), the unit can return
635 * invalid stream formats. Selecting clock parameters have an effect
636 * for the unit to refine it.
637 */
Takashi Sakamoto41319eb2021-06-01 17:17:51 +0900638 err = select_clock(dice, rate);
Takashi Sakamotob60152f2018-05-02 19:16:42 +0900639 if (err < 0)
640 return err;
641
642 err = get_register_params(dice, &tx_params, &rx_params);
643 if (err < 0)
644 return err;
645
646 for (i = 0; i < tx_params.count; ++i) {
647 err = snd_dice_transaction_read_tx(dice,
648 tx_params.size * i + TX_NUMBER_AUDIO,
649 reg, sizeof(reg));
650 if (err < 0)
651 return err;
652 dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
653 dice->tx_midi_ports[i] = max_t(unsigned int,
654 be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);
655 }
656 for (i = 0; i < rx_params.count; ++i) {
657 err = snd_dice_transaction_read_rx(dice,
658 rx_params.size * i + RX_NUMBER_AUDIO,
659 reg, sizeof(reg));
660 if (err < 0)
661 return err;
662 dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
663 dice->rx_midi_ports[i] = max_t(unsigned int,
664 be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);
665 }
666
667 return 0;
668}
669
Takashi Sakamoto6eb6c812014-11-29 00:59:14 +0900670static void dice_lock_changed(struct snd_dice *dice)
671{
672 dice->dev_lock_changed = true;
673 wake_up(&dice->hwdep_wait);
674}
675
676int snd_dice_stream_lock_try(struct snd_dice *dice)
677{
678 int err;
679
680 spin_lock_irq(&dice->lock);
681
682 if (dice->dev_lock_count < 0) {
683 err = -EBUSY;
684 goto out;
685 }
686
687 if (dice->dev_lock_count++ == 0)
688 dice_lock_changed(dice);
689 err = 0;
690out:
691 spin_unlock_irq(&dice->lock);
692 return err;
693}
694
695void snd_dice_stream_lock_release(struct snd_dice *dice)
696{
697 spin_lock_irq(&dice->lock);
698
699 if (WARN_ON(dice->dev_lock_count <= 0))
700 goto out;
701
702 if (--dice->dev_lock_count == 0)
703 dice_lock_changed(dice);
704out:
705 spin_unlock_irq(&dice->lock);
706}