btfmcodec: Add btadv audio support
This change adds below support for BT advance audio * Add support for codec type mixer control * Update slim driver to read master id, channel number. * Update slim driver to support HW EP. * Add support for transport switch based on the request CRs-Fixed: 3298745 Change-Id: Ica349cb6f3615f4dc51bbc3070c90d43eeba1cdd
This commit is contained in:
@@ -5,4 +5,4 @@ bt_fm_slim-objs := btfm_slim.o btfm_slim_codec.o btfm_slim_slave.o
|
||||
obj-$(CONFIG_BTFM_SLIM) += bt_fm_slim.o
|
||||
# Below src is for BTFM Driver support based on btfm codec
|
||||
btfm_slim_codec-objs := btfm_slim.o btfm_slim_hw_interface.o btfm_slim_slave.o
|
||||
obj-$(CONFIG_SLIM_BTFM_CODEC) += btfm_slim_codec.o
|
||||
obj-$(CONFIG_SLIM_BTFM_CODEC) += btfm_slim_codec.o
|
||||
|
@@ -515,6 +515,67 @@ int btfm_slim_hw_deinit(struct btfmslim *btfmslim)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if IS_ENABLED (CONFIG_BTFM_SLIM)
|
||||
void btfm_slim_get_hwep_details(struct slim_device *dev, struct btfmslim *btfm_slim)
|
||||
{
|
||||
}
|
||||
#else
|
||||
void btfm_slim_get_hwep_details(struct slim_device *slim, struct btfmslim *btfm_slim)
|
||||
{
|
||||
struct device_node *np = slim->dev.of_node;
|
||||
const __be32 *prop;
|
||||
struct btfmslim_ch *rx_chs = btfm_slim->rx_chs;
|
||||
struct btfmslim_ch *tx_chs = btfm_slim->tx_chs;
|
||||
int len;
|
||||
|
||||
prop = of_get_property(np, "qcom,btslim-address", &len);
|
||||
if (prop) {
|
||||
btfm_slim->device_id = be32_to_cpup(&prop[0]);
|
||||
BTFMSLIM_DBG("hwep slim address define in dt %08x", btfm_slim->device_id);
|
||||
} else {
|
||||
BTFMSLIM_ERR("btslim-address is not defined in dt using default address");
|
||||
btfm_slim->device_id = 0;
|
||||
}
|
||||
|
||||
if (!rx_chs || !tx_chs) {
|
||||
BTFMSLIM_ERR("either rx/tx channels are configured to null");
|
||||
return;
|
||||
}
|
||||
|
||||
prop = of_get_property(np, "qcom,btslimrx-channels", &len);
|
||||
if (prop) {
|
||||
/* Check if we need any protection for index */
|
||||
rx_chs[0].ch = (uint8_t)be32_to_cpup(&prop[0]);
|
||||
rx_chs[1].ch = (uint8_t)be32_to_cpup(&prop[1]);
|
||||
BTFMSLIM_DBG("Rx: id\tname\tport\tch");
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%d", rx_chs[0].id,
|
||||
rx_chs[0].name, rx_chs[0].port,
|
||||
rx_chs[0].ch);
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%d", rx_chs[1].id,
|
||||
rx_chs[1].name, rx_chs[1].port,
|
||||
rx_chs[1].ch);
|
||||
} else {
|
||||
BTFMSLIM_ERR("btslimrx channels are missing in dt using default values");
|
||||
}
|
||||
|
||||
prop = of_get_property(np, "qcom,btslimtx-channels", &len);
|
||||
if (prop) {
|
||||
/* Check if we need any protection for index */
|
||||
tx_chs[0].ch = (uint8_t)be32_to_cpup(&prop[0]);
|
||||
tx_chs[1].ch = (uint8_t)be32_to_cpup(&prop[1]);
|
||||
BTFMSLIM_DBG("Tx: id\tname\tport\tch");
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%x", tx_chs[0].id,
|
||||
tx_chs[0].name, tx_chs[0].port,
|
||||
tx_chs[0].ch);
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%x", tx_chs[1].id,
|
||||
tx_chs[1].name, tx_chs[1].port,
|
||||
tx_chs[1].ch);
|
||||
} else {
|
||||
BTFMSLIM_ERR("btslimtx channels are missing in dt using default values");
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
static int btfm_slim_status(struct slim_device *sdev,
|
||||
enum slim_device_status status)
|
||||
{
|
||||
@@ -526,6 +587,7 @@ static int btfm_slim_status(struct slim_device *sdev,
|
||||
#if IS_ENABLED(CONFIG_BTFM_SLIM)
|
||||
ret = btfm_slim_register_codec(btfm_slim);
|
||||
#else
|
||||
btfm_slim_get_hwep_details(sdev, btfm_slim);
|
||||
ret = btfm_slim_register_hw_ep(btfm_slim);
|
||||
#endif
|
||||
if (ret)
|
||||
|
@@ -73,6 +73,9 @@ struct btfmslim {
|
||||
int (*vendor_init)(struct btfmslim *btfmslim);
|
||||
int (*vendor_port_en)(struct btfmslim *btfmslim, uint8_t port_num,
|
||||
uint8_t rxport, uint8_t enable);
|
||||
#if IS_ENABLED(CONFIG_SLIM_BTFM_CODEC)
|
||||
int device_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int btfm_feedback_ch_setting;
|
||||
|
@@ -26,15 +26,16 @@
|
||||
|
||||
static int bt_soc_enable_status;
|
||||
int btfm_feedback_ch_setting;
|
||||
static uint8_t usecase_codec;
|
||||
|
||||
static int btfm_slim_codec_write(struct snd_soc_component *codec,
|
||||
static int btfm_slim_hwep_write(struct snd_soc_component *codec,
|
||||
unsigned int reg, unsigned int value)
|
||||
{
|
||||
BTFMSLIM_DBG("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int btfm_slim_codec_read(struct snd_soc_component *codec,
|
||||
static unsigned int btfm_slim_hwep_read(struct snd_soc_component *codec,
|
||||
unsigned int reg)
|
||||
{
|
||||
BTFMSLIM_DBG("");
|
||||
@@ -72,25 +73,39 @@ static int btfm_put_feedback_ch_setting(struct snd_kcontrol *kcontrol,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new status_controls[] = {
|
||||
static int btfm_get_codec_type(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
BTFMSLIM_DBG("current codec type:%s", codec_text[usecase_codec]);
|
||||
ucontrol->value.integer.value[0] = usecase_codec;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int btfm_put_codec_type(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
usecase_codec = ucontrol->value.integer.value[0];
|
||||
BTFMSLIM_DBG("codec type set to:%s", codec_text[usecase_codec]);
|
||||
return 1;
|
||||
}
|
||||
static struct snd_kcontrol_new status_controls[] = {
|
||||
SOC_SINGLE_EXT("BT SOC status", 0, 0, 1, 0,
|
||||
btfm_soc_status_get,
|
||||
btfm_soc_status_put),
|
||||
btfm_soc_status_get, btfm_soc_status_put),
|
||||
SOC_SINGLE_EXT("BT set feedback channel", 0, 0, 1, 0,
|
||||
btfm_get_feedback_ch_setting,
|
||||
btfm_put_feedback_ch_setting)
|
||||
btfm_put_feedback_ch_setting),
|
||||
SOC_ENUM_EXT("BT codec type", codec_display,
|
||||
btfm_get_codec_type, btfm_put_codec_type),
|
||||
};
|
||||
|
||||
|
||||
static int btfm_slim_codec_probe(struct snd_soc_component *codec)
|
||||
static int btfm_slim_hwep_probe(struct snd_soc_component *codec)
|
||||
{
|
||||
BTFMSLIM_DBG("");
|
||||
snd_soc_add_component_controls(codec, status_controls,
|
||||
ARRAY_SIZE(status_controls));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btfm_slim_codec_remove(struct snd_soc_component *codec)
|
||||
static void btfm_slim_hwep_remove(struct snd_soc_component *codec)
|
||||
{
|
||||
BTFMSLIM_DBG("");
|
||||
}
|
||||
@@ -163,6 +178,30 @@ static int btfm_slim_dai_hw_params(void *dai, uint32_t bps,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void btfm_get_sampling_rate(uint32_t *sampling_rate)
|
||||
{
|
||||
uint8_t codec_types_avb = ARRAY_SIZE(codec_text);
|
||||
if (usecase_codec > (codec_types_avb - 1)) {
|
||||
BTFMSLIM_ERR("falling back to use default sampling_rate: %u",
|
||||
*sampling_rate);
|
||||
return;
|
||||
}
|
||||
|
||||
if (*sampling_rate == 44100 || *sampling_rate == 48000) {
|
||||
if (usecase_codec == LDAC ||
|
||||
usecase_codec == APTX_AD)
|
||||
*sampling_rate = (*sampling_rate) *2;
|
||||
}
|
||||
|
||||
if (usecase_codec == LC3_VOICE ||
|
||||
usecase_codec == APTX_AD_SPEECH ||
|
||||
usecase_codec == LC3 || usecase_codec == APTX_AD_QLEA) {
|
||||
*sampling_rate = 96000;
|
||||
}
|
||||
|
||||
BTFMSLIM_INFO("current usecase codec type %s and sampling rate:%u khz",
|
||||
codec_text[usecase_codec], *sampling_rate);
|
||||
}
|
||||
static int btfm_slim_dai_prepare(void *dai, uint32_t sampling_rate, uint32_t direction, int id)
|
||||
{
|
||||
struct hwep_data *hwep_info = (struct hwep_data *)dai;
|
||||
@@ -175,6 +214,7 @@ static int btfm_slim_dai_prepare(void *dai, uint32_t sampling_rate, uint32_t dir
|
||||
btfmslim->direction = direction;
|
||||
bt_soc_enable_status = 0;
|
||||
|
||||
btfm_get_sampling_rate(&sampling_rate);
|
||||
/* save sample rate */
|
||||
btfmslim->sample_rate = sampling_rate;
|
||||
|
||||
@@ -254,7 +294,7 @@ static int btfm_slim_dai_set_channel_map(void *dai,
|
||||
* get channel handler from slimbus driver
|
||||
*/
|
||||
rx_chs->ch = *(uint8_t *)(rx_slot + i);
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%x\t%d\t%x", rx_chs->id,
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%x", rx_chs->id,
|
||||
rx_chs->name, rx_chs->port, rx_chs->ch);
|
||||
}
|
||||
|
||||
@@ -265,7 +305,7 @@ static int btfm_slim_dai_set_channel_map(void *dai,
|
||||
* get channel handler from slimbus driver
|
||||
*/
|
||||
tx_chs->ch = *(uint8_t *)(tx_slot + i);
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%x\t%d\t%x", tx_chs->id,
|
||||
BTFMSLIM_DBG(" %d\t%s\t%d\t%x", tx_chs->id,
|
||||
tx_chs->name, tx_chs->port, tx_chs->ch);
|
||||
}
|
||||
|
||||
@@ -352,6 +392,45 @@ static int btfm_slim_dai_get_channel_map(void *dai,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btfm_slim_dai_get_configs (void * dai,
|
||||
struct master_hwep_configurations *hwep_config,
|
||||
uint8_t id)
|
||||
{
|
||||
struct hwep_data *hwep_info = (struct hwep_data *)dai;
|
||||
struct btfmslim *btfmslim = dev_get_drvdata(hwep_info->dev);
|
||||
struct btfmslim_ch *ch = NULL;
|
||||
int i = 0;
|
||||
|
||||
BTFMSLIM_DBG("");
|
||||
hwep_config->stream_id = id;
|
||||
hwep_config->device_id = btfmslim->device_id;
|
||||
hwep_config->sample_rate = btfmslim->sample_rate;
|
||||
hwep_config->bit_width = (uint8_t)btfmslim->bps;
|
||||
hwep_config->codectype = usecase_codec;
|
||||
hwep_config->direction = btfmslim->direction;
|
||||
|
||||
switch (id) {
|
||||
case BTFM_FM_SLIM_TX:
|
||||
case BTFM_BT_SCO_SLIM_TX:
|
||||
ch = btfmslim->tx_chs;
|
||||
break;
|
||||
case BTFM_BT_SCO_A2DP_SLIM_RX:
|
||||
case BTFM_BT_SPLIT_A2DP_SLIM_RX:
|
||||
ch = btfmslim->rx_chs;
|
||||
break;
|
||||
}
|
||||
|
||||
for (; i < id ; i++) {
|
||||
if (ch[i].id == id) {
|
||||
BTFMSLIM_DBG("id matched");
|
||||
hwep_config->num_channels = 1;
|
||||
hwep_config->chan_num = ch[i].ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
static struct hwep_dai_ops btfmslim_hw_dai_ops = {
|
||||
.hwep_startup = btfm_slim_dai_startup,
|
||||
.hwep_shutdown = btfm_slim_dai_shutdown,
|
||||
@@ -359,6 +438,8 @@ static struct hwep_dai_ops btfmslim_hw_dai_ops = {
|
||||
.hwep_prepare = btfm_slim_dai_prepare,
|
||||
.hwep_set_channel_map = btfm_slim_dai_set_channel_map,
|
||||
.hwep_get_channel_map = btfm_slim_dai_get_channel_map,
|
||||
.hwep_get_configs = btfm_slim_dai_get_configs,
|
||||
.hwep_codectype = &usecase_codec,
|
||||
};
|
||||
|
||||
static struct hwep_dai_driver btfmslim_dai_driver[] = {
|
||||
@@ -403,10 +484,10 @@ static struct hwep_dai_driver btfmslim_dai_driver[] = {
|
||||
};
|
||||
|
||||
static struct hwep_comp_drv btfmslim_hw_driver = {
|
||||
.hwep_probe = btfm_slim_codec_probe,
|
||||
.hwep_remove = btfm_slim_codec_remove,
|
||||
.hwep_read = btfm_slim_codec_read,
|
||||
.hwep_write = btfm_slim_codec_write,
|
||||
.hwep_probe = btfm_slim_hwep_probe,
|
||||
.hwep_remove = btfm_slim_hwep_remove,
|
||||
.hwep_read = btfm_slim_hwep_read,
|
||||
.hwep_write = btfm_slim_hwep_write,
|
||||
};
|
||||
|
||||
int btfm_slim_register_hw_ep(struct btfmslim *btfm_slim)
|
||||
@@ -431,6 +512,8 @@ int btfm_slim_register_hw_ep(struct btfmslim *btfm_slim)
|
||||
hwep_info->dai_drv = btfmslim_dai_driver;
|
||||
hwep_info->num_dai = ARRAY_SIZE(btfmslim_dai_driver);
|
||||
hwep_info->num_dai = 2;
|
||||
hwep_info->num_mixer_ctrl = ARRAY_SIZE(status_controls);
|
||||
hwep_info->mixer_ctrl = status_controls;
|
||||
set_bit(BTADV_AUDIO_MASTER_CONFIG, &hwep_info->flags);
|
||||
/* Register to hardware endpoint */
|
||||
ret = btfmcodec_register_hw_ep(hwep_info);
|
||||
|
@@ -15,4 +15,28 @@
|
||||
// Todo protect with flags
|
||||
int btfm_slim_register_hw_ep(struct btfmslim *btfm_slim);
|
||||
void btfm_slim_unregister_hwep(void);
|
||||
|
||||
typedef enum Codec {
|
||||
SBC = 0,
|
||||
AAC,
|
||||
LDAC,
|
||||
APTX,
|
||||
APTX_HD,
|
||||
APTX_AD,
|
||||
LC3,
|
||||
APTX_AD_SPEECH,
|
||||
LC3_VOICE,
|
||||
APTX_AD_QLEA,
|
||||
APTX_AD_R4,
|
||||
NO_CODEC
|
||||
} codectype;
|
||||
|
||||
static char const *codec_text[] = {"CODEC_TYPE_SBC", "CODEC_TYPE_AAC",
|
||||
"CODEC_TYPE_LDAC", "CODEC_TYPE_APTX",
|
||||
"CODEC_TYPE_APTX_HD", "CODEC_TYPE_APTX_AD",
|
||||
"CODEC_TYPE_LC3", "CODEC_TYPE_APTX_AD_SPEECH",
|
||||
"CODEC_TYPE_LC3_VOICE", "CODEC_TYPE_APTX_AD_QLEA",
|
||||
"CODEC_TYPE_APTX_AD_R4","CODEC_TYPE_INVALID"};
|
||||
|
||||
static SOC_ENUM_SINGLE_EXT_DECL(codec_display, codec_text);
|
||||
#endif /*__LINUX_BTFM_SLIM_HW_INTERFACE_H*/
|
||||
|
Reference in New Issue
Block a user