dice-stream.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  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>
  7. */
  8. #include "dice.h"
  9. #define READY_TIMEOUT_MS 200
  10. #define NOTIFICATION_TIMEOUT_MS 100
  11. struct reg_params {
  12. unsigned int count;
  13. unsigned int size;
  14. };
  15. const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
  16. /* mode 0 */
  17. [0] = 32000,
  18. [1] = 44100,
  19. [2] = 48000,
  20. /* mode 1 */
  21. [3] = 88200,
  22. [4] = 96000,
  23. /* mode 2 */
  24. [5] = 176400,
  25. [6] = 192000,
  26. };
  27. int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
  28. enum snd_dice_rate_mode *mode)
  29. {
  30. /* Corresponding to each entry in snd_dice_rates. */
  31. static const enum snd_dice_rate_mode modes[] = {
  32. [0] = SND_DICE_RATE_MODE_LOW,
  33. [1] = SND_DICE_RATE_MODE_LOW,
  34. [2] = SND_DICE_RATE_MODE_LOW,
  35. [3] = SND_DICE_RATE_MODE_MIDDLE,
  36. [4] = SND_DICE_RATE_MODE_MIDDLE,
  37. [5] = SND_DICE_RATE_MODE_HIGH,
  38. [6] = SND_DICE_RATE_MODE_HIGH,
  39. };
  40. int i;
  41. for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
  42. if (!(dice->clock_caps & BIT(i)))
  43. continue;
  44. if (snd_dice_rates[i] != rate)
  45. continue;
  46. *mode = modes[i];
  47. return 0;
  48. }
  49. return -EINVAL;
  50. }
  51. static int select_clock(struct snd_dice *dice, unsigned int rate)
  52. {
  53. __be32 reg, new;
  54. u32 data;
  55. int i;
  56. int err;
  57. err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
  58. &reg, sizeof(reg));
  59. if (err < 0)
  60. return err;
  61. data = be32_to_cpu(reg);
  62. data &= ~CLOCK_RATE_MASK;
  63. for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
  64. if (snd_dice_rates[i] == rate)
  65. break;
  66. }
  67. if (i == ARRAY_SIZE(snd_dice_rates))
  68. return -EINVAL;
  69. data |= i << CLOCK_RATE_SHIFT;
  70. if (completion_done(&dice->clock_accepted))
  71. reinit_completion(&dice->clock_accepted);
  72. new = cpu_to_be32(data);
  73. err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
  74. &new, sizeof(new));
  75. if (err < 0)
  76. return err;
  77. if (wait_for_completion_timeout(&dice->clock_accepted,
  78. msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) {
  79. if (reg != new)
  80. return -ETIMEDOUT;
  81. }
  82. return 0;
  83. }
  84. static int get_register_params(struct snd_dice *dice,
  85. struct reg_params *tx_params,
  86. struct reg_params *rx_params)
  87. {
  88. __be32 reg[2];
  89. int err;
  90. err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg));
  91. if (err < 0)
  92. return err;
  93. tx_params->count =
  94. min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
  95. tx_params->size = be32_to_cpu(reg[1]) * 4;
  96. err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg));
  97. if (err < 0)
  98. return err;
  99. rx_params->count =
  100. min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
  101. rx_params->size = be32_to_cpu(reg[1]) * 4;
  102. return 0;
  103. }
  104. static void release_resources(struct snd_dice *dice)
  105. {
  106. int i;
  107. for (i = 0; i < MAX_STREAMS; ++i) {
  108. fw_iso_resources_free(&dice->tx_resources[i]);
  109. fw_iso_resources_free(&dice->rx_resources[i]);
  110. }
  111. }
  112. static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
  113. struct reg_params *params)
  114. {
  115. __be32 reg;
  116. unsigned int i;
  117. for (i = 0; i < params->count; i++) {
  118. reg = cpu_to_be32((u32)-1);
  119. if (dir == AMDTP_IN_STREAM) {
  120. snd_dice_transaction_write_tx(dice,
  121. params->size * i + TX_ISOCHRONOUS,
  122. &reg, sizeof(reg));
  123. } else {
  124. snd_dice_transaction_write_rx(dice,
  125. params->size * i + RX_ISOCHRONOUS,
  126. &reg, sizeof(reg));
  127. }
  128. }
  129. }
  130. static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream,
  131. struct fw_iso_resources *resources, unsigned int rate,
  132. unsigned int pcm_chs, unsigned int midi_ports)
  133. {
  134. bool double_pcm_frames;
  135. unsigned int i;
  136. int err;
  137. // At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
  138. // one data block of AMDTP packet. Thus sampling transfer frequency is
  139. // a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
  140. // transferred on AMDTP packets at 96 kHz. Two successive samples of a
  141. // channel are stored consecutively in the packet. This quirk is called
  142. // as 'Dual Wire'.
  143. // For this quirk, blocking mode is required and PCM buffer size should
  144. // be aligned to SYT_INTERVAL.
  145. double_pcm_frames = (rate > 96000 && !dice->disable_double_pcm_frames);
  146. if (double_pcm_frames) {
  147. rate /= 2;
  148. pcm_chs *= 2;
  149. }
  150. err = amdtp_am824_set_parameters(stream, rate, pcm_chs, midi_ports,
  151. double_pcm_frames);
  152. if (err < 0)
  153. return err;
  154. if (double_pcm_frames) {
  155. pcm_chs /= 2;
  156. for (i = 0; i < pcm_chs; i++) {
  157. amdtp_am824_set_pcm_position(stream, i, i * 2);
  158. amdtp_am824_set_pcm_position(stream, i + pcm_chs,
  159. i * 2 + 1);
  160. }
  161. }
  162. return fw_iso_resources_allocate(resources,
  163. amdtp_stream_get_max_payload(stream),
  164. fw_parent_device(dice->unit)->max_speed);
  165. }
  166. static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
  167. enum amdtp_stream_direction dir,
  168. struct reg_params *params)
  169. {
  170. enum snd_dice_rate_mode mode;
  171. int i;
  172. int err;
  173. err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
  174. if (err < 0)
  175. return err;
  176. for (i = 0; i < params->count; ++i) {
  177. __be32 reg[2];
  178. struct amdtp_stream *stream;
  179. struct fw_iso_resources *resources;
  180. unsigned int pcm_cache;
  181. unsigned int pcm_chs;
  182. unsigned int midi_ports;
  183. if (dir == AMDTP_IN_STREAM) {
  184. stream = &dice->tx_stream[i];
  185. resources = &dice->tx_resources[i];
  186. pcm_cache = dice->tx_pcm_chs[i][mode];
  187. err = snd_dice_transaction_read_tx(dice,
  188. params->size * i + TX_NUMBER_AUDIO,
  189. reg, sizeof(reg));
  190. } else {
  191. stream = &dice->rx_stream[i];
  192. resources = &dice->rx_resources[i];
  193. pcm_cache = dice->rx_pcm_chs[i][mode];
  194. err = snd_dice_transaction_read_rx(dice,
  195. params->size * i + RX_NUMBER_AUDIO,
  196. reg, sizeof(reg));
  197. }
  198. if (err < 0)
  199. return err;
  200. pcm_chs = be32_to_cpu(reg[0]);
  201. midi_ports = be32_to_cpu(reg[1]);
  202. // These are important for developer of this driver.
  203. if (pcm_chs != pcm_cache) {
  204. dev_info(&dice->unit->device,
  205. "cache mismatch: pcm: %u:%u, midi: %u\n",
  206. pcm_chs, pcm_cache, midi_ports);
  207. return -EPROTO;
  208. }
  209. err = keep_resources(dice, stream, resources, rate, pcm_chs,
  210. midi_ports);
  211. if (err < 0)
  212. return err;
  213. }
  214. return 0;
  215. }
  216. static void finish_session(struct snd_dice *dice, struct reg_params *tx_params,
  217. struct reg_params *rx_params)
  218. {
  219. stop_streams(dice, AMDTP_IN_STREAM, tx_params);
  220. stop_streams(dice, AMDTP_OUT_STREAM, rx_params);
  221. snd_dice_transaction_clear_enable(dice);
  222. }
  223. int snd_dice_stream_reserve_duplex(struct snd_dice *dice, unsigned int rate,
  224. unsigned int events_per_period,
  225. unsigned int events_per_buffer)
  226. {
  227. unsigned int curr_rate;
  228. int err;
  229. // Check sampling transmission frequency.
  230. err = snd_dice_transaction_get_rate(dice, &curr_rate);
  231. if (err < 0)
  232. return err;
  233. if (rate == 0)
  234. rate = curr_rate;
  235. if (dice->substreams_counter == 0 || curr_rate != rate) {
  236. struct reg_params tx_params, rx_params;
  237. amdtp_domain_stop(&dice->domain);
  238. err = get_register_params(dice, &tx_params, &rx_params);
  239. if (err < 0)
  240. return err;
  241. finish_session(dice, &tx_params, &rx_params);
  242. release_resources(dice);
  243. // Just after owning the unit (GLOBAL_OWNER), the unit can
  244. // return invalid stream formats. Selecting clock parameters
  245. // have an effect for the unit to refine it.
  246. err = select_clock(dice, rate);
  247. if (err < 0)
  248. return err;
  249. // After changing sampling transfer frequency, the value of
  250. // register can be changed.
  251. err = get_register_params(dice, &tx_params, &rx_params);
  252. if (err < 0)
  253. return err;
  254. err = keep_dual_resources(dice, rate, AMDTP_IN_STREAM,
  255. &tx_params);
  256. if (err < 0)
  257. goto error;
  258. err = keep_dual_resources(dice, rate, AMDTP_OUT_STREAM,
  259. &rx_params);
  260. if (err < 0)
  261. goto error;
  262. err = amdtp_domain_set_events_per_period(&dice->domain,
  263. events_per_period, events_per_buffer);
  264. if (err < 0)
  265. goto error;
  266. }
  267. return 0;
  268. error:
  269. release_resources(dice);
  270. return err;
  271. }
  272. static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
  273. unsigned int rate, struct reg_params *params)
  274. {
  275. unsigned int max_speed = fw_parent_device(dice->unit)->max_speed;
  276. int i;
  277. int err;
  278. for (i = 0; i < params->count; i++) {
  279. struct amdtp_stream *stream;
  280. struct fw_iso_resources *resources;
  281. __be32 reg;
  282. if (dir == AMDTP_IN_STREAM) {
  283. stream = dice->tx_stream + i;
  284. resources = dice->tx_resources + i;
  285. } else {
  286. stream = dice->rx_stream + i;
  287. resources = dice->rx_resources + i;
  288. }
  289. reg = cpu_to_be32(resources->channel);
  290. if (dir == AMDTP_IN_STREAM) {
  291. err = snd_dice_transaction_write_tx(dice,
  292. params->size * i + TX_ISOCHRONOUS,
  293. &reg, sizeof(reg));
  294. } else {
  295. err = snd_dice_transaction_write_rx(dice,
  296. params->size * i + RX_ISOCHRONOUS,
  297. &reg, sizeof(reg));
  298. }
  299. if (err < 0)
  300. return err;
  301. if (dir == AMDTP_IN_STREAM) {
  302. reg = cpu_to_be32(max_speed);
  303. err = snd_dice_transaction_write_tx(dice,
  304. params->size * i + TX_SPEED,
  305. &reg, sizeof(reg));
  306. if (err < 0)
  307. return err;
  308. }
  309. err = amdtp_domain_add_stream(&dice->domain, stream,
  310. resources->channel, max_speed);
  311. if (err < 0)
  312. return err;
  313. }
  314. return 0;
  315. }
  316. /*
  317. * MEMO: After this function, there're two states of streams:
  318. * - None streams are running.
  319. * - All streams are running.
  320. */
  321. int snd_dice_stream_start_duplex(struct snd_dice *dice)
  322. {
  323. unsigned int generation = dice->rx_resources[0].generation;
  324. struct reg_params tx_params, rx_params;
  325. unsigned int i;
  326. unsigned int rate;
  327. enum snd_dice_rate_mode mode;
  328. int err;
  329. if (dice->substreams_counter == 0)
  330. return -EIO;
  331. err = get_register_params(dice, &tx_params, &rx_params);
  332. if (err < 0)
  333. return err;
  334. // Check error of packet streaming.
  335. for (i = 0; i < MAX_STREAMS; ++i) {
  336. if (amdtp_streaming_error(&dice->tx_stream[i]) ||
  337. amdtp_streaming_error(&dice->rx_stream[i])) {
  338. amdtp_domain_stop(&dice->domain);
  339. finish_session(dice, &tx_params, &rx_params);
  340. break;
  341. }
  342. }
  343. if (generation != fw_parent_device(dice->unit)->card->generation) {
  344. for (i = 0; i < MAX_STREAMS; ++i) {
  345. if (i < tx_params.count)
  346. fw_iso_resources_update(dice->tx_resources + i);
  347. if (i < rx_params.count)
  348. fw_iso_resources_update(dice->rx_resources + i);
  349. }
  350. }
  351. // Check required streams are running or not.
  352. err = snd_dice_transaction_get_rate(dice, &rate);
  353. if (err < 0)
  354. return err;
  355. err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
  356. if (err < 0)
  357. return err;
  358. for (i = 0; i < MAX_STREAMS; ++i) {
  359. if (dice->tx_pcm_chs[i][mode] > 0 &&
  360. !amdtp_stream_running(&dice->tx_stream[i]))
  361. break;
  362. if (dice->rx_pcm_chs[i][mode] > 0 &&
  363. !amdtp_stream_running(&dice->rx_stream[i]))
  364. break;
  365. }
  366. if (i < MAX_STREAMS) {
  367. // Start both streams.
  368. err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
  369. if (err < 0)
  370. goto error;
  371. err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
  372. if (err < 0)
  373. goto error;
  374. err = snd_dice_transaction_set_enable(dice);
  375. if (err < 0) {
  376. dev_err(&dice->unit->device,
  377. "fail to enable interface\n");
  378. goto error;
  379. }
  380. // MEMO: The device immediately starts packet transmission when enabled. Some
  381. // devices are strictly to generate any discontinuity in the sequence of tx packet
  382. // when they receives invalid sequence of presentation time in CIP header. The
  383. // sequence replay for media clock recovery can suppress the behaviour.
  384. err = amdtp_domain_start(&dice->domain, 0, true, false);
  385. if (err < 0)
  386. goto error;
  387. if (!amdtp_domain_wait_ready(&dice->domain, READY_TIMEOUT_MS)) {
  388. err = -ETIMEDOUT;
  389. goto error;
  390. }
  391. }
  392. return 0;
  393. error:
  394. amdtp_domain_stop(&dice->domain);
  395. finish_session(dice, &tx_params, &rx_params);
  396. return err;
  397. }
  398. /*
  399. * MEMO: After this function, there're two states of streams:
  400. * - None streams are running.
  401. * - All streams are running.
  402. */
  403. void snd_dice_stream_stop_duplex(struct snd_dice *dice)
  404. {
  405. struct reg_params tx_params, rx_params;
  406. if (dice->substreams_counter == 0) {
  407. if (get_register_params(dice, &tx_params, &rx_params) >= 0)
  408. finish_session(dice, &tx_params, &rx_params);
  409. amdtp_domain_stop(&dice->domain);
  410. release_resources(dice);
  411. }
  412. }
  413. static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir,
  414. unsigned int index)
  415. {
  416. struct amdtp_stream *stream;
  417. struct fw_iso_resources *resources;
  418. int err;
  419. if (dir == AMDTP_IN_STREAM) {
  420. stream = &dice->tx_stream[index];
  421. resources = &dice->tx_resources[index];
  422. } else {
  423. stream = &dice->rx_stream[index];
  424. resources = &dice->rx_resources[index];
  425. }
  426. err = fw_iso_resources_init(resources, dice->unit);
  427. if (err < 0)
  428. goto end;
  429. resources->channels_mask = 0x00000000ffffffffuLL;
  430. err = amdtp_am824_init(stream, dice->unit, dir, CIP_BLOCKING);
  431. if (err < 0) {
  432. amdtp_stream_destroy(stream);
  433. fw_iso_resources_destroy(resources);
  434. }
  435. end:
  436. return err;
  437. }
  438. /*
  439. * This function should be called before starting streams or after stopping
  440. * streams.
  441. */
  442. static void destroy_stream(struct snd_dice *dice,
  443. enum amdtp_stream_direction dir,
  444. unsigned int index)
  445. {
  446. struct amdtp_stream *stream;
  447. struct fw_iso_resources *resources;
  448. if (dir == AMDTP_IN_STREAM) {
  449. stream = &dice->tx_stream[index];
  450. resources = &dice->tx_resources[index];
  451. } else {
  452. stream = &dice->rx_stream[index];
  453. resources = &dice->rx_resources[index];
  454. }
  455. amdtp_stream_destroy(stream);
  456. fw_iso_resources_destroy(resources);
  457. }
  458. int snd_dice_stream_init_duplex(struct snd_dice *dice)
  459. {
  460. int i, err;
  461. for (i = 0; i < MAX_STREAMS; i++) {
  462. err = init_stream(dice, AMDTP_IN_STREAM, i);
  463. if (err < 0) {
  464. for (; i >= 0; i--)
  465. destroy_stream(dice, AMDTP_IN_STREAM, i);
  466. goto end;
  467. }
  468. }
  469. for (i = 0; i < MAX_STREAMS; i++) {
  470. err = init_stream(dice, AMDTP_OUT_STREAM, i);
  471. if (err < 0) {
  472. for (; i >= 0; i--)
  473. destroy_stream(dice, AMDTP_OUT_STREAM, i);
  474. for (i = 0; i < MAX_STREAMS; i++)
  475. destroy_stream(dice, AMDTP_IN_STREAM, i);
  476. goto end;
  477. }
  478. }
  479. err = amdtp_domain_init(&dice->domain);
  480. if (err < 0) {
  481. for (i = 0; i < MAX_STREAMS; ++i) {
  482. destroy_stream(dice, AMDTP_OUT_STREAM, i);
  483. destroy_stream(dice, AMDTP_IN_STREAM, i);
  484. }
  485. }
  486. end:
  487. return err;
  488. }
  489. void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
  490. {
  491. unsigned int i;
  492. for (i = 0; i < MAX_STREAMS; i++) {
  493. destroy_stream(dice, AMDTP_IN_STREAM, i);
  494. destroy_stream(dice, AMDTP_OUT_STREAM, i);
  495. }
  496. amdtp_domain_destroy(&dice->domain);
  497. }
  498. void snd_dice_stream_update_duplex(struct snd_dice *dice)
  499. {
  500. struct reg_params tx_params, rx_params;
  501. /*
  502. * On a bus reset, the DICE firmware disables streaming and then goes
  503. * off contemplating its own navel for hundreds of milliseconds before
  504. * it can react to any of our attempts to reenable streaming. This
  505. * means that we lose synchronization anyway, so we force our streams
  506. * to stop so that the application can restart them in an orderly
  507. * manner.
  508. */
  509. dice->global_enabled = false;
  510. if (get_register_params(dice, &tx_params, &rx_params) == 0) {
  511. amdtp_domain_stop(&dice->domain);
  512. stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
  513. stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
  514. }
  515. }
  516. int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
  517. {
  518. unsigned int rate;
  519. enum snd_dice_rate_mode mode;
  520. __be32 reg[2];
  521. struct reg_params tx_params, rx_params;
  522. int i;
  523. int err;
  524. /* If extended protocol is available, detect detail spec. */
  525. err = snd_dice_detect_extension_formats(dice);
  526. if (err >= 0)
  527. return err;
  528. /*
  529. * Available stream format is restricted at current mode of sampling
  530. * clock.
  531. */
  532. err = snd_dice_transaction_get_rate(dice, &rate);
  533. if (err < 0)
  534. return err;
  535. err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
  536. if (err < 0)
  537. return err;
  538. /*
  539. * Just after owning the unit (GLOBAL_OWNER), the unit can return
  540. * invalid stream formats. Selecting clock parameters have an effect
  541. * for the unit to refine it.
  542. */
  543. err = select_clock(dice, rate);
  544. if (err < 0)
  545. return err;
  546. err = get_register_params(dice, &tx_params, &rx_params);
  547. if (err < 0)
  548. return err;
  549. for (i = 0; i < tx_params.count; ++i) {
  550. err = snd_dice_transaction_read_tx(dice,
  551. tx_params.size * i + TX_NUMBER_AUDIO,
  552. reg, sizeof(reg));
  553. if (err < 0)
  554. return err;
  555. dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
  556. dice->tx_midi_ports[i] = max_t(unsigned int,
  557. be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);
  558. }
  559. for (i = 0; i < rx_params.count; ++i) {
  560. err = snd_dice_transaction_read_rx(dice,
  561. rx_params.size * i + RX_NUMBER_AUDIO,
  562. reg, sizeof(reg));
  563. if (err < 0)
  564. return err;
  565. dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
  566. dice->rx_midi_ports[i] = max_t(unsigned int,
  567. be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);
  568. }
  569. return 0;
  570. }
  571. static void dice_lock_changed(struct snd_dice *dice)
  572. {
  573. dice->dev_lock_changed = true;
  574. wake_up(&dice->hwdep_wait);
  575. }
  576. int snd_dice_stream_lock_try(struct snd_dice *dice)
  577. {
  578. int err;
  579. spin_lock_irq(&dice->lock);
  580. if (dice->dev_lock_count < 0) {
  581. err = -EBUSY;
  582. goto out;
  583. }
  584. if (dice->dev_lock_count++ == 0)
  585. dice_lock_changed(dice);
  586. err = 0;
  587. out:
  588. spin_unlock_irq(&dice->lock);
  589. return err;
  590. }
  591. void snd_dice_stream_lock_release(struct snd_dice *dice)
  592. {
  593. spin_lock_irq(&dice->lock);
  594. if (WARN_ON(dice->dev_lock_count <= 0))
  595. goto out;
  596. if (--dice->dev_lock_count == 0)
  597. dice_lock_changed(dice);
  598. out:
  599. spin_unlock_irq(&dice->lock);
  600. }