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

TOMOYO Linux Cross Reference
Linux/sound/usb/hiface/pcm.c

Version: ~ [ linux-5.3-rc5 ] ~ [ linux-5.2.9 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.67 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.139 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.189 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.189 ] ~ [ 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.72 ] ~ [ 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  * Linux driver for M2Tech hiFace compatible devices
  3  *
  4  * Copyright 2012-2013 (C) M2TECH S.r.l and Amarula Solutions B.V.
  5  *
  6  * Authors:  Michael Trimarchi <michael@amarulasolutions.com>
  7  *           Antonio Ospite <ao2@amarulasolutions.com>
  8  *
  9  * The driver is based on the work done in TerraTec DMX 6Fire USB
 10  *
 11  * This program is free software; you can redistribute it and/or modify
 12  * it under the terms of the GNU General Public License as published by
 13  * the Free Software Foundation; either version 2 of the License, or
 14  * (at your option) any later version.
 15  */
 16 
 17 #include <linux/slab.h>
 18 #include <sound/pcm.h>
 19 
 20 #include "pcm.h"
 21 #include "chip.h"
 22 
 23 #define OUT_EP          0x2
 24 #define PCM_N_URBS      8
 25 #define PCM_PACKET_SIZE 4096
 26 #define PCM_BUFFER_SIZE (2 * PCM_N_URBS * PCM_PACKET_SIZE)
 27 
 28 struct pcm_urb {
 29         struct hiface_chip *chip;
 30 
 31         struct urb instance;
 32         struct usb_anchor submitted;
 33         u8 *buffer;
 34 };
 35 
 36 struct pcm_substream {
 37         spinlock_t lock;
 38         struct snd_pcm_substream *instance;
 39 
 40         bool active;
 41         snd_pcm_uframes_t dma_off;    /* current position in alsa dma_area */
 42         snd_pcm_uframes_t period_off; /* current position in current period */
 43 };
 44 
 45 enum { /* pcm streaming states */
 46         STREAM_DISABLED, /* no pcm streaming */
 47         STREAM_STARTING, /* pcm streaming requested, waiting to become ready */
 48         STREAM_RUNNING,  /* pcm streaming running */
 49         STREAM_STOPPING
 50 };
 51 
 52 struct pcm_runtime {
 53         struct hiface_chip *chip;
 54         struct snd_pcm *instance;
 55 
 56         struct pcm_substream playback;
 57         bool panic; /* if set driver won't do anymore pcm on device */
 58 
 59         struct pcm_urb out_urbs[PCM_N_URBS];
 60 
 61         struct mutex stream_mutex;
 62         u8 stream_state; /* one of STREAM_XXX */
 63         u8 extra_freq;
 64         wait_queue_head_t stream_wait_queue;
 65         bool stream_wait_cond;
 66 };
 67 
 68 static const unsigned int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000,
 69                                       352800, 384000 };
 70 static const struct snd_pcm_hw_constraint_list constraints_extra_rates = {
 71         .count = ARRAY_SIZE(rates),
 72         .list = rates,
 73         .mask = 0,
 74 };
 75 
 76 static const struct snd_pcm_hardware pcm_hw = {
 77         .info = SNDRV_PCM_INFO_MMAP |
 78                 SNDRV_PCM_INFO_INTERLEAVED |
 79                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
 80                 SNDRV_PCM_INFO_PAUSE |
 81                 SNDRV_PCM_INFO_MMAP_VALID |
 82                 SNDRV_PCM_INFO_BATCH,
 83 
 84         .formats = SNDRV_PCM_FMTBIT_S32_LE,
 85 
 86         .rates = SNDRV_PCM_RATE_44100 |
 87                 SNDRV_PCM_RATE_48000 |
 88                 SNDRV_PCM_RATE_88200 |
 89                 SNDRV_PCM_RATE_96000 |
 90                 SNDRV_PCM_RATE_176400 |
 91                 SNDRV_PCM_RATE_192000,
 92 
 93         .rate_min = 44100,
 94         .rate_max = 192000, /* changes in hiface_pcm_open to support extra rates */
 95         .channels_min = 2,
 96         .channels_max = 2,
 97         .buffer_bytes_max = PCM_BUFFER_SIZE,
 98         .period_bytes_min = PCM_PACKET_SIZE,
 99         .period_bytes_max = PCM_BUFFER_SIZE,
100         .periods_min = 2,
101         .periods_max = 1024
102 };
103 
104 /* message values used to change the sample rate */
105 #define HIFACE_SET_RATE_REQUEST 0xb0
106 
107 #define HIFACE_RATE_44100  0x43
108 #define HIFACE_RATE_48000  0x4b
109 #define HIFACE_RATE_88200  0x42
110 #define HIFACE_RATE_96000  0x4a
111 #define HIFACE_RATE_176400 0x40
112 #define HIFACE_RATE_192000 0x48
113 #define HIFACE_RATE_352800 0x58
114 #define HIFACE_RATE_384000 0x68
115 
116 static int hiface_pcm_set_rate(struct pcm_runtime *rt, unsigned int rate)
117 {
118         struct usb_device *device = rt->chip->dev;
119         u16 rate_value;
120         int ret;
121 
122         /* We are already sure that the rate is supported here thanks to
123          * ALSA constraints
124          */
125         switch (rate) {
126         case 44100:
127                 rate_value = HIFACE_RATE_44100;
128                 break;
129         case 48000:
130                 rate_value = HIFACE_RATE_48000;
131                 break;
132         case 88200:
133                 rate_value = HIFACE_RATE_88200;
134                 break;
135         case 96000:
136                 rate_value = HIFACE_RATE_96000;
137                 break;
138         case 176400:
139                 rate_value = HIFACE_RATE_176400;
140                 break;
141         case 192000:
142                 rate_value = HIFACE_RATE_192000;
143                 break;
144         case 352800:
145                 rate_value = HIFACE_RATE_352800;
146                 break;
147         case 384000:
148                 rate_value = HIFACE_RATE_384000;
149                 break;
150         default:
151                 dev_err(&device->dev, "Unsupported rate %d\n", rate);
152                 return -EINVAL;
153         }
154 
155         /*
156          * USBIO: Vendor 0xb0(wValue=0x0043, wIndex=0x0000)
157          * 43 b0 43 00 00 00 00 00
158          * USBIO: Vendor 0xb0(wValue=0x004b, wIndex=0x0000)
159          * 43 b0 4b 00 00 00 00 00
160          * This control message doesn't have any ack from the
161          * other side
162          */
163         ret = usb_control_msg(device, usb_sndctrlpipe(device, 0),
164                               HIFACE_SET_RATE_REQUEST,
165                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
166                               rate_value, 0, NULL, 0, 100);
167         if (ret < 0) {
168                 dev_err(&device->dev, "Error setting samplerate %d.\n", rate);
169                 return ret;
170         }
171 
172         return 0;
173 }
174 
175 static struct pcm_substream *hiface_pcm_get_substream(struct snd_pcm_substream
176                                                       *alsa_sub)
177 {
178         struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
179         struct device *device = &rt->chip->dev->dev;
180 
181         if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
182                 return &rt->playback;
183 
184         dev_err(device, "Error getting pcm substream slot.\n");
185         return NULL;
186 }
187 
188 /* call with stream_mutex locked */
189 static void hiface_pcm_stream_stop(struct pcm_runtime *rt)
190 {
191         int i, time;
192 
193         if (rt->stream_state != STREAM_DISABLED) {
194                 rt->stream_state = STREAM_STOPPING;
195 
196                 for (i = 0; i < PCM_N_URBS; i++) {
197                         time = usb_wait_anchor_empty_timeout(
198                                         &rt->out_urbs[i].submitted, 100);
199                         if (!time)
200                                 usb_kill_anchored_urbs(
201                                         &rt->out_urbs[i].submitted);
202                         usb_kill_urb(&rt->out_urbs[i].instance);
203                 }
204 
205                 rt->stream_state = STREAM_DISABLED;
206         }
207 }
208 
209 /* call with stream_mutex locked */
210 static int hiface_pcm_stream_start(struct pcm_runtime *rt)
211 {
212         int ret = 0;
213         int i;
214 
215         if (rt->stream_state == STREAM_DISABLED) {
216 
217                 /* reset panic state when starting a new stream */
218                 rt->panic = false;
219 
220                 /* submit our out urbs zero init */
221                 rt->stream_state = STREAM_STARTING;
222                 for (i = 0; i < PCM_N_URBS; i++) {
223                         memset(rt->out_urbs[i].buffer, 0, PCM_PACKET_SIZE);
224                         usb_anchor_urb(&rt->out_urbs[i].instance,
225                                        &rt->out_urbs[i].submitted);
226                         ret = usb_submit_urb(&rt->out_urbs[i].instance,
227                                              GFP_ATOMIC);
228                         if (ret) {
229                                 hiface_pcm_stream_stop(rt);
230                                 return ret;
231                         }
232                 }
233 
234                 /* wait for first out urb to return (sent in in urb handler) */
235                 wait_event_timeout(rt->stream_wait_queue, rt->stream_wait_cond,
236                                    HZ);
237                 if (rt->stream_wait_cond) {
238                         struct device *device = &rt->chip->dev->dev;
239                         dev_dbg(device, "%s: Stream is running wakeup event\n",
240                                  __func__);
241                         rt->stream_state = STREAM_RUNNING;
242                 } else {
243                         hiface_pcm_stream_stop(rt);
244                         return -EIO;
245                 }
246         }
247         return ret;
248 }
249 
250 /* The hardware wants word-swapped 32-bit values */
251 static void memcpy_swahw32(u8 *dest, u8 *src, unsigned int n)
252 {
253         unsigned int i;
254 
255         for (i = 0; i < n / 4; i++)
256                 ((u32 *)dest)[i] = swahw32(((u32 *)src)[i]);
257 }
258 
259 /* call with substream locked */
260 /* returns true if a period elapsed */
261 static bool hiface_pcm_playback(struct pcm_substream *sub, struct pcm_urb *urb)
262 {
263         struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
264         struct device *device = &urb->chip->dev->dev;
265         u8 *source;
266         unsigned int pcm_buffer_size;
267 
268         WARN_ON(alsa_rt->format != SNDRV_PCM_FORMAT_S32_LE);
269 
270         pcm_buffer_size = snd_pcm_lib_buffer_bytes(sub->instance);
271 
272         if (sub->dma_off + PCM_PACKET_SIZE <= pcm_buffer_size) {
273                 dev_dbg(device, "%s: (1) buffer_size %#x dma_offset %#x\n", __func__,
274                          (unsigned int) pcm_buffer_size,
275                          (unsigned int) sub->dma_off);
276 
277                 source = alsa_rt->dma_area + sub->dma_off;
278                 memcpy_swahw32(urb->buffer, source, PCM_PACKET_SIZE);
279         } else {
280                 /* wrap around at end of ring buffer */
281                 unsigned int len;
282 
283                 dev_dbg(device, "%s: (2) buffer_size %#x dma_offset %#x\n", __func__,
284                          (unsigned int) pcm_buffer_size,
285                          (unsigned int) sub->dma_off);
286 
287                 len = pcm_buffer_size - sub->dma_off;
288 
289                 source = alsa_rt->dma_area + sub->dma_off;
290                 memcpy_swahw32(urb->buffer, source, len);
291 
292                 source = alsa_rt->dma_area;
293                 memcpy_swahw32(urb->buffer + len, source,
294                                PCM_PACKET_SIZE - len);
295         }
296         sub->dma_off += PCM_PACKET_SIZE;
297         if (sub->dma_off >= pcm_buffer_size)
298                 sub->dma_off -= pcm_buffer_size;
299 
300         sub->period_off += PCM_PACKET_SIZE;
301         if (sub->period_off >= alsa_rt->period_size) {
302                 sub->period_off %= alsa_rt->period_size;
303                 return true;
304         }
305         return false;
306 }
307 
308 static void hiface_pcm_out_urb_handler(struct urb *usb_urb)
309 {
310         struct pcm_urb *out_urb = usb_urb->context;
311         struct pcm_runtime *rt = out_urb->chip->pcm;
312         struct pcm_substream *sub;
313         bool do_period_elapsed = false;
314         unsigned long flags;
315         int ret;
316 
317         if (rt->panic || rt->stream_state == STREAM_STOPPING)
318                 return;
319 
320         if (unlikely(usb_urb->status == -ENOENT ||      /* unlinked */
321                      usb_urb->status == -ENODEV ||      /* device removed */
322                      usb_urb->status == -ECONNRESET ||  /* unlinked */
323                      usb_urb->status == -ESHUTDOWN)) {  /* device disabled */
324                 goto out_fail;
325         }
326 
327         if (rt->stream_state == STREAM_STARTING) {
328                 rt->stream_wait_cond = true;
329                 wake_up(&rt->stream_wait_queue);
330         }
331 
332         /* now send our playback data (if a free out urb was found) */
333         sub = &rt->playback;
334         spin_lock_irqsave(&sub->lock, flags);
335         if (sub->active)
336                 do_period_elapsed = hiface_pcm_playback(sub, out_urb);
337         else
338                 memset(out_urb->buffer, 0, PCM_PACKET_SIZE);
339 
340         spin_unlock_irqrestore(&sub->lock, flags);
341 
342         if (do_period_elapsed)
343                 snd_pcm_period_elapsed(sub->instance);
344 
345         ret = usb_submit_urb(&out_urb->instance, GFP_ATOMIC);
346         if (ret < 0)
347                 goto out_fail;
348 
349         return;
350 
351 out_fail:
352         rt->panic = true;
353 }
354 
355 static int hiface_pcm_open(struct snd_pcm_substream *alsa_sub)
356 {
357         struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
358         struct pcm_substream *sub = NULL;
359         struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
360         int ret;
361 
362         if (rt->panic)
363                 return -EPIPE;
364 
365         mutex_lock(&rt->stream_mutex);
366         alsa_rt->hw = pcm_hw;
367 
368         if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
369                 sub = &rt->playback;
370 
371         if (!sub) {
372                 struct device *device = &rt->chip->dev->dev;
373                 mutex_unlock(&rt->stream_mutex);
374                 dev_err(device, "Invalid stream type\n");
375                 return -EINVAL;
376         }
377 
378         if (rt->extra_freq) {
379                 alsa_rt->hw.rates |= SNDRV_PCM_RATE_KNOT;
380                 alsa_rt->hw.rate_max = 384000;
381 
382                 /* explicit constraints needed as we added SNDRV_PCM_RATE_KNOT */
383                 ret = snd_pcm_hw_constraint_list(alsa_sub->runtime, 0,
384                                                  SNDRV_PCM_HW_PARAM_RATE,
385                                                  &constraints_extra_rates);
386                 if (ret < 0) {
387                         mutex_unlock(&rt->stream_mutex);
388                         return ret;
389                 }
390         }
391 
392         sub->instance = alsa_sub;
393         sub->active = false;
394         mutex_unlock(&rt->stream_mutex);
395         return 0;
396 }
397 
398 static int hiface_pcm_close(struct snd_pcm_substream *alsa_sub)
399 {
400         struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
401         struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub);
402         unsigned long flags;
403 
404         if (rt->panic)
405                 return 0;
406 
407         mutex_lock(&rt->stream_mutex);
408         if (sub) {
409                 hiface_pcm_stream_stop(rt);
410 
411                 /* deactivate substream */
412                 spin_lock_irqsave(&sub->lock, flags);
413                 sub->instance = NULL;
414                 sub->active = false;
415                 spin_unlock_irqrestore(&sub->lock, flags);
416 
417         }
418         mutex_unlock(&rt->stream_mutex);
419         return 0;
420 }
421 
422 static int hiface_pcm_hw_params(struct snd_pcm_substream *alsa_sub,
423                                 struct snd_pcm_hw_params *hw_params)
424 {
425         return snd_pcm_lib_alloc_vmalloc_buffer(alsa_sub,
426                                                 params_buffer_bytes(hw_params));
427 }
428 
429 static int hiface_pcm_hw_free(struct snd_pcm_substream *alsa_sub)
430 {
431         return snd_pcm_lib_free_vmalloc_buffer(alsa_sub);
432 }
433 
434 static int hiface_pcm_prepare(struct snd_pcm_substream *alsa_sub)
435 {
436         struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
437         struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub);
438         struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
439         int ret;
440 
441         if (rt->panic)
442                 return -EPIPE;
443         if (!sub)
444                 return -ENODEV;
445 
446         mutex_lock(&rt->stream_mutex);
447 
448         sub->dma_off = 0;
449         sub->period_off = 0;
450 
451         if (rt->stream_state == STREAM_DISABLED) {
452 
453                 ret = hiface_pcm_set_rate(rt, alsa_rt->rate);
454                 if (ret) {
455                         mutex_unlock(&rt->stream_mutex);
456                         return ret;
457                 }
458                 ret = hiface_pcm_stream_start(rt);
459                 if (ret) {
460                         mutex_unlock(&rt->stream_mutex);
461                         return ret;
462                 }
463         }
464         mutex_unlock(&rt->stream_mutex);
465         return 0;
466 }
467 
468 static int hiface_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd)
469 {
470         struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub);
471         struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
472 
473         if (rt->panic)
474                 return -EPIPE;
475         if (!sub)
476                 return -ENODEV;
477 
478         switch (cmd) {
479         case SNDRV_PCM_TRIGGER_START:
480         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
481                 spin_lock_irq(&sub->lock);
482                 sub->active = true;
483                 spin_unlock_irq(&sub->lock);
484                 return 0;
485 
486         case SNDRV_PCM_TRIGGER_STOP:
487         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
488                 spin_lock_irq(&sub->lock);
489                 sub->active = false;
490                 spin_unlock_irq(&sub->lock);
491                 return 0;
492 
493         default:
494                 return -EINVAL;
495         }
496 }
497 
498 static snd_pcm_uframes_t hiface_pcm_pointer(struct snd_pcm_substream *alsa_sub)
499 {
500         struct pcm_substream *sub = hiface_pcm_get_substream(alsa_sub);
501         struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
502         unsigned long flags;
503         snd_pcm_uframes_t dma_offset;
504 
505         if (rt->panic || !sub)
506                 return SNDRV_PCM_POS_XRUN;
507 
508         spin_lock_irqsave(&sub->lock, flags);
509         dma_offset = sub->dma_off;
510         spin_unlock_irqrestore(&sub->lock, flags);
511         return bytes_to_frames(alsa_sub->runtime, dma_offset);
512 }
513 
514 static struct snd_pcm_ops pcm_ops = {
515         .open = hiface_pcm_open,
516         .close = hiface_pcm_close,
517         .ioctl = snd_pcm_lib_ioctl,
518         .hw_params = hiface_pcm_hw_params,
519         .hw_free = hiface_pcm_hw_free,
520         .prepare = hiface_pcm_prepare,
521         .trigger = hiface_pcm_trigger,
522         .pointer = hiface_pcm_pointer,
523         .page = snd_pcm_lib_get_vmalloc_page,
524         .mmap = snd_pcm_lib_mmap_vmalloc,
525 };
526 
527 static int hiface_pcm_init_urb(struct pcm_urb *urb,
528                                struct hiface_chip *chip,
529                                unsigned int ep,
530                                void (*handler)(struct urb *))
531 {
532         urb->chip = chip;
533         usb_init_urb(&urb->instance);
534 
535         urb->buffer = kzalloc(PCM_PACKET_SIZE, GFP_KERNEL);
536         if (!urb->buffer)
537                 return -ENOMEM;
538 
539         usb_fill_bulk_urb(&urb->instance, chip->dev,
540                           usb_sndbulkpipe(chip->dev, ep), (void *)urb->buffer,
541                           PCM_PACKET_SIZE, handler, urb);
542         init_usb_anchor(&urb->submitted);
543 
544         return 0;
545 }
546 
547 void hiface_pcm_abort(struct hiface_chip *chip)
548 {
549         struct pcm_runtime *rt = chip->pcm;
550 
551         if (rt) {
552                 rt->panic = true;
553 
554                 mutex_lock(&rt->stream_mutex);
555                 hiface_pcm_stream_stop(rt);
556                 mutex_unlock(&rt->stream_mutex);
557         }
558 }
559 
560 static void hiface_pcm_destroy(struct hiface_chip *chip)
561 {
562         struct pcm_runtime *rt = chip->pcm;
563         int i;
564 
565         for (i = 0; i < PCM_N_URBS; i++)
566                 kfree(rt->out_urbs[i].buffer);
567 
568         kfree(chip->pcm);
569         chip->pcm = NULL;
570 }
571 
572 static void hiface_pcm_free(struct snd_pcm *pcm)
573 {
574         struct pcm_runtime *rt = pcm->private_data;
575 
576         if (rt)
577                 hiface_pcm_destroy(rt->chip);
578 }
579 
580 int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
581 {
582         int i;
583         int ret;
584         struct snd_pcm *pcm;
585         struct pcm_runtime *rt;
586 
587         rt = kzalloc(sizeof(*rt), GFP_KERNEL);
588         if (!rt)
589                 return -ENOMEM;
590 
591         rt->chip = chip;
592         rt->stream_state = STREAM_DISABLED;
593         if (extra_freq)
594                 rt->extra_freq = 1;
595 
596         init_waitqueue_head(&rt->stream_wait_queue);
597         mutex_init(&rt->stream_mutex);
598         spin_lock_init(&rt->playback.lock);
599 
600         for (i = 0; i < PCM_N_URBS; i++)
601                 hiface_pcm_init_urb(&rt->out_urbs[i], chip, OUT_EP,
602                                     hiface_pcm_out_urb_handler);
603 
604         ret = snd_pcm_new(chip->card, "USB-SPDIF Audio", 0, 1, 0, &pcm);
605         if (ret < 0) {
606                 kfree(rt);
607                 dev_err(&chip->dev->dev, "Cannot create pcm instance\n");
608                 return ret;
609         }
610 
611         pcm->private_data = rt;
612         pcm->private_free = hiface_pcm_free;
613 
614         strlcpy(pcm->name, "USB-SPDIF Audio", sizeof(pcm->name));
615         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
616 
617         rt->instance = pcm;
618 
619         chip->pcm = rt;
620         return 0;
621 }
622 

~ [ 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