diff options
Diffstat (limited to 'sound/soc/mediatek/common')
-rw-r--r-- | sound/soc/mediatek/common/mtk-afe-fe-dai.c | 51 | ||||
-rw-r--r-- | sound/soc/mediatek/common/mtk-btcvsd.c | 73 |
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, |