dice-stream.c 16 KB

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