bluez5: add quirk for LC3-24kHz for HFP

MT7925 fails to setup a SCO connection that results to working LC3-24kHz
audio. Other controllers (Intel etc) appear to work OK.

Add quirk for disabling this codec, and disable it for this Mediatek
controller.
This commit is contained in:
Pauli Virtanen 2026-04-16 22:51:51 +03:00 committed by Wim Taymans
parent 6e8e234e61
commit 84e6845aa6
4 changed files with 17 additions and 1 deletions

View file

@ -904,7 +904,7 @@ static bool device_supports_codec(struct impl *backend, struct spa_bt_device *de
{
int res;
bool alt6_ok = true, alt1_ok = true;
bool msbc_alt6_ok = true, msbc_alt1_ok = true;
bool msbc_alt6_ok = true, msbc_alt1_ok = true, lc3_a127_ok = true;
uint32_t bt_features;
if (device->adapter == NULL)
@ -913,6 +913,7 @@ static bool device_supports_codec(struct impl *backend, struct spa_bt_device *de
if (backend->quirks && spa_bt_quirks_get_features(backend->quirks, device->adapter, device, &bt_features) == 0) {
msbc_alt1_ok = (bt_features & (SPA_BT_FEATURE_MSBC_ALT1 | SPA_BT_FEATURE_MSBC_ALT1_RTL));
msbc_alt6_ok = (bt_features & SPA_BT_FEATURE_MSBC);
lc3_a127_ok = (bt_features & SPA_BT_FEATURE_LC3_A127);
}
switch (codec) {
@ -922,6 +923,10 @@ static bool device_supports_codec(struct impl *backend, struct spa_bt_device *de
alt1_ok = msbc_alt1_ok;
alt6_ok = msbc_alt6_ok;
break;
case SPA_BLUETOOTH_AUDIO_CODEC_LC3_A127:
alt1_ok = false;
alt6_ok = lc3_a127_ok;
break;
case SPA_BLUETOOTH_AUDIO_CODEC_LC3_SWB:
default:
/* LC3-SWB has same transport requirements as msbc.

View file

@ -15,6 +15,7 @@
# sbc-xq "nonstandard" SBC codec setting with better sound quality
# faststream FastStream codec support
# a2dp-duplex A2DP duplex codec support
# lc3-a127 HFP LC3-24KHz codec support
#
# Features are disabled with the key "no-features" whose value is an
# array of strings in the match rule.
@ -83,6 +84,9 @@ bluez5.features.adapter = [
# Realtek Semiconductor Corp.
{ bus-type = "usb", vendor-id = "usb:0bda" },
# Mediatek MT7925, #pipewire-5213
{ bus-type = "usb", vendor-id = "usb:0e8d", product-id = "e025", no-features = [ lc3-a127 ] },
# Generic USB adapters
{ bus-type = "usb", no-features = [ msbc-alt1-rtl ] },

View file

@ -811,6 +811,7 @@ enum spa_bt_feature {
SPA_BT_FEATURE_SBC_XQ = (1 << 5),
SPA_BT_FEATURE_FASTSTREAM = (1 << 6),
SPA_BT_FEATURE_A2DP_DUPLEX = (1 << 7),
SPA_BT_FEATURE_LC3_A127 = (1 << 8),
};
struct spa_bt_quirks;

View file

@ -52,6 +52,7 @@ struct spa_bt_quirks {
int force_sbc_xq;
int force_faststream;
int force_a2dp_duplex;
int force_lc3_a127;
char *device_rules;
char *adapter_rules;
@ -69,6 +70,7 @@ static enum spa_bt_feature parse_feature(const char *str)
{ "sbc-xq", SPA_BT_FEATURE_SBC_XQ },
{ "faststream", SPA_BT_FEATURE_FASTSTREAM },
{ "a2dp-duplex", SPA_BT_FEATURE_A2DP_DUPLEX },
{ "lc3-a127", SPA_BT_FEATURE_LC3_A127 },
};
SPA_FOR_EACH_ELEMENT_VAR(feature_keys, f) {
if (spa_streq(str, f->key))
@ -228,6 +230,7 @@ struct spa_bt_quirks *spa_bt_quirks_create(const struct spa_dict *info, struct s
this->force_hw_volume = parse_force_flag(info, "bluez5.enable-hw-volume");
this->force_faststream = parse_force_flag(info, "bluez5.enable-faststream");
this->force_a2dp_duplex = parse_force_flag(info, "bluez5.enable-a2dp-duplex");
this->force_lc3_a127 = parse_force_flag(info, "bluez5.enable-lc3-a127");
if ((str = spa_dict_lookup(info, "bluez5.hardware-database")) != NULL) {
spa_log_debug(this->log, "loading session manager provided data");
@ -385,6 +388,9 @@ static int get_features(const struct spa_bt_quirks *this,
if (this->force_a2dp_duplex != -1)
SPA_FLAG_UPDATE(*features, SPA_BT_FEATURE_A2DP_DUPLEX, this->force_a2dp_duplex);
if (this->force_lc3_a127 != -1)
SPA_FLAG_UPDATE(*features, SPA_BT_FEATURE_LC3_A127, this->force_lc3_a127);
return 0;
}