summaryrefslogtreecommitdiffstats
path: root/sound/soc/mediatek/common
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/mediatek/common')
-rw-r--r--sound/soc/mediatek/common/mtk-afe-fe-dai.c51
-rw-r--r--sound/soc/mediatek/common/mtk-btcvsd.c73
2 files changed, 90 insertions, 34 deletions
diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
index cf4978be062f..fded11d14cde 100644
--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
+++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
@@ -18,11 +18,11 @@
static int mtk_regmap_update_bits(struct regmap *map, int reg,
unsigned int mask,
- unsigned int val)
+ unsigned int val, int shift)
{
- if (reg < 0)
+ if (reg < 0 || WARN_ON_ONCE(shift < 0))
return 0;
- return regmap_update_bits(map, reg, mask, val);
+ return regmap_update_bits(map, reg, mask << shift, val << shift);
}
static int mtk_regmap_write(struct regmap *map, int reg, unsigned int val)
@@ -49,8 +49,7 @@ int mtk_afe_fe_startup(struct snd_pcm_substream *substream,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
/* enable agent */
mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg,
- 1 << memif->data->agent_disable_shift,
- 0 << memif->data->agent_disable_shift);
+ 1, 0, memif->data->agent_disable_shift);
snd_soc_set_runtime_hwparams(substream, mtk_afe_hardware);
@@ -105,8 +104,7 @@ void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream,
irq_id = memif->irq_usage;
mtk_regmap_update_bits(afe->regmap, memif->data->agent_disable_reg,
- 1 << memif->data->agent_disable_shift,
- 1 << memif->data->agent_disable_shift);
+ 1, 1, memif->data->agent_disable_shift);
if (!memif->const_irq) {
mtk_dynamic_irq_release(afe, irq_id);
@@ -144,16 +142,14 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
/* set MSB to 33-bit */
mtk_regmap_update_bits(afe->regmap, memif->data->msb_reg,
- 1 << memif->data->msb_shift,
- msb_at_bit33 << memif->data->msb_shift);
+ 1, msb_at_bit33, memif->data->msb_shift);
/* set channel */
if (memif->data->mono_shift >= 0) {
unsigned int mono = (params_channels(params) == 1) ? 1 : 0;
mtk_regmap_update_bits(afe->regmap, memif->data->mono_reg,
- 1 << memif->data->mono_shift,
- mono << memif->data->mono_shift);
+ 1, mono, memif->data->mono_shift);
}
/* set rate */
@@ -166,8 +162,8 @@ int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
mtk_regmap_update_bits(afe->regmap, memif->data->fs_reg,
- memif->data->fs_maskbit << memif->data->fs_shift,
- fs << memif->data->fs_shift);
+ memif->data->fs_maskbit, fs,
+ memif->data->fs_shift);
return 0;
}
@@ -197,17 +193,14 @@ int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
- if (memif->data->enable_shift >= 0)
- mtk_regmap_update_bits(afe->regmap,
- memif->data->enable_reg,
- 1 << memif->data->enable_shift,
- 1 << memif->data->enable_shift);
+ mtk_regmap_update_bits(afe->regmap,
+ memif->data->enable_reg,
+ 1, 1, memif->data->enable_shift);
/* set irq counter */
mtk_regmap_update_bits(afe->regmap, irq_data->irq_cnt_reg,
- irq_data->irq_cnt_maskbit
- << irq_data->irq_cnt_shift,
- counter << irq_data->irq_cnt_shift);
+ irq_data->irq_cnt_maskbit, counter,
+ irq_data->irq_cnt_shift);
/* set irq fs */
fs = afe->irq_fs(substream, runtime->rate);
@@ -216,24 +209,21 @@ int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd,
return -EINVAL;
mtk_regmap_update_bits(afe->regmap, irq_data->irq_fs_reg,
- irq_data->irq_fs_maskbit
- << irq_data->irq_fs_shift,
- fs << irq_data->irq_fs_shift);
+ irq_data->irq_fs_maskbit, fs,
+ irq_data->irq_fs_shift);
/* enable interrupt */
mtk_regmap_update_bits(afe->regmap, irq_data->irq_en_reg,
- 1 << irq_data->irq_en_shift,
- 1 << irq_data->irq_en_shift);
+ 1, 1, irq_data->irq_en_shift);
return 0;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
mtk_regmap_update_bits(afe->regmap, memif->data->enable_reg,
- 1 << memif->data->enable_shift, 0);
+ 1, 0, memif->data->enable_shift);
/* disable interrupt */
mtk_regmap_update_bits(afe->regmap, irq_data->irq_en_reg,
- 1 << irq_data->irq_en_shift,
- 0 << irq_data->irq_en_shift);
+ 1, 0, irq_data->irq_en_shift);
/* and clear pending IRQ */
mtk_regmap_write(afe->regmap, irq_data->irq_clr_reg,
1 << irq_data->irq_clr_shift);
@@ -270,8 +260,7 @@ int mtk_afe_fe_prepare(struct snd_pcm_substream *substream,
}
mtk_regmap_update_bits(afe->regmap, memif->data->hd_reg,
- 1 << memif->data->hd_shift,
- hd_audio << memif->data->hd_shift);
+ 1, hd_audio, memif->data->hd_shift);
return 0;
}
diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c
index 1b8bcdaf02d1..bd55c546e790 100644
--- a/sound/soc/mediatek/common/mtk-btcvsd.c
+++ b/sound/soc/mediatek/common/mtk-btcvsd.c
@@ -49,6 +49,7 @@ enum bt_sco_state {
BT_SCO_STATE_IDLE,
BT_SCO_STATE_RUNNING,
BT_SCO_STATE_ENDING,
+ BT_SCO_STATE_LOOPBACK,
};
enum bt_sco_direct {
@@ -192,13 +193,13 @@ static const u8 table_msbc_silence[SCO_PACKET_180] = {
static void mtk_btcvsd_snd_irq_enable(struct mtk_btcvsd_snd *bt)
{
regmap_update_bits(bt->infra, bt->infra_misc_offset,
- bt->conn_bt_cvsd_mask, bt->conn_bt_cvsd_mask);
+ bt->conn_bt_cvsd_mask, 0);
}
static void mtk_btcvsd_snd_irq_disable(struct mtk_btcvsd_snd *bt)
{
regmap_update_bits(bt->infra, bt->infra_misc_offset,
- bt->conn_bt_cvsd_mask, 0);
+ bt->conn_bt_cvsd_mask, bt->conn_bt_cvsd_mask);
}
static void mtk_btcvsd_snd_set_state(struct mtk_btcvsd_snd *bt,
@@ -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 &&
bt->rx->state != BT_SCO_STATE_ENDING &&
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",
__func__, bt->rx->state, bt->tx->state);
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_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 ||
bt->rx->state == BT_SCO_STATE_ENDING) {
if (bt->rx->xrun) {
@@ -1067,6 +1105,33 @@ static int btcvsd_band_set(struct snd_kcontrol *kcontrol,
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,
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[] = {
SOC_ENUM_EXT("BTCVSD Band", btcvsd_enum[0],
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,
btcvsd_tx_mute_get, btcvsd_tx_mute_set),
SOC_SINGLE_BOOL_EXT("BTCVSD Tx Irq Received Switch", 0,
OpenPOWER on IntegriCloud