Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Takashi Sakamoto and committed by
Takashi Iwai
25ab2b2f 5c0a35b2

+75 -23
+73 -23
sound/firewire/oxfw/oxfw-stream.c
··· 486 486 enum avc_general_plug_dir dir, 487 487 struct snd_oxfw_stream_formation *formation) 488 488 { 489 - u8 *format; 490 - unsigned int len; 491 489 int err; 492 490 493 - len = AVC_GENERIC_FRAME_MAXIMUM_BYTES; 494 - format = kmalloc(len, GFP_KERNEL); 495 - if (format == NULL) 496 - return -ENOMEM; 491 + if (!(oxfw->quirks & SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED)) { 492 + u8 *format; 493 + unsigned int len; 497 494 498 - err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len); 499 - if (err < 0) 500 - goto end; 501 - if (len < 3) { 502 - err = -EIO; 503 - goto end; 495 + len = AVC_GENERIC_FRAME_MAXIMUM_BYTES; 496 + format = kmalloc(len, GFP_KERNEL); 497 + if (format == NULL) 498 + return -ENOMEM; 499 + 500 + err = avc_stream_get_format_single(oxfw->unit, dir, 0, format, &len); 501 + if (err >= 0) { 502 + if (len < 3) 503 + err = -EIO; 504 + else 505 + err = snd_oxfw_stream_parse_format(format, formation); 506 + } 507 + 508 + kfree(format); 509 + } else { 510 + // Miglia Harmony Audio does not support Extended Stream Format Information 511 + // command. Use the duplicated hard-coded format, instead. 512 + unsigned int rate; 513 + u8 *const *formats; 514 + int i; 515 + 516 + err = avc_general_get_sig_fmt(oxfw->unit, &rate, dir, 0); 517 + if (err < 0) 518 + return err; 519 + 520 + if (dir == AVC_GENERAL_PLUG_DIR_IN) 521 + formats = oxfw->rx_stream_formats; 522 + else 523 + formats = oxfw->tx_stream_formats; 524 + 525 + for (i = 0; (i < SND_OXFW_STREAM_FORMAT_ENTRIES); ++i) { 526 + if (!formats[i]) 527 + continue; 528 + 529 + err = snd_oxfw_stream_parse_format(formats[i], formation); 530 + if (err < 0) 531 + continue; 532 + 533 + if (formation->rate == rate) 534 + break; 535 + } 536 + if (i == SND_OXFW_STREAM_FORMAT_ENTRIES) 537 + return -EIO; 504 538 } 505 539 506 - err = snd_oxfw_stream_parse_format(format, formation); 507 - end: 508 - kfree(format); 509 540 return err; 510 541 } 511 542 ··· 631 600 unsigned int i, eid; 632 601 int err; 633 602 634 - /* get format at current sampling rate */ 635 - err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len); 636 - if (err < 0) { 637 - dev_err(&oxfw->unit->device, 638 - "fail to get current stream format for isoc %s plug %d:%d\n", 639 - (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out", 640 - pid, err); 641 - goto end; 603 + // get format at current sampling rate. 604 + if (!(oxfw->quirks & SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED)) { 605 + err = avc_stream_get_format_single(oxfw->unit, dir, pid, buf, len); 606 + if (err < 0) { 607 + dev_err(&oxfw->unit->device, 608 + "fail to get current stream format for isoc %s plug %d:%d\n", 609 + (dir == AVC_GENERAL_PLUG_DIR_IN) ? "in" : "out", 610 + pid, err); 611 + goto end; 612 + } 613 + } else { 614 + // Miglia Harmony Audio does not support Extended Stream Format Information 615 + // command. Use the hard-coded format, instead. 616 + buf[0] = 0x90; 617 + buf[1] = 0x40; 618 + buf[2] = avc_stream_rate_table[0]; 619 + buf[3] = 0x00; 620 + buf[4] = 0x01; 621 + 622 + if (dir == AVC_GENERAL_PLUG_DIR_IN) 623 + buf[5] = 0x08; 624 + else 625 + buf[5] = 0x02; 626 + 627 + buf[6] = 0x06; 628 + 629 + *len = 7; 642 630 } 643 631 644 632 /* parse and set stream format */
+2
sound/firewire/oxfw/oxfw.h
··· 52 52 // performs media clock recovery voluntarily. In the recovery, the packets with NO_INFO 53 53 // are ignored, thus driver should transfer packets with timestamp. 54 54 SND_OXFW_QUIRK_VOLUNTARY_RECOVERY = 0x20, 55 + // Miglia Harmony Audio does not support AV/C Stream Format Information command. 56 + SND_OXFW_QUIRK_STREAM_FORMAT_INFO_UNSUPPORTED = 0x40, 55 57 }; 56 58 57 59 /* This is an arbitrary number for convinience. */