~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/firewire/dice/dice-stream.c

Version: ~ [ linux-5.5-rc7 ] ~ [ linux-5.4.13 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.97 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.166 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.210 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.210 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 10 #include "dice.h"
 11 
 12 #define CALLBACK_TIMEOUT        200
 13 #define NOTIFICATION_TIMEOUT_MS (2 * MSEC_PER_SEC)
 14 
 15 struct reg_params {
 16         unsigned int count;
 17         unsigned int size;
 18 };
 19 
 20 const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
 21         /* mode 0 */
 22         [0] =  32000,
 23         [1] =  44100,
 24         [2] =  48000,
 25         /* mode 1 */
 26         [3] =  88200,
 27         [4] =  96000,
 28         /* mode 2 */
 29         [5] = 176400,
 30         [6] = 192000,
 31 };
 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 
 61 /*
 62  * This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE
 63  * to GLOBAL_STATUS. Especially, just after powering on, these are different.
 64  */
 65 static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate)
 66 {
 67         __be32 reg, nominal;
 68         u32 data;
 69         int i;
 70         int err;
 71 
 72         err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
 73                                                &reg, sizeof(reg));
 74         if (err < 0)
 75                 return err;
 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 
 88         if (completion_done(&dice->clock_accepted))
 89                 reinit_completion(&dice->clock_accepted);
 90 
 91         reg = cpu_to_be32(data);
 92         err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
 93                                                 &reg, sizeof(reg));
 94         if (err < 0)
 95                 return err;
 96 
 97         if (wait_for_completion_timeout(&dice->clock_accepted,
 98                         msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) {
 99                 /*
100                  * Old versions of Dice firmware transfer no notification when
101                  * the same clock status as current one is set. In this case,
102                  * just check current clock status.
103                  */
104                 err = snd_dice_transaction_read_global(dice, GLOBAL_STATUS,
105                                                 &nominal, sizeof(nominal));
106                 if (err < 0)
107                         return err;
108                 if (!(be32_to_cpu(nominal) & STATUS_SOURCE_LOCKED))
109                         return -ETIMEDOUT;
110         }
111 
112         return 0;
113 }
114 
115 static int get_register_params(struct snd_dice *dice,
116                                struct reg_params *tx_params,
117                                struct reg_params *rx_params)
118 {
119         __be32 reg[2];
120         int err;
121 
122         err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg, sizeof(reg));
123         if (err < 0)
124                 return err;
125         tx_params->count =
126                         min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
127         tx_params->size = be32_to_cpu(reg[1]) * 4;
128 
129         err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg, sizeof(reg));
130         if (err < 0)
131                 return err;
132         rx_params->count =
133                         min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
134         rx_params->size = be32_to_cpu(reg[1]) * 4;
135 
136         return 0;
137 }
138 
139 static void release_resources(struct snd_dice *dice)
140 {
141         unsigned int i;
142 
143         for (i = 0; i < MAX_STREAMS; i++) {
144                 if (amdtp_stream_running(&dice->tx_stream[i])) {
145                         amdtp_stream_pcm_abort(&dice->tx_stream[i]);
146                         amdtp_stream_stop(&dice->tx_stream[i]);
147                 }
148                 if (amdtp_stream_running(&dice->rx_stream[i])) {
149                         amdtp_stream_pcm_abort(&dice->rx_stream[i]);
150                         amdtp_stream_stop(&dice->rx_stream[i]);
151                 }
152 
153                 fw_iso_resources_free(&dice->tx_resources[i]);
154                 fw_iso_resources_free(&dice->rx_resources[i]);
155         }
156 }
157 
158 static void stop_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
159                          struct reg_params *params)
160 {
161         __be32 reg;
162         unsigned int i;
163 
164         for (i = 0; i < params->count; i++) {
165                 reg = cpu_to_be32((u32)-1);
166                 if (dir == AMDTP_IN_STREAM) {
167                         snd_dice_transaction_write_tx(dice,
168                                         params->size * i + TX_ISOCHRONOUS,
169                                         &reg, sizeof(reg));
170                 } else {
171                         snd_dice_transaction_write_rx(dice,
172                                         params->size * i + RX_ISOCHRONOUS,
173                                         &reg, sizeof(reg));
174                 }
175         }
176 }
177 
178 static int keep_resources(struct snd_dice *dice,
179                           enum amdtp_stream_direction dir, unsigned int index,
180                           unsigned int rate, unsigned int pcm_chs,
181                           unsigned int midi_ports)
182 {
183         struct amdtp_stream *stream;
184         struct fw_iso_resources *resources;
185         bool double_pcm_frames;
186         unsigned int i;
187         int err;
188 
189         if (dir == AMDTP_IN_STREAM) {
190                 stream = &dice->tx_stream[index];
191                 resources = &dice->tx_resources[index];
192         } else {
193                 stream = &dice->rx_stream[index];
194                 resources = &dice->rx_resources[index];
195         }
196 
197         /*
198          * At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
199          * one data block of AMDTP packet. Thus sampling transfer frequency is
200          * a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
201          * transferred on AMDTP packets at 96 kHz. Two successive samples of a
202          * channel are stored consecutively in the packet. This quirk is called
203          * as 'Dual Wire'.
204          * For this quirk, blocking mode is required and PCM buffer size should
205          * be aligned to SYT_INTERVAL.
206          */
207         double_pcm_frames = rate > 96000;
208         if (double_pcm_frames) {
209                 rate /= 2;
210                 pcm_chs *= 2;
211         }
212 
213         err = amdtp_am824_set_parameters(stream, rate, pcm_chs, midi_ports,
214                                          double_pcm_frames);
215         if (err < 0)
216                 return err;
217 
218         if (double_pcm_frames) {
219                 pcm_chs /= 2;
220 
221                 for (i = 0; i < pcm_chs; i++) {
222                         amdtp_am824_set_pcm_position(stream, i, i * 2);
223                         amdtp_am824_set_pcm_position(stream, i + pcm_chs,
224                                                      i * 2 + 1);
225                 }
226         }
227 
228         return fw_iso_resources_allocate(resources,
229                                 amdtp_stream_get_max_payload(stream),
230                                 fw_parent_device(dice->unit)->max_speed);
231 }
232 
233 static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
234                          unsigned int rate, struct reg_params *params)
235 {
236         __be32 reg[2];
237         enum snd_dice_rate_mode mode;
238         unsigned int i, pcm_chs, midi_ports;
239         struct amdtp_stream *streams;
240         struct fw_iso_resources *resources;
241         struct fw_device *fw_dev = fw_parent_device(dice->unit);
242         int err = 0;
243 
244         if (dir == AMDTP_IN_STREAM) {
245                 streams = dice->tx_stream;
246                 resources = dice->tx_resources;
247         } else {
248                 streams = dice->rx_stream;
249                 resources = dice->rx_resources;
250         }
251 
252         err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
253         if (err < 0)
254                 return err;
255 
256         for (i = 0; i < params->count; i++) {
257                 unsigned int pcm_cache;
258                 unsigned int midi_cache;
259 
260                 if (dir == AMDTP_IN_STREAM) {
261                         pcm_cache = dice->tx_pcm_chs[i][mode];
262                         midi_cache = dice->tx_midi_ports[i];
263                         err = snd_dice_transaction_read_tx(dice,
264                                         params->size * i + TX_NUMBER_AUDIO,
265                                         reg, sizeof(reg));
266                 } else {
267                         pcm_cache = dice->rx_pcm_chs[i][mode];
268                         midi_cache = dice->rx_midi_ports[i];
269                         err = snd_dice_transaction_read_rx(dice,
270                                         params->size * i + RX_NUMBER_AUDIO,
271                                         reg, sizeof(reg));
272                 }
273                 if (err < 0)
274                         return err;
275                 pcm_chs = be32_to_cpu(reg[0]);
276                 midi_ports = be32_to_cpu(reg[1]);
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 
286                 err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports);
287                 if (err < 0)
288                         return err;
289 
290                 reg[0] = cpu_to_be32(resources[i].channel);
291                 if (dir == AMDTP_IN_STREAM) {
292                         err = snd_dice_transaction_write_tx(dice,
293                                         params->size * i + TX_ISOCHRONOUS,
294                                         reg, sizeof(reg[0]));
295                 } else {
296                         err = snd_dice_transaction_write_rx(dice,
297                                         params->size * i + RX_ISOCHRONOUS,
298                                         reg, sizeof(reg[0]));
299                 }
300                 if (err < 0)
301                         return err;
302 
303                 if (dir == AMDTP_IN_STREAM) {
304                         reg[0] = cpu_to_be32(fw_dev->max_speed);
305                         err = snd_dice_transaction_write_tx(dice,
306                                         params->size * i + TX_SPEED,
307                                         reg, sizeof(reg[0]));
308                         if (err < 0)
309                                 return err;
310                 }
311 
312                 err = amdtp_stream_start(&streams[i], resources[i].channel,
313                                          fw_dev->max_speed);
314                 if (err < 0)
315                         return err;
316         }
317 
318         return err;
319 }
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 
383 /*
384  * MEMO: After this function, there're two states of streams:
385  *  - None streams are running.
386  *  - All streams are running.
387  */
388 int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
389 {
390         unsigned int curr_rate;
391         unsigned int i;
392         enum snd_dice_rate_mode mode;
393         int err;
394 
395         if (dice->substreams_counter == 0)
396                 return -EIO;
397 
398         /* Check sampling transmission frequency. */
399         err = snd_dice_transaction_get_rate(dice, &curr_rate);
400         if (err < 0) {
401                 dev_err(&dice->unit->device,
402                         "fail to get sampling rate\n");
403                 return err;
404         }
405         if (rate == 0)
406                 rate = curr_rate;
407         if (rate != curr_rate)
408                 goto restart;
409 
410         /* Check error of packet streaming. */
411         for (i = 0; i < MAX_STREAMS; ++i) {
412                 if (amdtp_streaming_error(&dice->tx_stream[i]))
413                         break;
414                 if (amdtp_streaming_error(&dice->rx_stream[i]))
415                         break;
416         }
417         if (i < MAX_STREAMS)
418                 goto restart;
419 
420         /* Check required streams are running or not. */
421         err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
422         if (err < 0)
423                 return err;
424         for (i = 0; i < MAX_STREAMS; ++i) {
425                 if (dice->tx_pcm_chs[i][mode] > 0 &&
426                     !amdtp_stream_running(&dice->tx_stream[i]))
427                         break;
428                 if (dice->rx_pcm_chs[i][mode] > 0 &&
429                     !amdtp_stream_running(&dice->rx_stream[i]))
430                         break;
431         }
432         if (i < MAX_STREAMS)
433                 goto restart;
434 
435         return 0;
436 restart:
437         return start_duplex_streams(dice, rate);
438 }
439 
440 /*
441  * MEMO: After this function, there're two states of streams:
442  *  - None streams are running.
443  *  - All streams are running.
444  */
445 void snd_dice_stream_stop_duplex(struct snd_dice *dice)
446 {
447         struct reg_params tx_params, rx_params;
448 
449         if (dice->substreams_counter > 0)
450                 return;
451 
452         snd_dice_transaction_clear_enable(dice);
453 
454         if (get_register_params(dice, &tx_params, &rx_params) == 0) {
455                 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
456                 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
457         }
458 
459         release_resources(dice);
460 }
461 
462 static int init_stream(struct snd_dice *dice, enum amdtp_stream_direction dir,
463                        unsigned int index)
464 {
465         struct amdtp_stream *stream;
466         struct fw_iso_resources *resources;
467         int err;
468 
469         if (dir == AMDTP_IN_STREAM) {
470                 stream = &dice->tx_stream[index];
471                 resources = &dice->tx_resources[index];
472         } else {
473                 stream = &dice->rx_stream[index];
474                 resources = &dice->rx_resources[index];
475         }
476 
477         err = fw_iso_resources_init(resources, dice->unit);
478         if (err < 0)
479                 goto end;
480         resources->channels_mask = 0x00000000ffffffffuLL;
481 
482         err = amdtp_am824_init(stream, dice->unit, dir, CIP_BLOCKING);
483         if (err < 0) {
484                 amdtp_stream_destroy(stream);
485                 fw_iso_resources_destroy(resources);
486         }
487 end:
488         return err;
489 }
490 
491 /*
492  * This function should be called before starting streams or after stopping
493  * streams.
494  */
495 static void destroy_stream(struct snd_dice *dice,
496                            enum amdtp_stream_direction dir,
497                            unsigned int index)
498 {
499         struct amdtp_stream *stream;
500         struct fw_iso_resources *resources;
501 
502         if (dir == AMDTP_IN_STREAM) {
503                 stream = &dice->tx_stream[index];
504                 resources = &dice->tx_resources[index];
505         } else {
506                 stream = &dice->rx_stream[index];
507                 resources = &dice->rx_resources[index];
508         }
509 
510         amdtp_stream_destroy(stream);
511         fw_iso_resources_destroy(resources);
512 }
513 
514 int snd_dice_stream_init_duplex(struct snd_dice *dice)
515 {
516         int i, err;
517 
518         for (i = 0; i < MAX_STREAMS; i++) {
519                 err = init_stream(dice, AMDTP_IN_STREAM, i);
520                 if (err < 0) {
521                         for (; i >= 0; i--)
522                                 destroy_stream(dice, AMDTP_IN_STREAM, i);
523                         goto end;
524                 }
525         }
526 
527         for (i = 0; i < MAX_STREAMS; i++) {
528                 err = init_stream(dice, AMDTP_OUT_STREAM, i);
529                 if (err < 0) {
530                         for (; i >= 0; i--)
531                                 destroy_stream(dice, AMDTP_OUT_STREAM, i);
532                         for (i = 0; i < MAX_STREAMS; i++)
533                                 destroy_stream(dice, AMDTP_IN_STREAM, i);
534                         break;
535                 }
536         }
537 end:
538         return err;
539 }
540 
541 void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
542 {
543         unsigned int i;
544 
545         for (i = 0; i < MAX_STREAMS; i++) {
546                 destroy_stream(dice, AMDTP_IN_STREAM, i);
547                 destroy_stream(dice, AMDTP_OUT_STREAM, i);
548         }
549 }
550 
551 void snd_dice_stream_update_duplex(struct snd_dice *dice)
552 {
553         struct reg_params tx_params, rx_params;
554 
555         /*
556          * On a bus reset, the DICE firmware disables streaming and then goes
557          * off contemplating its own navel for hundreds of milliseconds before
558          * it can react to any of our attempts to reenable streaming.  This
559          * means that we lose synchronization anyway, so we force our streams
560          * to stop so that the application can restart them in an orderly
561          * manner.
562          */
563         dice->global_enabled = false;
564 
565         if (get_register_params(dice, &tx_params, &rx_params) == 0) {
566                 stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
567                 stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
568         }
569 }
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 
634 static void dice_lock_changed(struct snd_dice *dice)
635 {
636         dice->dev_lock_changed = true;
637         wake_up(&dice->hwdep_wait);
638 }
639 
640 int snd_dice_stream_lock_try(struct snd_dice *dice)
641 {
642         int err;
643 
644         spin_lock_irq(&dice->lock);
645 
646         if (dice->dev_lock_count < 0) {
647                 err = -EBUSY;
648                 goto out;
649         }
650 
651         if (dice->dev_lock_count++ == 0)
652                 dice_lock_changed(dice);
653         err = 0;
654 out:
655         spin_unlock_irq(&dice->lock);
656         return err;
657 }
658 
659 void snd_dice_stream_lock_release(struct snd_dice *dice)
660 {
661         spin_lock_irq(&dice->lock);
662 
663         if (WARN_ON(dice->dev_lock_count <= 0))
664                 goto out;
665 
666         if (--dice->dev_lock_count == 0)
667                 dice_lock_changed(dice);
668 out:
669         spin_unlock_irq(&dice->lock);
670 }
671 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp