Commit 25ab2b2f authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai
Browse files

ALSA: oxfw: support the case that AV/C Stream Format Information command is not available



Miglia Harmony Audio does neither support AV/C Stream Format Information
command nor AV/C Extended Stream Format Information command.

This commit adds a workaround for the case and uses the hard-coded formats.

Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Link: https://lore.kernel.org/r/20240218074128.95210-3-o-takashi@sakamocchi.jp


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 5c0a35b2
Loading
Loading
Loading
Loading
+73 −23
Original line number Diff line number Diff line
@@ -486,9 +486,11 @@ int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
				enum avc_general_plug_dir dir,
				struct snd_oxfw_stream_formation *formation)
{
	int err;

	if (!(oxfw->quirks & SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED)) {
		u8 *format;
		unsigned int len;
	int err;

		len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
		format = kmalloc(len, GFP_KERNEL);
@@ -496,16 +498,45 @@ int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
			return -ENOMEM;

		err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len);
	if (err < 0)
		goto end;
	if (len < 3) {
		if (err >= 0) {
			if (len < 3)
				err = -EIO;
		goto end;
			else
				err = snd_oxfw_stream_parse_format(format, formation);
		}

	err = snd_oxfw_stream_parse_format(format, formation);
end:
		kfree(format);
	} else {
		// Miglia Harmony Audio does not support Extended Stream Format Information
		// command. Use the duplicated hard-coded format, instead.
		unsigned int rate;
		u8 *const *formats;
		int i;

		err = avc_general_get_sig_fmt(oxfw->unit, &rate, dir, 0);
		if (err < 0)
			return err;

		if (dir == AVC_GENERAL_PLUG_DIR_IN)
			formats = oxfw->rx_stream_formats;
		else
			formats = oxfw->tx_stream_formats;

		for (i = 0; (i < SND_OXFW_STREAM_FORMAT_ENTRIES); ++i) {
			if (!formats[i])
				continue;

			err = snd_oxfw_stream_parse_format(formats[i], formation);
			if (err < 0)
				continue;

			if (formation->rate == rate)
				break;
		}
		if (i == SND_OXFW_STREAM_FORMAT_ENTRIES)
			return -EIO;
	}

	return err;
}

@@ -600,7 +631,8 @@ assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
	unsigned int i, eid;
	int err;

	/* get format at current sampling rate */
	// get format at current sampling rate.
	if (!(oxfw->quirks & SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED)) {
		err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len);
		if (err < 0) {
			dev_err(&oxfw->unit->device,
@@ -609,6 +641,24 @@ assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
				pid, err);
			goto end;
		}
	} else {
		// Miglia Harmony Audio does not support Extended Stream Format Information
		// command. Use the hard-coded format, instead.
		buf[0] = 0x90;
		buf[1] = 0x40;
		buf[2] = avc_stream_rate_table[0];
		buf[3] = 0x00;
		buf[4] = 0x01;

		if (dir == AVC_GENERAL_PLUG_DIR_IN)
			buf[5] = 0x08;
		else
			buf[5] = 0x02;

		buf[6] = 0x06;

		*len = 7;
	}

	/* parse and set stream format */
	eid = 0;
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ enum snd_oxfw_quirk {
	// performs media clock recovery voluntarily. In the recovery, the packets with NO_INFO
	// are ignored, thus driver should transfer packets with timestamp.
	SND_OXFW_QUIRK_VOLUNTARY_RECOVERY = 0x20,
	// Miglia Harmony Audio does not support AV/C Stream Format Information command.
	SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED = 0x40,
};

/* This is an arbitrary number for convinience. */