Commit 6b2d0620 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA CVS update - Takashi Iwai <tiwai@suse.de>

USB generic driver
- assign PCM unique (sub)streams for each USB format type.
  this will avoid the mix up of format I and format III on M-audio transit.
parent 136bba83
...@@ -117,7 +117,7 @@ struct audioformat { ...@@ -117,7 +117,7 @@ struct audioformat {
struct list_head list; struct list_head list;
snd_pcm_format_t format; /* format type */ snd_pcm_format_t format; /* format type */
unsigned int channels; /* # channels */ unsigned int channels; /* # channels */
unsigned int nonaudio: 1; /* non-audio (type II) */ unsigned int fmt_type; /* USB audio format type (1-3) */
unsigned int frame_size; /* samples per frame for non-audio */ unsigned int frame_size; /* samples per frame for non-audio */
int iface; /* interface number */ int iface; /* interface number */
unsigned char altsetting; /* corresponding alternate setting */ unsigned char altsetting; /* corresponding alternate setting */
...@@ -171,7 +171,7 @@ struct snd_usb_substream { ...@@ -171,7 +171,7 @@ struct snd_usb_substream {
unsigned int curpacksize; /* current packet size in bytes (for capture) */ unsigned int curpacksize; /* current packet size in bytes (for capture) */
unsigned int curframesize; /* current packet size in frames (for capture) */ unsigned int curframesize; /* current packet size in frames (for capture) */
unsigned int fill_max: 1; /* fill max packet size always */ unsigned int fill_max: 1; /* fill max packet size always */
unsigned int nonaudio: 1; /* Type II format (MPEG, AC3) */ unsigned int fmt_type; /* USB audio format type (1-3) */
unsigned int running: 1; /* running status */ unsigned int running: 1; /* running status */
...@@ -201,6 +201,7 @@ struct snd_usb_stream { ...@@ -201,6 +201,7 @@ struct snd_usb_stream {
snd_usb_audio_t *chip; snd_usb_audio_t *chip;
snd_pcm_t *pcm; snd_pcm_t *pcm;
int pcm_index; int pcm_index;
unsigned int fmt_type; /* USB audio format type (1-3) */
snd_usb_substream_t substream[2]; snd_usb_substream_t substream[2];
struct list_head list; struct list_head list;
}; };
...@@ -477,7 +478,7 @@ static int prepare_playback_urb(snd_usb_substream_t *subs, ...@@ -477,7 +478,7 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
subs->transfer_sched += counts; subs->transfer_sched += counts;
if (subs->transfer_sched >= runtime->period_size) { if (subs->transfer_sched >= runtime->period_size) {
subs->transfer_sched -= runtime->period_size; subs->transfer_sched -= runtime->period_size;
if (subs->nonaudio) { if (subs->fmt_type == USB_FORMAT_TYPE_II) {
if (subs->transfer_sched > 0) { if (subs->transfer_sched > 0) {
/* FIXME: fill-max mode is not supported yet */ /* FIXME: fill-max mode is not supported yet */
offs -= subs->transfer_sched; offs -= subs->transfer_sched;
...@@ -894,7 +895,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by ...@@ -894,7 +895,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
u->subs = subs; u->subs = subs;
u->transfer = 0; u->transfer = 0;
u->packets = npacks[i]; u->packets = npacks[i];
if (subs->nonaudio) if (subs->fmt_type == USB_FORMAT_TYPE_II)
u->packets++; /* for transfer delimiter */ u->packets++; /* for transfer delimiter */
if (! is_playback) { if (! is_playback) {
/* allocate a capture buffer per urb */ /* allocate a capture buffer per urb */
...@@ -1588,7 +1589,7 @@ static int setup_hw_info(snd_pcm_runtime_t *runtime, snd_usb_substream_t *subs) ...@@ -1588,7 +1589,7 @@ static int setup_hw_info(snd_pcm_runtime_t *runtime, snd_usb_substream_t *subs)
runtime->hw.channels_min = fp->channels; runtime->hw.channels_min = fp->channels;
if (runtime->hw.channels_max < fp->channels) if (runtime->hw.channels_max < fp->channels)
runtime->hw.channels_max = fp->channels; runtime->hw.channels_max = fp->channels;
if (fp->nonaudio && fp->frame_size > 0) { if (fp->fmt_type == USB_FORMAT_TYPE_II && fp->frame_size > 0) {
/* FIXME: there might be more than one audio formats... */ /* FIXME: there might be more than one audio formats... */
runtime->hw.period_bytes_min = runtime->hw.period_bytes_max = runtime->hw.period_bytes_min = runtime->hw.period_bytes_max =
fp->frame_size; fp->frame_size;
...@@ -1895,7 +1896,7 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat ...@@ -1895,7 +1896,7 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat
subs->formats |= 1ULL << fp->format; subs->formats |= 1ULL << fp->format;
subs->endpoint = fp->endpoint; subs->endpoint = fp->endpoint;
subs->num_formats++; subs->num_formats++;
subs->nonaudio = fp->nonaudio; subs->fmt_type = fp->fmt_type;
} }
...@@ -1954,17 +1955,12 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor ...@@ -1954,17 +1955,12 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
list_for_each(p, &chip->pcm_list) { list_for_each(p, &chip->pcm_list) {
as = list_entry(p, snd_usb_stream_t, list); as = list_entry(p, snd_usb_stream_t, list);
if (as->fmt_type != fp->fmt_type)
continue;
subs = &as->substream[stream]; subs = &as->substream[stream];
if (! subs->endpoint) if (! subs->endpoint)
break;
if (subs->endpoint == fp->endpoint) {
if (fp->nonaudio) {
if (!subs->nonaudio || subs->formats != (1ULL << fp->format))
continue; /* non-linear formats are handled exclusively */
} else {
if (subs->nonaudio)
continue; continue;
} if (subs->endpoint == fp->endpoint) {
list_add_tail(&fp->list, &subs->fmt_list); list_add_tail(&fp->list, &subs->fmt_list);
subs->num_formats++; subs->num_formats++;
subs->formats |= 1ULL << fp->format; subs->formats |= 1ULL << fp->format;
...@@ -1974,6 +1970,8 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor ...@@ -1974,6 +1970,8 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
/* look for an empty stream */ /* look for an empty stream */
list_for_each(p, &chip->pcm_list) { list_for_each(p, &chip->pcm_list) {
as = list_entry(p, snd_usb_stream_t, list); as = list_entry(p, snd_usb_stream_t, list);
if (as->fmt_type != fp->fmt_type)
continue;
subs = &as->substream[stream]; subs = &as->substream[stream];
if (subs->endpoint) if (subs->endpoint)
continue; continue;
...@@ -1991,6 +1989,7 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor ...@@ -1991,6 +1989,7 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
memset(as, 0, sizeof(*as)); memset(as, 0, sizeof(*as));
as->pcm_index = chip->pcm_devs; as->pcm_index = chip->pcm_devs;
as->chip = chip; as->chip = chip;
as->fmt_type = fp->fmt_type;
err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs, err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0, stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1, stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
...@@ -2216,7 +2215,6 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp, ...@@ -2216,7 +2215,6 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
break; break;
} }
fp->channels = 1; fp->channels = 1;
fp->nonaudio = 1;
brate = combine_word(&fmt[4]); /* fmt[4,5] : wMaxBitRate (in kbps) */ brate = combine_word(&fmt[4]); /* fmt[4,5] : wMaxBitRate (in kbps) */
framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */ framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */
snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
...@@ -2242,6 +2240,7 @@ static int parse_audio_format(struct usb_device *dev, struct audioformat *fp, ...@@ -2242,6 +2240,7 @@ static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
dev->devnum, fp->iface, fp->altsetting, fmt[3]); dev->devnum, fp->iface, fp->altsetting, fmt[3]);
return -1; return -1;
} }
fp->fmt_type = fmt[3];
if (err < 0) if (err < 0)
return err; return err;
#if 1 #if 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment