btfm: Close 3990 FM tx ports first and keep overflow bit always set
Close data source ports i.e. wcn3990 tx ports before data sink ports i.e. AFE for FM tx case. Also, do not set wcn3990 overflow/underflow registers to 0 during channel disable path. This causes audio loss if audio focus is lost during FM playback. Change-Id: Id6c8ee145bf7feb8681851499ba36b708667b4ef Signed-off-by: Rupesh Tatiya <rtatiya@codeaurora.org>
This commit is contained in:
parent
f39a5999e2
commit
9a983b8062
2 changed files with 96 additions and 35 deletions
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue