diff --git a/drivers/bluetooth/btfm_slim_codec.c b/drivers/bluetooth/btfm_slim_codec.c index 061177173ab8..1ed366fd3d71 100644 --- a/drivers/bluetooth/btfm_slim_codec.c +++ b/drivers/bluetooth/btfm_slim_codec.c @@ -92,6 +92,9 @@ static void btfm_slim_dai_shutdown(struct snd_pcm_substream *substream, return; } + if (dai->id == BTFM_FM_SLIM_TX) + goto out; + /* Search for dai->id matched port handler */ for (i = 0; (i < BTFM_SLIM_NUM_CODEC_DAIS) && (ch->id != BTFM_SLIM_NUM_CODEC_DAIS) && @@ -105,6 +108,7 @@ static void btfm_slim_dai_shutdown(struct snd_pcm_substream *substream, } btfm_slim_disable_ch(btfmslim, ch, rxport, grp, nchan); +out: btfm_slim_hw_deinit(btfmslim); } @@ -167,6 +171,61 @@ int btfm_slim_dai_prepare(struct snd_pcm_substream *substream, return ret; } +static int btfm_slim_dai_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + int ret = -EINVAL, i; + struct btfmslim *btfmslim = dai->dev->platform_data; + struct btfmslim_ch *ch; + uint8_t rxport, grp = false, nchan = 1; + + BTFMSLIM_DBG("dai->name: %s, dai->id: %d, dai->rate: %d", dai->name, + dai->id, dai->rate); + + switch (dai->id) { + case BTFM_FM_SLIM_TX: + grp = true; nchan = 2; + ch = btfmslim->tx_chs; + rxport = 0; + break; + case BTFM_BT_SCO_SLIM_TX: + ch = btfmslim->tx_chs; + rxport = 0; + break; + case BTFM_BT_SCO_A2DP_SLIM_RX: + case BTFM_BT_SPLIT_A2DP_SLIM_RX: + ch = btfmslim->rx_chs; + rxport = 1; + break; + case BTFM_SLIM_NUM_CODEC_DAIS: + default: + BTFMSLIM_ERR("dai->id is invalid:%d", dai->id); + goto out; + } + + if (dai->id != BTFM_FM_SLIM_TX) { + ret = 0; + goto out; + } + + /* Search for dai->id matched port handler */ + for (i = 0; (i < BTFM_SLIM_NUM_CODEC_DAIS) && + (ch->id != BTFM_SLIM_NUM_CODEC_DAIS) && + (ch->id != dai->id); ch++, i++) + ; + + if ((ch->port == BTFM_SLIM_PGD_PORT_LAST) || + (ch->id == BTFM_SLIM_NUM_CODEC_DAIS)) { + BTFMSLIM_ERR("ch is invalid!!"); + goto out; + } + + btfm_slim_disable_ch(btfmslim, ch, rxport, grp, nchan); + +out: + return ret; +} + /* This function will be called once during boot up */ static int btfm_slim_dai_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_num, unsigned int *tx_slot, @@ -306,6 +365,7 @@ static struct snd_soc_dai_ops btfmslim_dai_ops = { .shutdown = btfm_slim_dai_shutdown, .hw_params = btfm_slim_dai_hw_params, .prepare = btfm_slim_dai_prepare, + .hw_free = btfm_slim_dai_hw_free, .set_channel_map = btfm_slim_dai_set_channel_map, .get_channel_map = btfm_slim_dai_get_channel_map, }; diff --git a/drivers/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c index 72e28da4bd3b..d61454ac6e84 100644 --- a/drivers/bluetooth/btfm_slim_wcn3990.c +++ b/drivers/bluetooth/btfm_slim_wcn3990.c @@ -39,6 +39,7 @@ int btfm_slim_chrk_hw_init(struct btfmslim *btfmslim) { int ret = 0; uint8_t reg_val; + uint16_t reg; BTFMSLIM_DBG(""); @@ -46,20 +47,20 @@ int btfm_slim_chrk_hw_init(struct btfmslim *btfmslim) return -EINVAL; /* Get SB_SLAVE_HW_REV_MSB value*/ - ret = btfm_slim_read(btfmslim, CHRK_SB_SLAVE_HW_REV_MSB, 1, - ®_val, IFD); + reg = CHRK_SB_SLAVE_HW_REV_MSB; + ret = btfm_slim_read(btfmslim, reg, 1, ®_val, IFD); if (ret) { - BTFMSLIM_ERR("failed to read (%d)", ret); + BTFMSLIM_ERR("failed to read (%d) reg 0x%x", ret, reg); goto error; } BTFMSLIM_DBG("Major Rev: 0x%x, Minor Rev: 0x%x", (reg_val & 0xF0) >> 4, (reg_val & 0x0F)); /* Get SB_SLAVE_HW_REV_LSB value*/ - ret = btfm_slim_read(btfmslim, CHRK_SB_SLAVE_HW_REV_LSB, 1, - ®_val, IFD); + reg = CHRK_SB_SLAVE_HW_REV_LSB; + ret = btfm_slim_read(btfmslim, reg, 1, ®_val, IFD); if (ret) { - BTFMSLIM_ERR("failed to read (%d)", ret); + BTFMSLIM_ERR("failed to read (%d) reg 0x%x", ret, reg); goto error; } BTFMSLIM_DBG("Step Rev: 0x%x", reg_val); @@ -80,41 +81,41 @@ int btfm_slim_chrk_enable_port(struct btfmslim *btfmslim, uint8_t port_num, if (rxport) { /* Port enable */ reg = CHRK_SB_PGD_PORT_RX_CFGN(port_num - 0x10); - } else { /* txport */ - /* Multiple Channel Setting - only FM Tx will be multiple - * channel - */ - if (enable && (port_num == CHRK_SB_PGD_PORT_TX1_FM || - port_num == CHRK_SB_PGD_PORT_TX2_FM)) { + goto enable_disable_rxport; + } + /* txport */ + if (!enable) + goto enable_disable_txport; - reg_val = (0x1 << CHRK_SB_PGD_PORT_TX1_FM) | + /* Multiple Channel Setting - only for FM Tx */ + if (port_num == CHRK_SB_PGD_PORT_TX1_FM || + port_num == CHRK_SB_PGD_PORT_TX2_FM) { + + reg_val = (0x1 << CHRK_SB_PGD_PORT_TX1_FM) | (0x1 << CHRK_SB_PGD_PORT_TX2_FM); - reg = CHRK_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num); - ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD); - if (ret) { - BTFMSLIM_ERR("failed to write (%d)", ret); - goto error; - } - } - - /* Enable Tx port hw auto recovery for underrun or - * overrun error - */ - reg_val = (enable) ? (CHRK_ENABLE_OVERRUN_AUTO_RECOVERY | - CHRK_ENABLE_UNDERRUN_AUTO_RECOVERY) : 0x0; - - ret = btfm_slim_write(btfmslim, - CHRK_SB_PGD_PORT_TX_OR_UR_CFGN(port_num), 1, - ®_val, IFD); + reg = CHRK_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num); + ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD); if (ret) { - BTFMSLIM_ERR("failed to write (%d)", ret); + BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg); goto error; } - - /* Port enable */ - reg = CHRK_SB_PGD_PORT_TX_CFGN(port_num); } + /* Enable Tx port hw auto recovery for underrun or overrun error */ + reg_val = (CHRK_ENABLE_OVERRUN_AUTO_RECOVERY | + CHRK_ENABLE_UNDERRUN_AUTO_RECOVERY); + reg = CHRK_SB_PGD_PORT_TX_OR_UR_CFGN(port_num); + ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD); + if (ret) { + BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg); + goto error; + } + +enable_disable_txport: + /* Port enable */ + reg = CHRK_SB_PGD_PORT_TX_CFGN(port_num); + +enable_disable_rxport: if (enable) /* Set water mark to 1 and enable the port */ reg_val = CHRK_SB_PGD_PORT_ENABLE | CHRK_SB_PGD_PORT_WM_LB; @@ -123,7 +124,7 @@ int btfm_slim_chrk_enable_port(struct btfmslim *btfmslim, uint8_t port_num, ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD); if (ret) - BTFMSLIM_ERR("failed to write (%d)", ret); + BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg); error: return ret;