Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 */
+2 −2
Original line number Diff line number Diff line
@@ -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;
		}
	}
@@ -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)
+5 −5
Original line number Diff line number Diff line
@@ -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
@@ -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;
	}

+10 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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;
	}
@@ -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];
+7 −2
Original line number Diff line number Diff line
@@ -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,
Loading