btfm_codec_interface.c 25 KB

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