123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
- */
- #include <linux/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;
- uint32_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, IFD);
- if (ret < 0)
- BTFMSLIM_ERR("failed to read (%d) reg 0x%x", ret, reg);
- BTFMSLIM_DBG("Major Rev: 0x%x, Minor Rev: 0x%x",
- (ret & 0xF0) >> 4, (ret & 0x0F));
- /* Get SB_SLAVE_HW_REV_LSB value*/
- reg = SLAVE_SB_SLAVE_HW_REV_LSB;
- ret = btfm_slim_read(btfmslim, reg, IFD);
- if (ret < 0)
- BTFMSLIM_ERR("failed to read (%d) reg 0x%x", ret, reg);
- else {
- BTFMSLIM_INFO("read (%d) reg 0x%x", ret, reg);
- ret = 0;
- }
- 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;
- BTFMSLIM_DBG("port(%d) enable(%d)", port_num, enable);
- if (rxport) {
- BTFMSLIM_DBG("sample rate is %d", btfmslim->sample_rate);
- if (enable &&
- btfmslim->sample_rate != 44100 &&
- btfmslim->sample_rate != 88200) {
- BTFMSLIM_DBG("setting multichannel bit");
- /* 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);
- }
- BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
- reg_val, reg);
- ret = btfm_slim_write(btfmslim, reg, reg_val, IFD);
- if (ret < 0) {
- 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, reg_val, IFD);
- if (ret < 0) {
- 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, reg_val, IFD);
- if (ret < 0) {
- 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, reg_val, IFD);
- if (ret < 0) {
- 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, reg_val, IFD);
- if (ret < 0)
- BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
- error:
- return ret;
- }
|