Commit 015eb0b0 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Takashi Iwai

ALSA: usb-audio: use a format bitmask per alternate setting

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: default avatarClemens Ladisch <clemens@ladisch.de>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent e11b4e0e
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
struct audioformat { struct audioformat {
struct list_head list; struct list_head list;
snd_pcm_format_t format; /* format type */ u64 formats; /* ALSA format bits */
unsigned int channels; /* # channels */ unsigned int channels; /* # channels */
unsigned int fmt_type; /* USB audio format type (1-3) */ 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 */
......
...@@ -94,7 +94,7 @@ int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct au ...@@ -94,7 +94,7 @@ int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct au
if (subs->endpoint == fp->endpoint) { 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 |= fp->formats;
return 0; return 0;
} }
} }
...@@ -268,7 +268,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) ...@@ -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 && if (fmt[4] == 1 && fmt[5] == 2 && altno == 2 && num == 3 &&
fp && fp->altsetting == 1 && fp->channels == 1 && 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 && protocol == UAC_VERSION_1 &&
le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
fp->maxpacksize * 2) fp->maxpacksize * 2)
......
...@@ -323,7 +323,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, ...@@ -323,7 +323,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
return -1; return -1;
} }
fp->format = pcm_format; fp->formats = 1uLL << pcm_format;
/* gather possible sample rates */ /* gather possible sample rates */
/* audio class v1 reports possible sample rates as part of the /* audio class v1 reports possible sample rates as part of the
...@@ -365,16 +365,16 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, ...@@ -365,16 +365,16 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
switch (format) { switch (format) {
case UAC_FORMAT_TYPE_II_AC3: case UAC_FORMAT_TYPE_II_AC3:
/* FIXME: there is no AC3 format defined yet */ /* FIXME: there is no AC3 format defined yet */
// fp->format = SNDRV_PCM_FORMAT_AC3; // fp->formats = SNDRV_PCM_FMTBIT_AC3;
fp->format = SNDRV_PCM_FORMAT_U8; /* temporarily hack to receive byte streams */ fp->formats = SNDRV_PCM_FMTBIT_U8; /* temporary hack to receive byte streams */
break; break;
case UAC_FORMAT_TYPE_II_MPEG: case UAC_FORMAT_TYPE_II_MPEG:
fp->format = SNDRV_PCM_FORMAT_MPEG; fp->formats = SNDRV_PCM_FMTBIT_MPEG;
break; break;
default: default:
snd_printd(KERN_INFO "%d:%u:%d : unknown format tag %#x is detected. processed as MPEG.\n", 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); chip->dev->devnum, fp->iface, fp->altsetting, format);
fp->format = SNDRV_PCM_FORMAT_MPEG; fp->formats = SNDRV_PCM_FMTBIT_MPEG;
break; break;
} }
......
...@@ -58,7 +58,9 @@ static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned ...@@ -58,7 +58,9 @@ static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned
list_for_each(p, &subs->fmt_list) { list_for_each(p, &subs->fmt_list) {
struct audioformat *fp; struct audioformat *fp;
fp = list_entry(p, struct audioformat, list); 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; continue;
if (rate < fp->rate_min || rate > fp->rate_max) if (rate < fp->rate_min || rate > fp->rate_max)
continue; continue;
...@@ -428,10 +430,15 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, ...@@ -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_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_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_interval *pt = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
struct snd_mask check_fmts;
unsigned int ptime; unsigned int ptime;
/* check the format */ /* 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); hwc_debug(" > check: no supported format %d\n", fp->format);
return 0; return 0;
} }
...@@ -584,7 +591,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params, ...@@ -584,7 +591,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
fp = list_entry(p, struct audioformat, list); fp = list_entry(p, struct audioformat, list);
if (!hw_check_valid_format(subs, params, fp)) if (!hw_check_valid_format(subs, params, fp))
continue; continue;
fbits |= (1ULL << fp->format); fbits |= fp->formats;
} }
oldbits[0] = fmt->bits[0]; oldbits[0] = fmt->bits[0];
......
...@@ -79,11 +79,16 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s ...@@ -79,11 +79,16 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
list_for_each(p, &subs->fmt_list) { list_for_each(p, &subs->fmt_list) {
struct audioformat *fp; struct audioformat *fp;
snd_pcm_format_t fmt;
fp = list_entry(p, struct audioformat, list); fp = list_entry(p, struct audioformat, list);
snd_iprintf(buffer, " Interface %d\n", fp->iface); snd_iprintf(buffer, " Interface %d\n", fp->iface);
snd_iprintf(buffer, " Altset %d\n", fp->altsetting); snd_iprintf(buffer, " Altset %d\n", fp->altsetting);
snd_iprintf(buffer, " Format: %s\n", snd_iprintf(buffer, " Format:");
snd_pcm_format_name(fp->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, " Channels: %d\n", fp->channels);
snd_iprintf(buffer, " Endpoint: %d %s (%s)\n", snd_iprintf(buffer, " Endpoint: %d %s (%s)\n",
fp->endpoint & USB_ENDPOINT_NUMBER_MASK, fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
......
...@@ -279,7 +279,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -279,7 +279,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 0, .ifnum = 0,
.type = QUIRK_AUDIO_FIXED_ENDPOINT, .type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) { .data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S16_LE, .formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels = 4, .channels = 4,
.iface = 0, .iface = 0,
.altsetting = 1, .altsetting = 1,
...@@ -296,7 +296,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -296,7 +296,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 1, .ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT, .type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) { .data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S16_LE, .formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels = 2, .channels = 2,
.iface = 1, .iface = 1,
.altsetting = 1, .altsetting = 1,
...@@ -580,7 +580,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -580,7 +580,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 0, .ifnum = 0,
.type = QUIRK_AUDIO_FIXED_ENDPOINT, .type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) { .data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S24_3LE, .formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2, .channels = 2,
.iface = 0, .iface = 0,
.altsetting = 1, .altsetting = 1,
...@@ -597,7 +597,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -597,7 +597,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 1, .ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT, .type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) { .data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S24_3LE, .formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2, .channels = 2,
.iface = 1, .iface = 1,
.altsetting = 1, .altsetting = 1,
...@@ -793,7 +793,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -793,7 +793,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 1, .ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT, .type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) { .data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S24_3LE, .formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2, .channels = 2,
.iface = 1, .iface = 1,
.altsetting = 1, .altsetting = 1,
...@@ -810,7 +810,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -810,7 +810,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.ifnum = 2, .ifnum = 2,
.type = QUIRK_AUDIO_FIXED_ENDPOINT, .type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = & (const struct audioformat) { .data = & (const struct audioformat) {
.format = SNDRV_PCM_FORMAT_S24_3LE, .formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2, .channels = 2,
.iface = 2, .iface = 2,
.altsetting = 1, .altsetting = 1,
......
...@@ -174,7 +174,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, ...@@ -174,7 +174,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
const struct snd_usb_audio_quirk *quirk) const struct snd_usb_audio_quirk *quirk)
{ {
static const struct audioformat ua_format = { static const struct audioformat ua_format = {
.format = SNDRV_PCM_FORMAT_S24_3LE, .formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 2, .channels = 2,
.fmt_type = UAC_FORMAT_TYPE_I, .fmt_type = UAC_FORMAT_TYPE_I,
.altsetting = 1, .altsetting = 1,
......
...@@ -662,7 +662,7 @@ static int prepare_nodata_playback_urb(struct snd_usb_substream *subs, ...@@ -662,7 +662,7 @@ static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
urb->number_of_packets = ctx->packets; urb->number_of_packets = ctx->packets;
urb->transfer_buffer_length = offs * stride; urb->transfer_buffer_length = offs * stride;
memset(urb->transfer_buffer, memset(urb->transfer_buffer,
subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0, runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
offs * stride); offs * stride);
return 0; return 0;
} }
...@@ -924,7 +924,7 @@ void snd_usb_init_substream(struct snd_usb_stream *as, ...@@ -924,7 +924,7 @@ void snd_usb_init_substream(struct snd_usb_stream *as,
snd_usb_set_pcm_ops(as->pcm, stream); snd_usb_set_pcm_ops(as->pcm, stream);
list_add_tail(&fp->list, &subs->fmt_list); list_add_tail(&fp->list, &subs->fmt_list);
subs->formats |= 1ULL << fp->format; subs->formats |= fp->formats;
subs->endpoint = fp->endpoint; subs->endpoint = fp->endpoint;
subs->num_formats++; subs->num_formats++;
subs->fmt_type = fp->fmt_type; subs->fmt_type = fp->fmt_type;
......
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