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.

(cherry picked from commit 84e6845aa6)
This commit is contained in:
Pauli Virtanen 2026-04-16 22:51:51 +03:00
parent b2028a03f0
commit bb6199214d
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;
}