btfm_slim_slave.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/slimbus.h>
  7. #include "btfm_slim.h"
  8. #include "btfm_slim_slave.h"
  9. /* SLAVE (WCN3990/QCA6390) Port assignment */
  10. struct btfmslim_ch slave_rxport[] = {
  11. {.id = BTFM_BT_SCO_A2DP_SLIM_RX, .name = "SCO_A2P_Rx",
  12. .port = SLAVE_SB_PGD_PORT_RX_SCO},
  13. {.id = BTFM_BT_SPLIT_A2DP_SLIM_RX, .name = "A2P_Rx",
  14. .port = SLAVE_SB_PGD_PORT_RX_A2P},
  15. {.id = BTFM_SLIM_NUM_CODEC_DAIS, .name = "",
  16. .port = BTFM_SLIM_PGD_PORT_LAST},
  17. };
  18. struct btfmslim_ch slave_txport[] = {
  19. {.id = BTFM_BT_SCO_SLIM_TX, .name = "SCO_Tx",
  20. .port = SLAVE_SB_PGD_PORT_TX_SCO},
  21. {.id = BTFM_FM_SLIM_TX, .name = "FM_Tx1",
  22. .port = SLAVE_SB_PGD_PORT_TX1_FM},
  23. {.id = BTFM_FM_SLIM_TX, .name = "FM_Tx2",
  24. .port = SLAVE_SB_PGD_PORT_TX2_FM},
  25. {.id = BTFM_SLIM_NUM_CODEC_DAIS, .name = "",
  26. .port = BTFM_SLIM_PGD_PORT_LAST},
  27. };
  28. /* Function description */
  29. int btfm_slim_slave_hw_init(struct btfmslim *btfmslim)
  30. {
  31. int ret = 0;
  32. uint32_t reg;
  33. BTFMSLIM_DBG("");
  34. if (!btfmslim)
  35. return -EINVAL;
  36. /* Get SB_SLAVE_HW_REV_MSB value*/
  37. reg = SLAVE_SB_SLAVE_HW_REV_MSB;
  38. ret = btfm_slim_read(btfmslim, reg, IFD);
  39. if (ret < 0)
  40. BTFMSLIM_ERR("failed to read (%d) reg 0x%x", ret, reg);
  41. BTFMSLIM_DBG("Major Rev: 0x%x, Minor Rev: 0x%x",
  42. (ret & 0xF0) >> 4, (ret & 0x0F));
  43. /* Get SB_SLAVE_HW_REV_LSB value*/
  44. reg = SLAVE_SB_SLAVE_HW_REV_LSB;
  45. ret = btfm_slim_read(btfmslim, reg, IFD);
  46. if (ret < 0)
  47. BTFMSLIM_ERR("failed to read (%d) reg 0x%x", ret, reg);
  48. else {
  49. BTFMSLIM_INFO("read (%d) reg 0x%x", ret, reg);
  50. ret = 0;
  51. }
  52. return ret;
  53. }
  54. static inline int is_fm_port(uint8_t port_num)
  55. {
  56. if (port_num == SLAVE_SB_PGD_PORT_TX1_FM ||
  57. port_num == CHRKVER3_SB_PGD_PORT_TX1_FM ||
  58. port_num == CHRKVER3_SB_PGD_PORT_TX2_FM ||
  59. port_num == SLAVE_SB_PGD_PORT_TX2_FM)
  60. return 1;
  61. else
  62. return 0;
  63. }
  64. int btfm_slim_slave_enable_port(struct btfmslim *btfmslim, uint8_t port_num,
  65. uint8_t rxport, uint8_t enable)
  66. {
  67. int ret = 0;
  68. uint8_t reg_val = 0, en;
  69. uint8_t rxport_num = 0;
  70. uint16_t reg;
  71. BTFMSLIM_DBG("port(%d) enable(%d)", port_num, enable);
  72. if (rxport) {
  73. BTFMSLIM_DBG("sample rate is %d", btfmslim->sample_rate);
  74. if (enable &&
  75. btfmslim->sample_rate != 44100 &&
  76. btfmslim->sample_rate != 88200) {
  77. BTFMSLIM_DBG("setting multichannel bit");
  78. /* For SCO Rx, A2DP Rx other than 44.1 and 88.2Khz */
  79. if (port_num < 24) {
  80. rxport_num = port_num - 16;
  81. reg_val = 0x01 << rxport_num;
  82. reg = SLAVE_SB_PGD_RX_PORTn_MULTI_CHNL_0(
  83. rxport_num);
  84. } else {
  85. rxport_num = port_num - 24;
  86. reg_val = 0x01 << rxport_num;
  87. reg = SLAVE_SB_PGD_RX_PORTn_MULTI_CHNL_1(
  88. rxport_num);
  89. }
  90. BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
  91. reg_val, reg);
  92. ret = btfm_slim_write(btfmslim, reg, reg_val, IFD);
  93. if (ret < 0) {
  94. BTFMSLIM_ERR("failed to write (%d) reg 0x%x",
  95. ret, reg);
  96. goto error;
  97. }
  98. }
  99. /* Port enable */
  100. reg = SLAVE_SB_PGD_PORT_RX_CFGN(port_num - 0x10);
  101. goto enable_disable_rxport;
  102. }
  103. if (!enable)
  104. goto enable_disable_txport;
  105. /* txport */
  106. /* Multiple Channel Setting */
  107. if (is_fm_port(port_num)) {
  108. if (port_num == CHRKVER3_SB_PGD_PORT_TX1_FM)
  109. reg_val = (0x1 << CHRKVER3_SB_PGD_PORT_TX1_FM);
  110. else if (port_num == CHRKVER3_SB_PGD_PORT_TX2_FM)
  111. reg_val = (0x1 << CHRKVER3_SB_PGD_PORT_TX2_FM);
  112. else
  113. reg_val = (0x1 << SLAVE_SB_PGD_PORT_TX1_FM) |
  114. (0x1 << SLAVE_SB_PGD_PORT_TX2_FM);
  115. reg = SLAVE_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num);
  116. BTFMSLIM_INFO("writing reg_val (%d) to reg(%x)", reg_val, reg);
  117. ret = btfm_slim_write(btfmslim, reg, reg_val, IFD);
  118. if (ret < 0) {
  119. BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
  120. goto error;
  121. }
  122. } else if (port_num == SLAVE_SB_PGD_PORT_TX_SCO) {
  123. /* SCO Tx */
  124. reg_val = 0x1 << SLAVE_SB_PGD_PORT_TX_SCO;
  125. reg = SLAVE_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num);
  126. BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
  127. reg_val, reg);
  128. ret = btfm_slim_write(btfmslim, reg, reg_val, IFD);
  129. if (ret < 0) {
  130. BTFMSLIM_ERR("failed to write (%d) reg 0x%x",
  131. ret, reg);
  132. goto error;
  133. }
  134. }
  135. /* Enable Tx port hw auto recovery for underrun or overrun error */
  136. reg_val = (SLAVE_ENABLE_OVERRUN_AUTO_RECOVERY |
  137. SLAVE_ENABLE_UNDERRUN_AUTO_RECOVERY);
  138. reg = SLAVE_SB_PGD_PORT_TX_OR_UR_CFGN(port_num);
  139. ret = btfm_slim_write(btfmslim, reg, reg_val, IFD);
  140. if (ret < 0) {
  141. BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
  142. goto error;
  143. }
  144. enable_disable_txport:
  145. /* Port enable */
  146. reg = SLAVE_SB_PGD_PORT_TX_CFGN(port_num);
  147. enable_disable_rxport:
  148. if (enable)
  149. en = SLAVE_SB_PGD_PORT_ENABLE;
  150. else
  151. en = SLAVE_SB_PGD_PORT_DISABLE;
  152. if (is_fm_port(port_num))
  153. reg_val = en | SLAVE_SB_PGD_PORT_WM_L8;
  154. else if (port_num == SLAVE_SB_PGD_PORT_TX_SCO)
  155. reg_val = enable ? en | SLAVE_SB_PGD_PORT_WM_L1 : en;
  156. else
  157. reg_val = enable ? en | SLAVE_SB_PGD_PORT_WM_LB : en;
  158. if (enable && port_num == SLAVE_SB_PGD_PORT_TX_SCO)
  159. BTFMSLIM_INFO("programming SCO Tx with reg_val %d to reg 0x%x",
  160. reg_val, reg);
  161. ret = btfm_slim_write(btfmslim, reg, reg_val, IFD);
  162. if (ret < 0)
  163. BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
  164. error:
  165. return ret;
  166. }