ce3ab0ecae
When opening port for 44.1/88.2KHz A2DP Rx, explicitly unset multi channel bit. This is required because for SCO/A2DP with other sample rates, we set the multi channel bit. The bit remains set even after the channel is removed and until we expliciltly unset again. Change-Id: I76d7a46b107baf811657b7ade307a7dd60a21c4a Signed-off-by: gaoxiang <quic_gaoxiang@quicinc.com>
202 lines
5.5 KiB
C
202 lines
5.5 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
|
*/
|
|
|
|
#include <linux/slimbus/slimbus.h>
|
|
#include "btfm_slim.h"
|
|
#include "btfm_slim_slave.h"
|
|
|
|
/* SLAVE (WCN3990/QCA6390) Port assignment */
|
|
struct btfmslim_ch slave_rxport[] = {
|
|
{.id = BTFM_BT_SCO_A2DP_SLIM_RX, .name = "SCO_A2P_Rx",
|
|
.port = SLAVE_SB_PGD_PORT_RX_SCO},
|
|
{.id = BTFM_BT_SPLIT_A2DP_SLIM_RX, .name = "A2P_Rx",
|
|
.port = SLAVE_SB_PGD_PORT_RX_A2P},
|
|
{.id = BTFM_SLIM_NUM_CODEC_DAIS, .name = "",
|
|
.port = BTFM_SLIM_PGD_PORT_LAST},
|
|
};
|
|
|
|
struct btfmslim_ch slave_txport[] = {
|
|
{.id = BTFM_BT_SCO_SLIM_TX, .name = "SCO_Tx",
|
|
.port = SLAVE_SB_PGD_PORT_TX_SCO},
|
|
{.id = BTFM_FM_SLIM_TX, .name = "FM_Tx1",
|
|
.port = SLAVE_SB_PGD_PORT_TX1_FM},
|
|
{.id = BTFM_FM_SLIM_TX, .name = "FM_Tx2",
|
|
.port = SLAVE_SB_PGD_PORT_TX2_FM},
|
|
{.id = BTFM_SLIM_NUM_CODEC_DAIS, .name = "",
|
|
.port = BTFM_SLIM_PGD_PORT_LAST},
|
|
};
|
|
|
|
/* Function description */
|
|
int btfm_slim_slave_hw_init(struct btfmslim *btfmslim)
|
|
{
|
|
int ret = 0;
|
|
uint8_t reg_val;
|
|
uint16_t reg;
|
|
|
|
BTFMSLIM_DBG("");
|
|
|
|
if (!btfmslim)
|
|
return -EINVAL;
|
|
|
|
/* Get SB_SLAVE_HW_REV_MSB value*/
|
|
reg = SLAVE_SB_SLAVE_HW_REV_MSB;
|
|
ret = btfm_slim_read(btfmslim, reg, 1, ®_val, IFD);
|
|
if (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*/
|
|
reg = SLAVE_SB_SLAVE_HW_REV_LSB;
|
|
ret = btfm_slim_read(btfmslim, reg, 1, ®_val, IFD);
|
|
if (ret) {
|
|
BTFMSLIM_ERR("failed to read (%d) reg 0x%x", ret, reg);
|
|
goto error;
|
|
}
|
|
BTFMSLIM_DBG("Step Rev: 0x%x", reg_val);
|
|
|
|
error:
|
|
return ret;
|
|
}
|
|
|
|
static inline int is_fm_port(uint8_t port_num)
|
|
{
|
|
if (port_num == SLAVE_SB_PGD_PORT_TX1_FM ||
|
|
port_num == CHRKVER3_SB_PGD_PORT_TX1_FM ||
|
|
port_num == CHRKVER3_SB_PGD_PORT_TX2_FM ||
|
|
port_num == SLAVE_SB_PGD_PORT_TX2_FM)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int btfm_slim_slave_enable_port(struct btfmslim *btfmslim, uint8_t port_num,
|
|
uint8_t rxport, uint8_t enable)
|
|
{
|
|
int ret = 0;
|
|
uint8_t reg_val = 0, en;
|
|
uint8_t rxport_num = 0;
|
|
uint16_t reg;
|
|
uint8_t prev_reg_val = 0;
|
|
|
|
BTFMSLIM_DBG("port(%d) enable(%d)", port_num, enable);
|
|
if (rxport) {
|
|
BTFMSLIM_DBG("sample rate is %d", btfmslim->sample_rate);
|
|
if (enable) {
|
|
/* For SCO Rx, A2DP Rx other than 44.1 and 88.2Khz */
|
|
if (port_num < 24) {
|
|
rxport_num = port_num - 16;
|
|
reg_val = 0x01 << rxport_num;
|
|
reg = SLAVE_SB_PGD_RX_PORTn_MULTI_CHNL_0(
|
|
rxport_num);
|
|
} else {
|
|
rxport_num = port_num - 24;
|
|
reg_val = 0x01 << rxport_num;
|
|
reg = SLAVE_SB_PGD_RX_PORTn_MULTI_CHNL_1(
|
|
rxport_num);
|
|
}
|
|
|
|
if (btfmslim->sample_rate == 44100 ||
|
|
btfmslim->sample_rate == 88200) {
|
|
BTFMSLIM_DBG("unsetting multichannel bit");
|
|
ret = btfm_slim_read(btfmslim, reg, 1,
|
|
&prev_reg_val, IFD);
|
|
if (ret < 0) {
|
|
BTFMSLIM_ERR("error %d reading", ret);
|
|
prev_reg_val = 0;
|
|
}
|
|
BTFMSLIM_DBG("prev_reg_val (%d) from reg(%x)",
|
|
prev_reg_val, reg);
|
|
reg_val = prev_reg_val & ~reg_val;
|
|
} else
|
|
BTFMSLIM_DBG("setting multichannel bit");
|
|
|
|
BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
|
|
reg_val, reg);
|
|
ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD);
|
|
if (ret) {
|
|
BTFMSLIM_ERR("failed to write (%d) reg 0x%x",
|
|
ret, reg);
|
|
goto error;
|
|
}
|
|
}
|
|
/* Port enable */
|
|
reg = SLAVE_SB_PGD_PORT_RX_CFGN(port_num - 0x10);
|
|
goto enable_disable_rxport;
|
|
}
|
|
if (!enable)
|
|
goto enable_disable_txport;
|
|
|
|
/* txport */
|
|
/* Multiple Channel Setting */
|
|
if (is_fm_port(port_num)) {
|
|
if (port_num == CHRKVER3_SB_PGD_PORT_TX1_FM)
|
|
reg_val = (0x1 << CHRKVER3_SB_PGD_PORT_TX1_FM);
|
|
else if (port_num == CHRKVER3_SB_PGD_PORT_TX2_FM)
|
|
reg_val = (0x1 << CHRKVER3_SB_PGD_PORT_TX2_FM);
|
|
else
|
|
reg_val = (0x1 << SLAVE_SB_PGD_PORT_TX1_FM) |
|
|
(0x1 << SLAVE_SB_PGD_PORT_TX2_FM);
|
|
reg = SLAVE_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num);
|
|
BTFMSLIM_INFO("writing reg_val (%d) to reg(%x)", reg_val, reg);
|
|
ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD);
|
|
if (ret) {
|
|
BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
|
|
goto error;
|
|
}
|
|
} else if (port_num == SLAVE_SB_PGD_PORT_TX_SCO) {
|
|
/* SCO Tx */
|
|
reg_val = 0x1 << SLAVE_SB_PGD_PORT_TX_SCO;
|
|
reg = SLAVE_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num);
|
|
BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
|
|
reg_val, reg);
|
|
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 Tx port hw auto recovery for underrun or overrun error */
|
|
reg_val = (SLAVE_ENABLE_OVERRUN_AUTO_RECOVERY |
|
|
SLAVE_ENABLE_UNDERRUN_AUTO_RECOVERY);
|
|
reg = SLAVE_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 = SLAVE_SB_PGD_PORT_TX_CFGN(port_num);
|
|
|
|
enable_disable_rxport:
|
|
if (enable)
|
|
en = SLAVE_SB_PGD_PORT_ENABLE;
|
|
else
|
|
en = SLAVE_SB_PGD_PORT_DISABLE;
|
|
|
|
if (is_fm_port(port_num))
|
|
reg_val = en | SLAVE_SB_PGD_PORT_WM_L8;
|
|
else if (port_num == SLAVE_SB_PGD_PORT_TX_SCO)
|
|
reg_val = enable ? en | SLAVE_SB_PGD_PORT_WM_L1 : en;
|
|
else
|
|
reg_val = enable ? en | SLAVE_SB_PGD_PORT_WM_LB : en;
|
|
|
|
if (enable && port_num == SLAVE_SB_PGD_PORT_TX_SCO)
|
|
BTFMSLIM_INFO("programming SCO Tx with reg_val %d to reg 0x%x",
|
|
reg_val, reg);
|
|
|
|
ret = btfm_slim_write(btfmslim, reg, 1, ®_val, IFD);
|
|
if (ret)
|
|
BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
|
|
|
|
error:
|
|
return ret;
|
|
}
|