btfm_codec_interface.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/remoteproc.h>
  7. #include <linux/remoteproc/qcom_rproc.h>
  8. #include "btfm_codec.h"
  9. #include "btfm_codec_interface.h"
  10. #include "btfm_codec_pkt.h"
  11. #include "btfm_codec_btadv_interface.h"
  12. static struct snd_soc_dai_driver *btfmcodec_dai_info;
  13. uint32_t bits_per_second;
  14. static int btfm_codec_get_mixer_control(struct snd_kcontrol *kcontrol,
  15. struct snd_ctl_elem_value *ucontrol)
  16. {
  17. struct snd_soc_component *codec = kcontrol->private_data;
  18. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(codec);
  19. struct hwep_data *hwepinfo = btfmcodec->hwep_info;
  20. struct snd_kcontrol_new *mixer_ctrl = hwepinfo->mixer_ctrl;
  21. struct snd_ctl_elem_id id = kcontrol->id;
  22. int num_mixer_ctrl = hwepinfo->num_mixer_ctrl;
  23. int i = 0;
  24. BTFMCODEC_DBG("");
  25. for (; i < num_mixer_ctrl ; i++) {
  26. BTFMCODEC_DBG("checking mixer_ctrl:%s and current mixer:%s",
  27. id.name, mixer_ctrl[i].name);
  28. if (!strncmp(id.name, mixer_ctrl[i].name, 64)) {
  29. BTFMCODEC_DBG("Matched");
  30. mixer_ctrl[i].get(kcontrol, ucontrol);
  31. break;
  32. }
  33. }
  34. if (num_mixer_ctrl == i)
  35. return 0;
  36. return 1;
  37. }
  38. static int btfmcodec_put_mixer_control(struct snd_kcontrol *kcontrol,
  39. struct snd_ctl_elem_value *ucontrol)
  40. {
  41. struct snd_soc_component *codec = kcontrol->private_data;
  42. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(codec);
  43. struct hwep_data *hwepinfo = btfmcodec->hwep_info;
  44. struct snd_kcontrol_new *mixer_ctrl = hwepinfo->mixer_ctrl;
  45. struct snd_ctl_elem_id id = kcontrol->id;
  46. int num_mixer_ctrl = hwepinfo->num_mixer_ctrl;
  47. int i = 0;
  48. BTFMCODEC_DBG("");
  49. for (; i < num_mixer_ctrl ; i++) {
  50. BTFMCODEC_DBG("checking mixer_ctrl:%s and current mixer:%s",
  51. id.name, mixer_ctrl[i].name);
  52. if (!strncmp(id.name, mixer_ctrl[i].name, 64)) {
  53. BTFMCODEC_DBG("Matched");
  54. mixer_ctrl[i].put(kcontrol, ucontrol);
  55. break;
  56. }
  57. }
  58. if (num_mixer_ctrl == i)
  59. return 0;
  60. return 1;
  61. }
  62. static int btfmcodec_codec_probe(struct snd_soc_component *codec)
  63. {
  64. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(codec);
  65. struct btfmcodec_state_machine *state = &btfmcodec->states;
  66. struct hwep_data *hwep_info = btfmcodec->hwep_info;
  67. int num_mixer_ctrl = hwep_info->num_mixer_ctrl;
  68. BTFMCODEC_DBG("");
  69. // ToDo: check weather probe has to allowed when state if different
  70. if (btfmcodec_get_current_transport(state)!= IDLE) {
  71. BTFMCODEC_WARN("Received probe when state is :%s",
  72. coverttostring(btfmcodec_get_current_transport(state)));
  73. } else if (hwep_info->drv && hwep_info->drv->hwep_probe) {
  74. hwep_info->drv->hwep_probe(codec);
  75. /* Register mixer control */
  76. if (hwep_info->mixer_ctrl && num_mixer_ctrl >= 1) {
  77. struct snd_kcontrol_new *mixer_ctrl;
  78. int i = 0;
  79. mixer_ctrl = (struct snd_kcontrol_new *)
  80. kzalloc(num_mixer_ctrl *
  81. sizeof(struct snd_kcontrol_new), GFP_KERNEL);
  82. if (!mixer_ctrl) {
  83. BTFMCODEC_ERR("failed to register mixer controls");
  84. goto end;
  85. }
  86. BTFMCODEC_INFO("Registering %d mixer controls", num_mixer_ctrl);
  87. memcpy(mixer_ctrl, hwep_info->mixer_ctrl, num_mixer_ctrl * sizeof(struct snd_kcontrol_new));
  88. for (; i< num_mixer_ctrl; i++) {
  89. BTFMCODEC_INFO("name of control:%s", mixer_ctrl[i].name);
  90. mixer_ctrl[i].get = btfm_codec_get_mixer_control;
  91. mixer_ctrl[i].put = btfmcodec_put_mixer_control;
  92. }
  93. snd_soc_add_component_controls(codec, mixer_ctrl, num_mixer_ctrl);
  94. BTFMCODEC_INFO("CODEC address while registering mixer ctrl:%p", codec);
  95. }
  96. }
  97. end:
  98. // ToDo to add mixer control.
  99. return 0;
  100. }
  101. static void btfmcodec_codec_remove(struct snd_soc_component *codec)
  102. {
  103. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(codec);
  104. struct btfmcodec_state_machine *state = &btfmcodec->states;
  105. struct hwep_data *hwep_info = btfmcodec->hwep_info;
  106. BTFMCODEC_DBG("");
  107. // ToDo: check whether remove has to allowed when state if different
  108. if (btfmcodec_get_current_transport(state)!= IDLE) {
  109. BTFMCODEC_WARN("Received probe when state is :%s",
  110. coverttostring(btfmcodec_get_current_transport(state)));
  111. } else if (hwep_info->drv && hwep_info->drv->hwep_remove) {
  112. hwep_info->drv->hwep_remove(codec);
  113. }
  114. }
  115. static int btfmcodec_codec_write(struct snd_soc_component *codec,
  116. unsigned int reg, unsigned int value)
  117. {
  118. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(codec);
  119. struct btfmcodec_state_machine *state = &btfmcodec->states;
  120. struct hwep_data *hwep_info = btfmcodec->hwep_info;
  121. BTFMCODEC_DBG("");
  122. // ToDo: check whether write has to allowed when state if different
  123. if (btfmcodec_get_current_transport(state)!= IDLE) {
  124. BTFMCODEC_WARN("Received probe when state is :%s",
  125. coverttostring(btfmcodec_get_current_transport(state)));
  126. } else if (hwep_info->drv && hwep_info->drv->hwep_remove) {
  127. return hwep_info->drv->hwep_write(codec, reg, value);
  128. }
  129. return 0;
  130. }
  131. static unsigned int btfmcodec_codec_read(struct snd_soc_component *codec,
  132. unsigned int reg)
  133. {
  134. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(codec);
  135. struct btfmcodec_state_machine *state = &btfmcodec->states;
  136. struct hwep_data *hwep_info = btfmcodec->hwep_info;
  137. BTFMCODEC_DBG("");
  138. // ToDo: check whether read has to allowed when state if different
  139. if (btfmcodec_get_current_transport(state)!= IDLE) {
  140. BTFMCODEC_WARN("Received probe when state is :%s",
  141. coverttostring(btfmcodec_get_current_transport(state)));
  142. } else if (hwep_info->drv && hwep_info->drv->hwep_read) {
  143. return hwep_info->drv->hwep_read(codec, reg);
  144. }
  145. return 0;
  146. }
  147. static const struct snd_soc_component_driver btfmcodec_codec_component = {
  148. .probe = btfmcodec_codec_probe,
  149. .remove = btfmcodec_codec_remove,
  150. .read = btfmcodec_codec_read,
  151. .write = btfmcodec_codec_write,
  152. };
  153. static inline void * btfmcodec_get_dai_drvdata(struct hwep_data *hwep_info)
  154. {
  155. if (!hwep_info || !hwep_info->dai_drv) return NULL;
  156. return hwep_info->dai_drv;
  157. }
  158. int btfmcodec_hwep_startup(struct btfmcodec_data *btfmcodec)
  159. {
  160. struct hwep_data *hwep_info = btfmcodec->hwep_info;
  161. struct hwep_dai_driver *dai_drv = (struct hwep_dai_driver *)
  162. btfmcodec_get_dai_drvdata(hwep_info);
  163. if (dai_drv && dai_drv->dai_ops && dai_drv->dai_ops->hwep_startup) {
  164. return dai_drv->dai_ops->hwep_startup((void *)btfmcodec->hwep_info);
  165. } else {
  166. return -1;
  167. }
  168. }
  169. static int btfmcodec_dai_startup(struct snd_pcm_substream *substream,
  170. struct snd_soc_dai *dai)
  171. {
  172. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(dai->component);
  173. struct btfmcodec_state_machine *state = &btfmcodec->states;
  174. BTFMCODEC_DBG("substream = %s stream = %d dai->name = %s",
  175. substream->name, substream->stream, dai->name);
  176. if (btfmcodec_get_current_transport(state) != IDLE &&
  177. btfmcodec_get_current_transport(state) != BT_Connected) {
  178. BTFMCODEC_DBG("Not allowing as state is:%s",
  179. coverttostring(btfmcodec_get_current_transport(state)));
  180. } else {
  181. return btfmcodec_hwep_startup(btfmcodec);
  182. }
  183. return 0;
  184. }
  185. int btfmcodec_hwep_shutdown(struct btfmcodec_data *btfmcodec, int id,
  186. bool disable_master)
  187. {
  188. struct hwep_data *hwep_info = btfmcodec->hwep_info;
  189. struct btfmcodec_char_device *btfmcodec_dev = btfmcodec->btfmcodec_dev;
  190. struct hwep_dai_driver *dai_drv = (struct hwep_dai_driver *)
  191. btfmcodec_get_dai_drvdata(hwep_info);
  192. struct btfmcodec_state_machine *state = &btfmcodec->states;
  193. struct btm_master_shutdown_req shutdown_req;
  194. wait_queue_head_t *rsp_wait_q =
  195. &btfmcodec_dev->rsp_wait_q[BTM_PKT_TYPE_MASTER_SHUTDOWN_RSP];
  196. uint8_t *status = &btfmcodec_dev->status[BTM_PKT_TYPE_MASTER_SHUTDOWN_RSP];
  197. int ret = 0;
  198. /* for master configurations failure cases, we don't need to send
  199. * shutdown request
  200. */
  201. if (btfmcodec_get_current_transport(state) == BT_Connected && disable_master) {
  202. BTFMCODEC_DBG("sending master shutdown request..");
  203. shutdown_req.opcode = BTM_BTFMCODEC_MASTER_SHUTDOWN_REQ;
  204. shutdown_req.len = BTM_MASTER_SHUTDOWN_REQ_LEN;
  205. shutdown_req.stream_id = id;
  206. /* See if we need to protect below with lock */
  207. *status = BTM_WAITING_RSP;
  208. btfmcodec_dev_enqueue_pkt(btfmcodec_dev, &shutdown_req, (shutdown_req.len +
  209. BTM_HEADER_LEN));
  210. ret = wait_event_interruptible_timeout(*rsp_wait_q,
  211. (*status) != BTM_WAITING_RSP,
  212. msecs_to_jiffies(BTM_MASTER_CONFIG_RSP_TIMEOUT));
  213. if (ret == 0) {
  214. BTFMCODEC_ERR("failed to recevie response from BTADV audio Manager");
  215. } else {
  216. if (*status == BTM_RSP_RECV)
  217. ret = 0;
  218. else if (*status == BTM_FAIL_RESP_RECV ||
  219. *status == BTM_RSP_NOT_RECV_CLIENT_KILLED)
  220. ret = -1;
  221. }
  222. } else {
  223. if (!disable_master)
  224. BTFMCODEC_WARN("Not sending master shutdown request as graph might have closed");
  225. else
  226. BTFMCODEC_WARN("Not sending master shutdown request as state is:%s",
  227. coverttostring(btfmcodec_get_current_transport(state)));
  228. }
  229. if (dai_drv && dai_drv->dai_ops && dai_drv->dai_ops->hwep_shutdown) {
  230. dai_drv->dai_ops->hwep_shutdown((void *)btfmcodec->hwep_info, id);
  231. }
  232. return ret;
  233. }
  234. void btfmcodec_wq_hwep_shutdown(struct work_struct *work)
  235. {
  236. struct btfmcodec_char_device *btfmcodec_dev = container_of(work,
  237. struct btfmcodec_char_device,
  238. wq_hwep_shutdown);
  239. struct btfmcodec_data *btfmcodec = (struct btfmcodec_data *)btfmcodec_dev->btfmcodec;
  240. struct list_head *head = &btfmcodec->config_head;
  241. struct hwep_configurations *hwep_configs = NULL;
  242. int ret = -1;
  243. int idx = BTM_PKT_TYPE_HWEP_SHUTDOWN;
  244. BTFMCODEC_INFO(" starting shutdown");
  245. /* Just check if first Rx has to be closed first or
  246. * any order should be ok.
  247. */
  248. list_for_each_entry(hwep_configs, head, dai_list) {
  249. BTFMCODEC_INFO("shuting down dai id:%d", hwep_configs->stream_id);
  250. ret = btfmcodec_hwep_shutdown(btfmcodec, hwep_configs->stream_id, true);
  251. if (ret < 0) {
  252. BTFMCODEC_ERR("failed to shutdown master with id", hwep_configs->stream_id);
  253. break;
  254. }
  255. }
  256. if (ret < 0)
  257. btfmcodec_dev->status[idx] = BTM_FAIL_RESP_RECV;
  258. else
  259. btfmcodec_dev->status[idx] = BTM_RSP_RECV;
  260. wake_up_interruptible(&btfmcodec_dev->rsp_wait_q[idx]);
  261. }
  262. static int btfmcodec_delete_configs(struct btfmcodec_data *btfmcodec, uint8_t id)
  263. {
  264. struct list_head *head = &btfmcodec->config_head;
  265. struct hwep_configurations *hwep_configs;
  266. int ret = -1;
  267. list_for_each_entry(hwep_configs, head, dai_list) {
  268. if (hwep_configs->stream_id == id) {
  269. BTFMCODEC_INFO("deleting configs with id %d", id);
  270. list_del(&hwep_configs->dai_list);
  271. ret = 1;
  272. break;
  273. }
  274. }
  275. return ret;
  276. }
  277. static void btfmcodec_dai_shutdown(struct snd_pcm_substream *substream,
  278. struct snd_soc_dai *dai)
  279. {
  280. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(dai->component);
  281. struct btfmcodec_state_machine *state = &btfmcodec->states;
  282. BTFMCODEC_DBG("dai->name: %s, dai->id: %d, dai->rate: %d", dai->name,
  283. dai->id, dai->rate);
  284. if (btfmcodec_get_current_transport(state) != IDLE &&
  285. btfmcodec_get_current_transport(state) != BT_Connected) {
  286. BTFMCODEC_WARN("not allowing shutdown as state is:%s",
  287. coverttostring(btfmcodec_get_current_transport(state)));
  288. /* Delete stored configs */
  289. btfmcodec_delete_configs(btfmcodec, dai->id);
  290. } else {
  291. /* first master shutdown has to done */
  292. btfmcodec_hwep_shutdown(btfmcodec, dai->id, false);
  293. btfmcodec_delete_configs(btfmcodec, dai->id);
  294. if (!btfmcodec_is_valid_cache_avb(btfmcodec))
  295. btfmcodec_set_current_state(state, IDLE);
  296. else {
  297. BTFMCODEC_WARN("valid stream id is available not updating state\n");
  298. btfmcodec_set_current_state(state, BT_Connected);
  299. }
  300. }
  301. }
  302. int btfmcodec_hwep_hw_params (struct btfmcodec_data *btfmcodec, uint32_t bps,
  303. uint32_t direction)
  304. {
  305. struct hwep_data *hwep_info = btfmcodec->hwep_info;
  306. struct hwep_dai_driver *dai_drv = (struct hwep_dai_driver *)
  307. btfmcodec_get_dai_drvdata(hwep_info);
  308. if (dai_drv && dai_drv->dai_ops && dai_drv->dai_ops->hwep_hw_params) {
  309. return dai_drv->dai_ops->hwep_hw_params((void *)btfmcodec->hwep_info,
  310. bps, direction);
  311. } else {
  312. return -1;
  313. }
  314. }
  315. static int btfmcodec_dai_hw_params(struct snd_pcm_substream *substream,
  316. struct snd_pcm_hw_params *params,
  317. struct snd_soc_dai *dai)
  318. {
  319. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(dai->component);
  320. struct btfmcodec_state_machine *state = &btfmcodec->states;
  321. uint32_t bps = params_width(params);
  322. uint32_t direction = substream->stream;
  323. BTFMCODEC_DBG("dai->name = %s DAI-ID %x rate %d bps %d num_ch %d",
  324. dai->name, dai->id, params_rate(params), params_width(params),
  325. params_channels(params));
  326. if (btfmcodec_get_current_transport(state) != IDLE &&
  327. btfmcodec_get_current_transport(state) != BT_Connected) {
  328. BTFMCODEC_WARN("caching bps as state is :%s",
  329. coverttostring(btfmcodec_get_current_transport(state)));
  330. bits_per_second = bps;
  331. } else {
  332. return btfmcodec_hwep_hw_params(btfmcodec, bps, direction);
  333. }
  334. return 0;
  335. }
  336. bool btfmcodec_is_valid_cache_avb(struct btfmcodec_data *btfmcodec)
  337. {
  338. struct list_head *head = &btfmcodec->config_head;
  339. struct hwep_configurations *hwep_configs;
  340. bool cache_avb = false;
  341. list_for_each_entry(hwep_configs, head, dai_list) {
  342. cache_avb = true;
  343. break;
  344. }
  345. return cache_avb;
  346. }
  347. static int btfmcodec_check_and_cache_configs(struct btfmcodec_data *btfmcodec,
  348. uint32_t sampling_rate, uint32_t direction,
  349. int id, uint8_t codectype)
  350. {
  351. struct list_head *head = &btfmcodec->config_head;
  352. struct hwep_configurations *hwep_configs;
  353. list_for_each_entry(hwep_configs, head, dai_list) {
  354. if (hwep_configs->stream_id == id) {
  355. BTFMCODEC_WARN("previous entry for %d is already available",
  356. id);
  357. list_del(&hwep_configs->dai_list);
  358. }
  359. }
  360. hwep_configs = kzalloc(sizeof(struct hwep_configurations),
  361. GFP_KERNEL);
  362. if (!hwep_configs) {
  363. BTFMCODEC_ERR("failed to allocate memory");
  364. return -ENOMEM;
  365. }
  366. hwep_configs->stream_id = id; /* Stream identifier */
  367. hwep_configs->sample_rate = sampling_rate;
  368. hwep_configs->bit_width = bits_per_second;
  369. hwep_configs->codectype = codectype;
  370. hwep_configs->direction = direction;
  371. list_add(&hwep_configs->dai_list, head);
  372. BTFMCODEC_INFO("added dai id:%d to list with sampling_rate :%u, direction:%u", id, sampling_rate, direction);
  373. return 1;
  374. }
  375. static int btfmcodec_configure_master(struct btfmcodec_data *btfmcodec, uint8_t id)
  376. {
  377. struct btfmcodec_char_device *btfmcodec_dev = btfmcodec->btfmcodec_dev;
  378. struct hwep_data *hwep_info = btfmcodec->hwep_info;
  379. struct master_hwep_configurations hwep_configs;
  380. struct btm_master_config_req config_reg;
  381. struct hwep_dai_driver *dai_drv = (struct hwep_dai_driver *)
  382. btfmcodec_get_dai_drvdata(hwep_info);
  383. wait_queue_head_t *rsp_wait_q =
  384. &btfmcodec_dev->rsp_wait_q[BTM_PKT_TYPE_MASTER_CONFIG_RSP];
  385. uint8_t *status = &btfmcodec_dev->status[BTM_PKT_TYPE_MASTER_CONFIG_RSP];
  386. int ret = 0;
  387. if (dai_drv && dai_drv->dai_ops && dai_drv->dai_ops->hwep_get_configs) {
  388. dai_drv->dai_ops->hwep_get_configs((void *)btfmcodec->hwep_info,
  389. &hwep_configs, id);
  390. } else {
  391. BTFMCODEC_ERR("No hwep_get_configs is set by hw ep driver");
  392. return -1;
  393. }
  394. BTFMCODEC_INFO("framing packet for %d", id);
  395. config_reg.opcode = BTM_BTFMCODEC_MASTER_CONFIG_REQ;
  396. config_reg.len = BTM_MASTER_CONFIG_REQ_LEN;
  397. config_reg.stream_id = hwep_configs.stream_id;
  398. config_reg.device_id = hwep_configs.device_id;
  399. config_reg.sample_rate = hwep_configs.sample_rate;
  400. config_reg.bit_width = hwep_configs.bit_width;
  401. config_reg.num_channels = hwep_configs.num_channels;
  402. config_reg.channel_num = hwep_configs.chan_num;
  403. config_reg.codec_id = hwep_configs.codectype;
  404. BTFMCODEC_DBG("================================================\n");
  405. BTFMCODEC_DBG("config_reg.len :%d", config_reg.len);
  406. BTFMCODEC_DBG("config_reg.stream_id :%d", config_reg.stream_id);
  407. BTFMCODEC_DBG("config_reg.device_id :%d", config_reg.device_id);
  408. BTFMCODEC_DBG("config_reg.sample_rate :%d", config_reg.sample_rate);
  409. BTFMCODEC_DBG("config_reg.bit_width :%d", config_reg.bit_width);
  410. BTFMCODEC_DBG("config_reg.num_channels :%d", config_reg.num_channels);
  411. BTFMCODEC_DBG("config_reg.channel_num :%d", config_reg.channel_num);
  412. BTFMCODEC_DBG("config_reg.codec_id :%d", config_reg.codec_id);
  413. BTFMCODEC_DBG("================================================\n");
  414. /* See if we need to protect below with lock */
  415. *status = BTM_WAITING_RSP;
  416. btfmcodec_dev_enqueue_pkt(btfmcodec_dev, &config_reg, (config_reg.len +
  417. BTM_HEADER_LEN));
  418. ret = wait_event_interruptible_timeout(*rsp_wait_q,
  419. (*status) != BTM_WAITING_RSP,
  420. msecs_to_jiffies(BTM_MASTER_CONFIG_RSP_TIMEOUT));
  421. if (ret == 0) {
  422. BTFMCODEC_ERR("failed to recevie response from BTADV audio Manager");
  423. ret = -ETIMEDOUT;
  424. } else {
  425. if (*status == BTM_RSP_RECV)
  426. return 0;
  427. else if (*status == BTM_FAIL_RESP_RECV ||
  428. *status == BTM_RSP_NOT_RECV_CLIENT_KILLED)
  429. return -1;
  430. }
  431. return ret;
  432. }
  433. int btfmcodec_hwep_prepare(struct btfmcodec_data *btfmcodec, uint32_t sampling_rate,
  434. uint32_t direction, int id)
  435. {
  436. struct hwep_data *hwep_info = btfmcodec->hwep_info;
  437. struct hwep_dai_driver *dai_drv = (struct hwep_dai_driver *)
  438. btfmcodec_get_dai_drvdata(hwep_info);
  439. struct btfmcodec_state_machine *state = &btfmcodec->states;
  440. int ret;
  441. if (dai_drv && dai_drv->dai_ops && dai_drv->dai_ops->hwep_prepare) {
  442. ret = dai_drv->dai_ops->hwep_prepare((void *)hwep_info, sampling_rate,
  443. direction, id);
  444. if (ret == 0 && test_bit(BTADV_AUDIO_MASTER_CONFIG, &hwep_info->flags)) {
  445. ret = btfmcodec_configure_master(btfmcodec, (uint8_t)id);
  446. if (ret < 0) {
  447. BTFMCODEC_ERR("failed to configure master error %d", ret);
  448. /* close slave port and reset the state*/
  449. btfmcodec_set_current_state(state, IDLE);
  450. /* we don't need to do shutdown, ASOC is doing it */
  451. // btfmcodec_hwep_shutdown(btfmcodec, id);
  452. } else {
  453. btfmcodec_set_current_state(state, BT_Connected);
  454. }
  455. }
  456. } else {
  457. return -1;
  458. }
  459. return ret;
  460. }
  461. static int btfmcodec_dai_prepare(struct snd_pcm_substream *substream,
  462. struct snd_soc_dai *dai)
  463. {
  464. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(dai->component);
  465. struct btfmcodec_state_machine *state = &btfmcodec->states;
  466. struct hwep_data *hwep_info = btfmcodec->hwep_info;
  467. struct hwep_dai_driver *dai_drv = (struct hwep_dai_driver *)
  468. btfmcodec_get_dai_drvdata(hwep_info);
  469. uint8_t *codectype = dai_drv->dai_ops->hwep_codectype;
  470. uint32_t sampling_rate = dai->rate;
  471. uint32_t direction = substream->stream;
  472. int id = dai->id;
  473. int ret;
  474. BTFMCODEC_INFO("dai->name: %s, dai->id: %d, dai->rate: %d direction: %d",
  475. dai->name, id, sampling_rate, direction);
  476. if (btfmcodec_get_current_transport(state) != IDLE &&
  477. btfmcodec_get_current_transport(state) != BT_Connected) {
  478. BTFMCODEC_WARN("caching required info as state is:%s",
  479. coverttostring(btfmcodec_get_current_transport(state)));
  480. ret = btfmcodec_check_and_cache_configs(btfmcodec, sampling_rate, direction,
  481. id, *codectype);
  482. } else {
  483. ret = btfmcodec_hwep_prepare(btfmcodec, sampling_rate, direction, id);
  484. if (ret >= 0) {
  485. btfmcodec_check_and_cache_configs(btfmcodec, sampling_rate, direction,
  486. id, *codectype);
  487. }
  488. }
  489. return ret;
  490. }
  491. int btfmcodec_hwep_set_channel_map(void *hwep_info, unsigned int tx_num,
  492. unsigned int *tx_slot, unsigned int rx_num,
  493. unsigned int *rx_slot)
  494. {
  495. struct hwep_dai_driver *dai_drv = (struct hwep_dai_driver *)
  496. btfmcodec_get_dai_drvdata(hwep_info);
  497. if (dai_drv && dai_drv->dai_ops && dai_drv->dai_ops->hwep_set_channel_map) {
  498. return dai_drv->dai_ops->hwep_set_channel_map(hwep_info, tx_num,
  499. tx_slot, rx_num,
  500. rx_slot);
  501. } else {
  502. return -1;
  503. }
  504. }
  505. static int btfmcodec_dai_set_channel_map(struct snd_soc_dai *dai,
  506. unsigned int tx_num, unsigned int *tx_slot,
  507. unsigned int rx_num, unsigned int *rx_slot)
  508. {
  509. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(dai->component);
  510. struct btfmcodec_state_machine states = btfmcodec->states;
  511. BTFMCODEC_DBG("");
  512. // ToDo: check whether hw_params has to allowed when state if different
  513. if (states.current_state != IDLE) {
  514. BTFMCODEC_WARN("Received probe when state is :%s", coverttostring(states.current_state));
  515. } else {
  516. return btfmcodec_hwep_set_channel_map((void *)btfmcodec->hwep_info, tx_num,
  517. tx_slot, rx_num, rx_slot);
  518. }
  519. return 0;
  520. }
  521. int btfmcodec_hwep_get_channel_map(void *hwep_info, unsigned int *tx_num,
  522. unsigned int *tx_slot, unsigned int *rx_num,
  523. unsigned int *rx_slot, int id)
  524. {
  525. struct hwep_dai_driver *dai_drv = (struct hwep_dai_driver *)
  526. btfmcodec_get_dai_drvdata(hwep_info);
  527. if (dai_drv && dai_drv->dai_ops && dai_drv->dai_ops->hwep_get_channel_map) {
  528. return dai_drv->dai_ops->hwep_get_channel_map(hwep_info, tx_num,
  529. tx_slot, rx_num,
  530. rx_slot, id);
  531. } else {
  532. return -1;
  533. }
  534. }
  535. static int btfmcodec_dai_get_channel_map(struct snd_soc_dai *dai,
  536. unsigned int *tx_num, unsigned int *tx_slot,
  537. unsigned int *rx_num, unsigned int *rx_slot)
  538. {
  539. struct btfmcodec_data *btfmcodec = snd_soc_component_get_drvdata(dai->component);
  540. // struct btfmcodec_state_machine states = btfmcodec->states;
  541. BTFMCODEC_DBG("");
  542. // ToDo: get_channel_map is not needed for new driver
  543. /* if (states.current_state != IDLE) {
  544. BTFMCODEC_WARN("Received probe when state is :%s", coverttostring(states.current_state));
  545. } else {
  546. */ return btfmcodec_hwep_get_channel_map((void *)btfmcodec->hwep_info,
  547. tx_num, tx_slot, rx_num,
  548. rx_slot, dai->id);
  549. // }
  550. return 0;
  551. }
  552. void btfmcodec_wq_hwep_configure(struct work_struct *work)
  553. {
  554. struct btfmcodec_char_device *btfmcodec_dev = container_of(work,
  555. struct btfmcodec_char_device,
  556. wq_hwep_configure);
  557. struct btfmcodec_data *btfmcodec = (struct btfmcodec_data *)btfmcodec_dev->btfmcodec;
  558. struct list_head *head = &btfmcodec->config_head;
  559. struct hwep_configurations *hwep_configs = NULL;
  560. int ret;
  561. int idx = BTM_PKT_TYPE_HWEP_CONFIG;
  562. uint32_t sample_rate, direction;
  563. uint8_t id, bit_width, codectype;
  564. list_for_each_entry(hwep_configs, head, dai_list) {
  565. id = hwep_configs->stream_id;
  566. sample_rate = hwep_configs->sample_rate;
  567. bit_width = hwep_configs->bit_width;
  568. codectype = hwep_configs->codectype;
  569. direction = hwep_configs->direction;
  570. BTFMCODEC_INFO("configuring dai id:%d with sampling rate:%d bit_width:%d", id, sample_rate, bit_width);
  571. ret = btfmcodec_hwep_startup(btfmcodec);
  572. if (ret >= 0)
  573. ret = btfmcodec_hwep_hw_params(btfmcodec, bit_width, direction);
  574. if (ret >= 0)
  575. ret = btfmcodec_hwep_prepare(btfmcodec, sample_rate, direction, id);
  576. if (ret < 0) {
  577. BTFMCODEC_ERR("failed to configure hwep", hwep_configs->stream_id);
  578. break;
  579. }
  580. }
  581. if (ret < 0)
  582. btfmcodec_dev->status[idx] = BTM_FAIL_RESP_RECV;
  583. else
  584. btfmcodec_dev->status[idx] = BTM_RSP_RECV;
  585. wake_up_interruptible(&btfmcodec_dev->rsp_wait_q[idx]);
  586. }
  587. static struct snd_soc_dai_ops btfmcodec_dai_ops = {
  588. .startup = btfmcodec_dai_startup,
  589. .shutdown = btfmcodec_dai_shutdown,
  590. .hw_params = btfmcodec_dai_hw_params,
  591. .prepare = btfmcodec_dai_prepare,
  592. .set_channel_map = btfmcodec_dai_set_channel_map,
  593. .get_channel_map = btfmcodec_dai_get_channel_map,
  594. };
  595. static int btfmcodec_adsp_ssr_notify(struct notifier_block *nb,
  596. unsigned long action, void *data)
  597. {
  598. struct btfmcodec_data *btfmcodec = container_of(nb,
  599. struct btfmcodec_data, notifier.nb);
  600. struct btfmcodec_char_device *btfmcodec_dev = btfmcodec->btfmcodec_dev;
  601. struct btm_adsp_state_ind state_ind;
  602. switch (action) {
  603. case QCOM_SSR_BEFORE_SHUTDOWN: {
  604. BTFMCODEC_WARN("LPASS SSR triggered");
  605. break;
  606. } case QCOM_SSR_AFTER_SHUTDOWN: {
  607. BTFMCODEC_WARN("LPASS SSR Completed");
  608. break;
  609. } case QCOM_SSR_BEFORE_POWERUP: {
  610. BTFMCODEC_WARN("LPASS booted up after SSR");
  611. break;
  612. } case QCOM_SSR_AFTER_POWERUP: {
  613. BTFMCODEC_WARN("LPASS booted up completely");
  614. state_ind.opcode = BTM_BTFMCODEC_ADSP_STATE_IND;
  615. state_ind.len = BTM_ADSP_STATE_IND_LEN;
  616. state_ind.action = (uint32_t)action;
  617. btfmcodec_dev_enqueue_pkt(btfmcodec_dev, &state_ind,
  618. (state_ind.len +
  619. BTM_HEADER_LEN));
  620. break;
  621. } default:
  622. BTFMCODEC_WARN("unhandled action id %lu", action);
  623. break;
  624. }
  625. return 0;
  626. }
  627. int btfm_register_codec(struct hwep_data *hwep_info)
  628. {
  629. struct btfmcodec_data *btfmcodec;
  630. struct btfmcodec_char_device *btfmcodec_dev;
  631. struct device *dev;
  632. struct hwep_dai_driver *dai_drv;
  633. int i, ret;
  634. btfmcodec = btfm_get_btfmcodec();
  635. btfmcodec_dev = btfmcodec->btfmcodec_dev;
  636. dev = &btfmcodec->dev;
  637. btfmcodec->notifier.nb.notifier_call = btfmcodec_adsp_ssr_notify;
  638. btfmcodec->notifier.notifier = qcom_register_ssr_notifier("lpass",
  639. &btfmcodec->notifier.nb);
  640. if (IS_ERR(btfmcodec->notifier.notifier)) {
  641. ret = PTR_ERR(btfmcodec->notifier.notifier);
  642. BTFMCODEC_ERR("Failed to register SSR notification: %d\n", ret);
  643. return ret;
  644. }
  645. btfmcodec_dai_info = kzalloc((sizeof(struct snd_soc_dai_driver) * hwep_info->num_dai), GFP_KERNEL);
  646. if (!btfmcodec_dai_info) {
  647. BTFMCODEC_ERR("failed to allocate memory");
  648. return -ENOMEM;
  649. }
  650. for (i = 0; i < hwep_info->num_dai; i++) {
  651. dai_drv = &hwep_info->dai_drv[i];
  652. btfmcodec_dai_info[i].name = dai_drv->dai_name;
  653. btfmcodec_dai_info[i].id = dai_drv->id;
  654. btfmcodec_dai_info[i].capture = dai_drv->capture;
  655. btfmcodec_dai_info[i].playback = dai_drv->playback;
  656. btfmcodec_dai_info[i].ops = &btfmcodec_dai_ops;
  657. }
  658. BTFMCODEC_INFO("Adding %d dai support to codec", hwep_info->num_dai);
  659. BTFMCODEC_INFO("slim bus driver name:%s", dev->driver->name);
  660. ret = snd_soc_register_component(dev, &btfmcodec_codec_component,
  661. btfmcodec_dai_info, hwep_info->num_dai);
  662. BTFMCODEC_INFO("Dev node address: %p", dev);
  663. BTFMCODEC_INFO("btfmcodec address :%p, btfmcodec");
  664. BTFMCODEC_INFO("HWEPINFO address:%p", hwep_info);
  665. BTFMCODEC_INFO("btfmcodec_dev INFO address:%p", btfmcodec->btfmcodec_dev);
  666. BTFMCODEC_INFO("before wq_hwep_shutdown:%p", btfmcodec_dev->wq_hwep_shutdown);
  667. BTFMCODEC_INFO("before wq_prepare_bearer:%p", btfmcodec_dev->wq_prepare_bearer);
  668. INIT_WORK(&btfmcodec_dev->wq_hwep_shutdown, btfmcodec_wq_hwep_shutdown);
  669. INIT_WORK(&btfmcodec_dev->wq_prepare_bearer, btfmcodec_wq_prepare_bearer);
  670. INIT_WORK(&btfmcodec_dev->wq_hwep_configure, btfmcodec_wq_hwep_configure);
  671. BTFMCODEC_INFO("after wq_hwep_shutdown:%p", btfmcodec_dev->wq_hwep_shutdown);
  672. BTFMCODEC_INFO("after wq_prepare_bearer:%p", btfmcodec_dev->wq_prepare_bearer);
  673. BTFMCODEC_INFO("btfmcodec_wq_prepare_bearer:%p", btfmcodec_wq_prepare_bearer);
  674. BTFMCODEC_INFO("btfmcodec_wq_hwep_shutdown:%p", btfmcodec_wq_hwep_shutdown);
  675. return ret;
  676. }
  677. void btfm_unregister_codec(void)
  678. {
  679. struct btfmcodec_data *btfmcodec;
  680. btfmcodec = btfm_get_btfmcodec();
  681. snd_soc_unregister_component(&btfmcodec->dev);
  682. }