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: Takashi Sakamoto <o-takashi@sakamocchi.jp> Link: https://lore.kernel.org/r/20240218074128.95210-3-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
5c0a35b26f
commit
25ab2b2f6a
@ -486,26 +486,57 @@ int snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
|
|||||||
enum avc_general_plug_dir dir,
|
enum avc_general_plug_dir dir,
|
||||||
struct snd_oxfw_stream_formation *formation)
|
struct snd_oxfw_stream_formation *formation)
|
||||||
{
|
{
|
||||||
u8 *format;
|
|
||||||
unsigned int len;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
|
if (!(oxfw->quirks & SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED)) {
|
||||||
format = kmalloc(len, GFP_KERNEL);
|
u8 *format;
|
||||||
if (format == NULL)
|
unsigned int len;
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len);
|
len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
|
||||||
if (err < 0)
|
format = kmalloc(len, GFP_KERNEL);
|
||||||
goto end;
|
if (format == NULL)
|
||||||
if (len < 3) {
|
return -ENOMEM;
|
||||||
err = -EIO;
|
|
||||||
goto end;
|
err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len);
|
||||||
|
if (err >= 0) {
|
||||||
|
if (len < 3)
|
||||||
|
err = -EIO;
|
||||||
|
else
|
||||||
|
err = snd_oxfw_stream_parse_format(format, formation);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = snd_oxfw_stream_parse_format(format, formation);
|
|
||||||
end:
|
|
||||||
kfree(format);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,14 +631,33 @@ assume_stream_formats(struct snd_oxfw *oxfw, enum avc_general_plug_dir dir,
|
|||||||
unsigned int i, eid;
|
unsigned int i, eid;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* get format at current sampling rate */
|
// get format at current sampling rate.
|
||||||
err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len);
|
if (!(oxfw->quirks & SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED)) {
|
||||||
if (err < 0) {
|
err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len);
|
||||||
dev_err(&oxfw->unit->device,
|
if (err < 0) {
|
||||||
"fail to get current stream format for isoc %s plug %d:%d\n",
|
dev_err(&oxfw->unit->device,
|
||||||
(dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
|
"fail to get current stream format for isoc %s plug %d:%d\n",
|
||||||
pid, err);
|
(dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out",
|
||||||
goto end;
|
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 */
|
/* parse and set stream format */
|
||||||
|
@ -52,6 +52,8 @@ enum snd_oxfw_quirk {
|
|||||||
// performs media clock recovery voluntarily. In the recovery, the packets with NO_INFO
|
// performs media clock recovery voluntarily. In the recovery, the packets with NO_INFO
|
||||||
// are ignored, thus driver should transfer packets with timestamp.
|
// are ignored, thus driver should transfer packets with timestamp.
|
||||||
SND_OXFW_QUIRK_VOLUNTARY_RECOVERY = 0x20,
|
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. */
|
/* This is an arbitrary number for convinience. */
|
||||||
|
Loading…
Reference in New Issue
Block a user