ASoC: mediatek: btcvsd add loopback
add direct loopback path from rx to tx Signed-off-by: KaiChieh Chuang <kaichieh.chuang@mediatek.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
7b6b0049e2
commit
f060f46f09
@ -49,6 +49,7 @@ enum bt_sco_state {
|
|||||||
BT_SCO_STATE_IDLE,
|
BT_SCO_STATE_IDLE,
|
||||||
BT_SCO_STATE_RUNNING,
|
BT_SCO_STATE_RUNNING,
|
||||||
BT_SCO_STATE_ENDING,
|
BT_SCO_STATE_ENDING,
|
||||||
|
BT_SCO_STATE_LOOPBACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bt_sco_direct {
|
enum bt_sco_direct {
|
||||||
@ -486,7 +487,8 @@ static irqreturn_t mtk_btcvsd_snd_irq_handler(int irq_id, void *dev)
|
|||||||
if (bt->rx->state != BT_SCO_STATE_RUNNING &&
|
if (bt->rx->state != BT_SCO_STATE_RUNNING &&
|
||||||
bt->rx->state != BT_SCO_STATE_ENDING &&
|
bt->rx->state != BT_SCO_STATE_ENDING &&
|
||||||
bt->tx->state != BT_SCO_STATE_RUNNING &&
|
bt->tx->state != BT_SCO_STATE_RUNNING &&
|
||||||
bt->tx->state != BT_SCO_STATE_ENDING) {
|
bt->tx->state != BT_SCO_STATE_ENDING &&
|
||||||
|
bt->tx->state != BT_SCO_STATE_LOOPBACK) {
|
||||||
dev_warn(bt->dev, "%s(), in idle state: rx->state: %d, tx->state: %d\n",
|
dev_warn(bt->dev, "%s(), in idle state: rx->state: %d, tx->state: %d\n",
|
||||||
__func__, bt->rx->state, bt->tx->state);
|
__func__, bt->rx->state, bt->tx->state);
|
||||||
goto irq_handler_exit;
|
goto irq_handler_exit;
|
||||||
@ -512,6 +514,42 @@ static irqreturn_t mtk_btcvsd_snd_irq_handler(int irq_id, void *dev)
|
|||||||
buf_cnt_tx = btsco_packet_info[packet_type][2];
|
buf_cnt_tx = btsco_packet_info[packet_type][2];
|
||||||
buf_cnt_rx = btsco_packet_info[packet_type][3];
|
buf_cnt_rx = btsco_packet_info[packet_type][3];
|
||||||
|
|
||||||
|
if (bt->tx->state == BT_SCO_STATE_LOOPBACK) {
|
||||||
|
u8 *src, *dst;
|
||||||
|
unsigned long connsys_addr_rx, ap_addr_rx;
|
||||||
|
unsigned long connsys_addr_tx, ap_addr_tx;
|
||||||
|
|
||||||
|
connsys_addr_rx = *bt->bt_reg_pkt_r;
|
||||||
|
ap_addr_rx = (unsigned long)bt->bt_sram_bank2_base +
|
||||||
|
(connsys_addr_rx & 0xFFFF);
|
||||||
|
|
||||||
|
connsys_addr_tx = *bt->bt_reg_pkt_w;
|
||||||
|
ap_addr_tx = (unsigned long)bt->bt_sram_bank2_base +
|
||||||
|
(connsys_addr_tx & 0xFFFF);
|
||||||
|
|
||||||
|
if (connsys_addr_tx == 0xdeadfeed ||
|
||||||
|
connsys_addr_rx == 0xdeadfeed) {
|
||||||
|
/* bt return 0xdeadfeed if read reg during bt sleep */
|
||||||
|
dev_warn(bt->dev, "%s(), connsys_addr_tx == 0xdeadfeed\n",
|
||||||
|
__func__);
|
||||||
|
goto irq_handler_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
src = (u8 *)ap_addr_rx;
|
||||||
|
dst = (u8 *)ap_addr_tx;
|
||||||
|
|
||||||
|
mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_BT2ARM, src,
|
||||||
|
bt->tx->temp_packet_buf,
|
||||||
|
packet_length,
|
||||||
|
packet_num);
|
||||||
|
mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_ARM2BT,
|
||||||
|
bt->tx->temp_packet_buf, dst,
|
||||||
|
packet_length,
|
||||||
|
packet_num);
|
||||||
|
bt->rx->rw_cnt++;
|
||||||
|
bt->tx->rw_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
if (bt->rx->state == BT_SCO_STATE_RUNNING ||
|
if (bt->rx->state == BT_SCO_STATE_RUNNING ||
|
||||||
bt->rx->state == BT_SCO_STATE_ENDING) {
|
bt->rx->state == BT_SCO_STATE_ENDING) {
|
||||||
if (bt->rx->xrun) {
|
if (bt->rx->xrun) {
|
||||||
@ -1067,6 +1105,33 @@ static int btcvsd_band_set(struct snd_kcontrol *kcontrol,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int btcvsd_loopback_get(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||||
|
struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
|
||||||
|
bool lpbk_en = bt->tx->state == BT_SCO_STATE_LOOPBACK;
|
||||||
|
|
||||||
|
ucontrol->value.integer.value[0] = lpbk_en;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int btcvsd_loopback_set(struct snd_kcontrol *kcontrol,
|
||||||
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
|
{
|
||||||
|
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
|
||||||
|
struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
|
||||||
|
|
||||||
|
if (ucontrol->value.integer.value[0]) {
|
||||||
|
mtk_btcvsd_snd_set_state(bt, bt->tx, BT_SCO_STATE_LOOPBACK);
|
||||||
|
mtk_btcvsd_snd_set_state(bt, bt->rx, BT_SCO_STATE_LOOPBACK);
|
||||||
|
} else {
|
||||||
|
mtk_btcvsd_snd_set_state(bt, bt->tx, BT_SCO_STATE_RUNNING);
|
||||||
|
mtk_btcvsd_snd_set_state(bt, bt->rx, BT_SCO_STATE_RUNNING);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int btcvsd_tx_mute_get(struct snd_kcontrol *kcontrol,
|
static int btcvsd_tx_mute_get(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_value *ucontrol)
|
struct snd_ctl_elem_value *ucontrol)
|
||||||
{
|
{
|
||||||
@ -1202,6 +1267,8 @@ static int btcvsd_tx_timestamp_get(struct snd_kcontrol *kcontrol,
|
|||||||
static const struct snd_kcontrol_new mtk_btcvsd_snd_controls[] = {
|
static const struct snd_kcontrol_new mtk_btcvsd_snd_controls[] = {
|
||||||
SOC_ENUM_EXT("BTCVSD Band", btcvsd_enum[0],
|
SOC_ENUM_EXT("BTCVSD Band", btcvsd_enum[0],
|
||||||
btcvsd_band_get, btcvsd_band_set),
|
btcvsd_band_get, btcvsd_band_set),
|
||||||
|
SOC_SINGLE_BOOL_EXT("BTCVSD Loopback Switch", 0,
|
||||||
|
btcvsd_loopback_get, btcvsd_loopback_set),
|
||||||
SOC_SINGLE_BOOL_EXT("BTCVSD Tx Mute Switch", 0,
|
SOC_SINGLE_BOOL_EXT("BTCVSD Tx Mute Switch", 0,
|
||||||
btcvsd_tx_mute_get, btcvsd_tx_mute_set),
|
btcvsd_tx_mute_get, btcvsd_tx_mute_set),
|
||||||
SOC_SINGLE_BOOL_EXT("BTCVSD Tx Irq Received Switch", 0,
|
SOC_SINGLE_BOOL_EXT("BTCVSD Tx Irq Received Switch", 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user