Skip to content

Commit

Permalink
ALSA: usb-audio: use a format bitmask per alternate setting
Browse files Browse the repository at this point in the history
In preparation for USB audio 2.0 support, change the audioformat
structure so that it uses a bitmask to specify possible formats.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Clemens Ladisch authored and Takashi Iwai committed Mar 5, 2010
1 parent e11b4e0 commit 015eb0b
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 22 deletions.
2 changes: 1 addition & 1 deletion sound/usb/card.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

struct audioformat {
struct list_head list;
snd_pcm_format_t format; /* format type */
u64 formats; /* ALSA format bits */
unsigned int channels; /* # channels */
unsigned int fmt_type; /* USB audio format type (1-3) */
unsigned int frame_size; /* samples per frame for non-audio */
Expand Down
4 changes: 2 additions & 2 deletions sound/usb/endpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct au
if (subs->endpoint == fp->endpoint) {
list_add_tail(&fp->list, &subs->fmt_list);
subs->num_formats++;
subs->formats |= 1ULL << fp->format;
subs->formats |= fp->formats;
return 0;
}
}
Expand Down Expand Up @@ -268,7 +268,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
*/
if (fmt[4] == 1 && fmt[5] == 2 && altno == 2 && num == 3 &&
fp && fp->altsetting == 1 && fp->channels == 1 &&
fp->format == SNDRV_PCM_FORMAT_S16_LE &&
fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
protocol == UAC_VERSION_1 &&
le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
fp->maxpacksize * 2)
Expand Down
10 changes: 5 additions & 5 deletions sound/usb/format.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
return -1;
}

fp->format = pcm_format;
fp->formats = 1uLL << pcm_format;

/* gather possible sample rates */
/* audio class v1 reports possible sample rates as part of the
Expand Down Expand Up @@ -365,16 +365,16 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
switch (format) {
case UAC_FORMAT_TYPE_II_AC3:
/* FIXME: there is no AC3 format defined yet */
// fp->format = SNDRV_PCM_FORMAT_AC3;
fp->format = SNDRV_PCM_FORMAT_U8; /* temporarily hack to receive byte streams */
// fp->formats = SNDRV_PCM_FMTBIT_AC3;
fp->formats = SNDRV_PCM_FMTBIT_U8; /* temporary hack to receive byte streams */
break;
case UAC_FORMAT_TYPE_II_MPEG:
fp->format = SNDRV_PCM_FORMAT_MPEG;
fp->formats = SNDRV_PCM_FMTBIT_MPEG;
break;
default:
snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected. processed as MPEG.\n",
chip->dev->devnum, fp->iface, fp->altsetting, format);
fp->format = SNDRV_PCM_FORMAT_MPEG;
fp->formats = SNDRV_PCM_FMTBIT_MPEG;
break;
}

Expand Down
13 changes: 10 additions & 3 deletions sound/usb/pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned
list_for_each(p, &subs->fmt_list) {
struct audioformat *fp;
fp = list_entry(p, struct audioformat, list);
if (fp->format != format || fp->channels != channels)
if (!(fp->formats & (1uLL << format)))
continue;
if (fp->channels != channels)
continue;
if (rate < fp->rate_min || rate > fp->rate_max)
continue;
Expand Down Expand Up @@ -428,10 +430,15 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
struct snd_interval *pt = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
struct snd_mask check_fmts;
unsigned int ptime;

/* check the format */
if (!snd_mask_test(fmts, fp->format)) {
snd_mask_none(&check_fmts);
check_fmts.bits[0] = (u32)fp->formats;
check_fmts.bits[1] = (u32)(fp->formats >> 32);
snd_mask_intersect(&check_fmts, fmts);
if (snd_mask_empty(&check_fmts)) {
hwc_debug(" > check: no supported format %d\n", fp->format);
return 0;
}
Expand Down Expand Up @@ -584,7 +591,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
fp = list_entry(p, struct audioformat, list);
if (!hw_check_valid_format(subs, params, fp))
continue;
fbits |= (1ULL << fp->format);
fbits |= fp->formats;
}

oldbits[0] = fmt->bits[0];
Expand Down
9 changes: 7 additions & 2 deletions sound/usb/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,16 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s

list_for_each(p, &subs->fmt_list) {
struct audioformat *fp;
snd_pcm_format_t fmt;
fp = list_entry(p, struct audioformat, list);
snd_iprintf(buffer, " Interface %d\n", fp->iface);
snd_iprintf(buffer, " Altset %d\n", fp->altsetting);
snd_iprintf(buffer, " Format: %s\n",
snd_pcm_format_name(fp->format));
snd_iprintf(buffer, " Format:");
for (fmt = 0; fmt <= SNDRV_PCM_FORMAT_LAST; ++fmt)
if (fp->formats & (1uLL << fmt))
snd_iprintf(buffer, " %s",
snd_pcm_format_name(fmt));
snd_iprintf(buffer, "\n");
snd_iprintf(buffer, " Channels: %d\n", fp->channels);
snd_iprintf(buffer, " Endpoint: %d %s (%s)\n",
fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
Expand Down
12 changes: 6 additions & 6 deletions sound/usb/quirks-table.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 0,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S16_LE,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels = 4,
.iface = 0,
.altsetting = 1,
Expand All @@ -296,7 +296,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S16_LE,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels = 2,
.iface = 1,
.altsetting = 1,
Expand Down Expand Up @@ -580,7 +580,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 0,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S24_3LE,
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.iface = 0,
.altsetting = 1,
Expand All @@ -597,7 +597,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S24_3LE,
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.iface = 1,
.altsetting = 1,
Expand Down Expand Up @@ -793,7 +793,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S24_3LE,
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.iface = 1,
.altsetting = 1,
Expand All @@ -810,7 +810,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 2,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S24_3LE,
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.iface = 2,
.altsetting = 1,
Expand Down
2 changes: 1 addition & 1 deletion sound/usb/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
const struct snd_usb_audio_quirk *quirk)
{
static const struct audioformat ua_format = {
.format = SNDRV_PCM_FORMAT_S24_3LE,
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2,
.fmt_type = UAC_FORMAT_TYPE_I,
.altsetting = 1,
Expand Down
4 changes: 2 additions & 2 deletions sound/usb/urb.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
urb->number_of_packets = ctx->packets;
urb->transfer_buffer_length = offs * stride;
memset(urb->transfer_buffer,
subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
offs * stride);
return 0;
}
Expand Down Expand Up @@ -924,7 +924,7 @@ void snd_usb_init_substream(struct snd_usb_stream *as,
snd_usb_set_pcm_ops(as->pcm, stream);

list_add_tail(&fp->list, &subs->fmt_list);
subs->formats |= 1ULL << fp->format;
subs->formats |= fp->formats;
subs->endpoint = fp->endpoint;
subs->num_formats++;
subs->fmt_type = fp->fmt_type;
Expand Down

0 comments on commit 015eb0b

Please sign in to comment.