sst_stream.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /*
  2. * sst_stream.c - Intel SST Driver for audio engine
  3. *
  4. * Copyright (C) 2008-14 Intel Corp
  5. * Authors: Vinod Koul <vinod.koul@intel.com>
  6. * Harsha Priya <priya.harsha@intel.com>
  7. * Dharageswari R <dharageswari.r@intel.com>
  8. * KP Jeeja <jeeja.kp@intel.com>
  9. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; version 2 of the License.
  14. *
  15. * This program is distributed in the hope that it will be useful, but
  16. * WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * General Public License for more details.
  19. *
  20. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  21. */
  22. #include <linux/pci.h>
  23. #include <linux/firmware.h>
  24. #include <linux/sched.h>
  25. #include <linux/delay.h>
  26. #include <linux/pm_runtime.h>
  27. #include <sound/core.h>
  28. #include <sound/pcm.h>
  29. #include <sound/soc.h>
  30. #include <sound/compress_driver.h>
  31. #include <asm/platform_sst_audio.h>
  32. #include "../sst-mfld-platform.h"
  33. #include "sst.h"
  34. #include "../../common/sst-dsp.h"
  35. int sst_alloc_stream_mrfld(struct intel_sst_drv *sst_drv_ctx, void *params)
  36. {
  37. struct snd_sst_alloc_mrfld alloc_param;
  38. struct snd_sst_params *str_params;
  39. struct snd_sst_tstamp fw_tstamp;
  40. struct stream_info *str_info;
  41. struct snd_sst_alloc_response *response;
  42. unsigned int str_id, pipe_id, task_id;
  43. int i, num_ch, ret = 0;
  44. void *data = NULL;
  45. dev_dbg(sst_drv_ctx->dev, "Enter\n");
  46. BUG_ON(!params);
  47. str_params = (struct snd_sst_params *)params;
  48. memset(&alloc_param, 0, sizeof(alloc_param));
  49. alloc_param.operation = str_params->ops;
  50. alloc_param.codec_type = str_params->codec;
  51. alloc_param.sg_count = str_params->aparams.sg_count;
  52. alloc_param.ring_buf_info[0].addr =
  53. str_params->aparams.ring_buf_info[0].addr;
  54. alloc_param.ring_buf_info[0].size =
  55. str_params->aparams.ring_buf_info[0].size;
  56. alloc_param.frag_size = str_params->aparams.frag_size;
  57. memcpy(&alloc_param.codec_params, &str_params->sparams,
  58. sizeof(struct snd_sst_stream_params));
  59. /*
  60. * fill channel map params for multichannel support.
  61. * Ideally channel map should be received from upper layers
  62. * for multichannel support.
  63. * Currently hardcoding as per FW reqm.
  64. */
  65. num_ch = sst_get_num_channel(str_params);
  66. for (i = 0; i < 8; i++) {
  67. if (i < num_ch)
  68. alloc_param.codec_params.uc.pcm_params.channel_map[i] = i;
  69. else
  70. alloc_param.codec_params.uc.pcm_params.channel_map[i] = 0xFF;
  71. }
  72. str_id = str_params->stream_id;
  73. str_info = get_stream_info(sst_drv_ctx, str_id);
  74. if (str_info == NULL) {
  75. dev_err(sst_drv_ctx->dev, "get stream info returned null\n");
  76. return -EINVAL;
  77. }
  78. pipe_id = str_params->device_type;
  79. task_id = str_params->task;
  80. sst_drv_ctx->streams[str_id].pipe_id = pipe_id;
  81. sst_drv_ctx->streams[str_id].task_id = task_id;
  82. sst_drv_ctx->streams[str_id].num_ch = num_ch;
  83. if (sst_drv_ctx->info.lpe_viewpt_rqd)
  84. alloc_param.ts = sst_drv_ctx->info.mailbox_start +
  85. sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
  86. else
  87. alloc_param.ts = sst_drv_ctx->mailbox_add +
  88. sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
  89. dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n",
  90. alloc_param.ts);
  91. dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n",
  92. pipe_id, task_id);
  93. /* allocate device type context */
  94. sst_init_stream(&sst_drv_ctx->streams[str_id], alloc_param.codec_type,
  95. str_id, alloc_param.operation, 0);
  96. dev_info(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
  97. str_id, pipe_id);
  98. ret = sst_prepare_and_post_msg(sst_drv_ctx, task_id, IPC_CMD,
  99. IPC_IA_ALLOC_STREAM_MRFLD, pipe_id, sizeof(alloc_param),
  100. &alloc_param, &data, true, true, false, true);
  101. if (ret < 0) {
  102. dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
  103. /* alloc failed, so reset the state to uninit */
  104. str_info->status = STREAM_UN_INIT;
  105. str_id = ret;
  106. } else if (data) {
  107. response = (struct snd_sst_alloc_response *)data;
  108. ret = response->str_type.result;
  109. if (!ret)
  110. goto out;
  111. dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
  112. if (ret == SST_ERR_STREAM_IN_USE) {
  113. dev_err(sst_drv_ctx->dev,
  114. "FW not in clean state, send free for:%d\n", str_id);
  115. sst_free_stream(sst_drv_ctx, str_id);
  116. }
  117. str_id = -ret;
  118. }
  119. out:
  120. kfree(data);
  121. return str_id;
  122. }
  123. /**
  124. * sst_start_stream - Send msg for a starting stream
  125. * @str_id: stream ID
  126. *
  127. * This function is called by any function which wants to start
  128. * a stream.
  129. */
  130. int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  131. {
  132. int retval = 0;
  133. struct stream_info *str_info;
  134. u16 data = 0;
  135. dev_dbg(sst_drv_ctx->dev, "sst_start_stream for %d\n", str_id);
  136. str_info = get_stream_info(sst_drv_ctx, str_id);
  137. if (!str_info)
  138. return -EINVAL;
  139. if (str_info->status != STREAM_RUNNING)
  140. return -EBADRQC;
  141. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
  142. IPC_CMD, IPC_IA_START_STREAM_MRFLD, str_info->pipe_id,
  143. sizeof(u16), &data, NULL, true, true, true, false);
  144. return retval;
  145. }
  146. int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx,
  147. struct snd_sst_bytes_v2 *bytes)
  148. { struct ipc_post *msg = NULL;
  149. u32 length;
  150. int pvt_id, ret = 0;
  151. struct sst_block *block = NULL;
  152. dev_dbg(sst_drv_ctx->dev,
  153. "type:%u ipc_msg:%u block:%u task_id:%u pipe: %#x length:%#x\n",
  154. bytes->type, bytes->ipc_msg, bytes->block, bytes->task_id,
  155. bytes->pipe_id, bytes->len);
  156. if (sst_create_ipc_msg(&msg, true))
  157. return -ENOMEM;
  158. pvt_id = sst_assign_pvt_id(sst_drv_ctx);
  159. sst_fill_header_mrfld(&msg->mrfld_header, bytes->ipc_msg,
  160. bytes->task_id, 1, pvt_id);
  161. msg->mrfld_header.p.header_high.part.res_rqd = bytes->block;
  162. length = bytes->len;
  163. msg->mrfld_header.p.header_low_payload = length;
  164. dev_dbg(sst_drv_ctx->dev, "length is %d\n", length);
  165. memcpy(msg->mailbox_data, &bytes->bytes, bytes->len);
  166. if (bytes->block) {
  167. block = sst_create_block(sst_drv_ctx, bytes->ipc_msg, pvt_id);
  168. if (block == NULL) {
  169. kfree(msg);
  170. ret = -ENOMEM;
  171. goto out;
  172. }
  173. }
  174. sst_add_to_dispatch_list_and_post(sst_drv_ctx, msg);
  175. dev_dbg(sst_drv_ctx->dev, "msg->mrfld_header.p.header_low_payload:%d",
  176. msg->mrfld_header.p.header_low_payload);
  177. if (bytes->block) {
  178. ret = sst_wait_timeout(sst_drv_ctx, block);
  179. if (ret) {
  180. dev_err(sst_drv_ctx->dev, "fw returned err %d\n", ret);
  181. sst_free_block(sst_drv_ctx, block);
  182. goto out;
  183. }
  184. }
  185. if (bytes->type == SND_SST_BYTES_GET) {
  186. /*
  187. * copy the reply and send back
  188. * we need to update only sz and payload
  189. */
  190. if (bytes->block) {
  191. unsigned char *r = block->data;
  192. dev_dbg(sst_drv_ctx->dev, "read back %d bytes",
  193. bytes->len);
  194. memcpy(bytes->bytes, r, bytes->len);
  195. }
  196. }
  197. if (bytes->block)
  198. sst_free_block(sst_drv_ctx, block);
  199. out:
  200. test_and_clear_bit(pvt_id, &sst_drv_ctx->pvt_id);
  201. return ret;
  202. }
  203. /*
  204. * sst_pause_stream - Send msg for a pausing stream
  205. * @str_id: stream ID
  206. *
  207. * This function is called by any function which wants to pause
  208. * an already running stream.
  209. */
  210. int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  211. {
  212. int retval = 0;
  213. struct stream_info *str_info;
  214. dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_pause_stream for %d\n", str_id);
  215. str_info = get_stream_info(sst_drv_ctx, str_id);
  216. if (!str_info)
  217. return -EINVAL;
  218. if (str_info->status == STREAM_PAUSED)
  219. return 0;
  220. if (str_info->status == STREAM_RUNNING ||
  221. str_info->status == STREAM_INIT) {
  222. if (str_info->prev == STREAM_UN_INIT)
  223. return -EBADRQC;
  224. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
  225. IPC_IA_PAUSE_STREAM_MRFLD, str_info->pipe_id,
  226. 0, NULL, NULL, true, true, false, true);
  227. if (retval == 0) {
  228. str_info->prev = str_info->status;
  229. str_info->status = STREAM_PAUSED;
  230. } else if (retval == SST_ERR_INVALID_STREAM_ID) {
  231. retval = -EINVAL;
  232. mutex_lock(&sst_drv_ctx->sst_lock);
  233. sst_clean_stream(str_info);
  234. mutex_unlock(&sst_drv_ctx->sst_lock);
  235. }
  236. } else {
  237. retval = -EBADRQC;
  238. dev_dbg(sst_drv_ctx->dev, "SST DBG:BADRQC for stream\n ");
  239. }
  240. return retval;
  241. }
  242. /**
  243. * sst_resume_stream - Send msg for resuming stream
  244. * @str_id: stream ID
  245. *
  246. * This function is called by any function which wants to resume
  247. * an already paused stream.
  248. */
  249. int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  250. {
  251. int retval = 0;
  252. struct stream_info *str_info;
  253. dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_resume_stream for %d\n", str_id);
  254. str_info = get_stream_info(sst_drv_ctx, str_id);
  255. if (!str_info)
  256. return -EINVAL;
  257. if (str_info->status == STREAM_RUNNING)
  258. return 0;
  259. if (str_info->status == STREAM_PAUSED) {
  260. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
  261. IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD,
  262. str_info->pipe_id, 0, NULL, NULL,
  263. true, true, false, true);
  264. if (!retval) {
  265. if (str_info->prev == STREAM_RUNNING)
  266. str_info->status = STREAM_RUNNING;
  267. else
  268. str_info->status = STREAM_INIT;
  269. str_info->prev = STREAM_PAUSED;
  270. } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
  271. retval = -EINVAL;
  272. mutex_lock(&sst_drv_ctx->sst_lock);
  273. sst_clean_stream(str_info);
  274. mutex_unlock(&sst_drv_ctx->sst_lock);
  275. }
  276. } else {
  277. retval = -EBADRQC;
  278. dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream\n");
  279. }
  280. return retval;
  281. }
  282. /**
  283. * sst_drop_stream - Send msg for stopping stream
  284. * @str_id: stream ID
  285. *
  286. * This function is called by any function which wants to stop
  287. * a stream.
  288. */
  289. int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  290. {
  291. int retval = 0;
  292. struct stream_info *str_info;
  293. dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drop_stream for %d\n", str_id);
  294. str_info = get_stream_info(sst_drv_ctx, str_id);
  295. if (!str_info)
  296. return -EINVAL;
  297. if (str_info->status != STREAM_UN_INIT) {
  298. str_info->prev = STREAM_UN_INIT;
  299. str_info->status = STREAM_INIT;
  300. str_info->cumm_bytes = 0;
  301. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
  302. IPC_CMD, IPC_IA_DROP_STREAM_MRFLD,
  303. str_info->pipe_id, 0, NULL, NULL,
  304. true, true, true, false);
  305. } else {
  306. retval = -EBADRQC;
  307. dev_dbg(sst_drv_ctx->dev, "BADQRC for stream, state %x\n",
  308. str_info->status);
  309. }
  310. return retval;
  311. }
  312. /**
  313. * sst_drain_stream - Send msg for draining stream
  314. * @str_id: stream ID
  315. *
  316. * This function is called by any function which wants to drain
  317. * a stream.
  318. */
  319. int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx,
  320. int str_id, bool partial_drain)
  321. {
  322. int retval = 0;
  323. struct stream_info *str_info;
  324. dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drain_stream for %d\n", str_id);
  325. str_info = get_stream_info(sst_drv_ctx, str_id);
  326. if (!str_info)
  327. return -EINVAL;
  328. if (str_info->status != STREAM_RUNNING &&
  329. str_info->status != STREAM_INIT &&
  330. str_info->status != STREAM_PAUSED) {
  331. dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream = %d\n",
  332. str_info->status);
  333. return -EBADRQC;
  334. }
  335. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
  336. IPC_IA_DRAIN_STREAM_MRFLD, str_info->pipe_id,
  337. sizeof(u8), &partial_drain, NULL, true, true, false, false);
  338. /*
  339. * with new non blocked drain implementation in core we dont need to
  340. * wait for respsonse, and need to only invoke callback for drain
  341. * complete
  342. */
  343. return retval;
  344. }
  345. /**
  346. * sst_free_stream - Frees a stream
  347. * @str_id: stream ID
  348. *
  349. * This function is called by any function which wants to free
  350. * a stream.
  351. */
  352. int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  353. {
  354. int retval = 0;
  355. struct stream_info *str_info;
  356. struct intel_sst_ops *ops;
  357. dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id);
  358. mutex_lock(&sst_drv_ctx->sst_lock);
  359. if (sst_drv_ctx->sst_state == SST_RESET) {
  360. mutex_unlock(&sst_drv_ctx->sst_lock);
  361. return -ENODEV;
  362. }
  363. mutex_unlock(&sst_drv_ctx->sst_lock);
  364. str_info = get_stream_info(sst_drv_ctx, str_id);
  365. if (!str_info)
  366. return -EINVAL;
  367. ops = sst_drv_ctx->ops;
  368. mutex_lock(&str_info->lock);
  369. if (str_info->status != STREAM_UN_INIT) {
  370. str_info->prev = str_info->status;
  371. str_info->status = STREAM_UN_INIT;
  372. mutex_unlock(&str_info->lock);
  373. dev_info(sst_drv_ctx->dev, "Free for str %d pipe %#x\n",
  374. str_id, str_info->pipe_id);
  375. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
  376. IPC_IA_FREE_STREAM_MRFLD, str_info->pipe_id, 0,
  377. NULL, NULL, true, true, false, true);
  378. dev_dbg(sst_drv_ctx->dev, "sst: wait for free returned %d\n",
  379. retval);
  380. mutex_lock(&sst_drv_ctx->sst_lock);
  381. sst_clean_stream(str_info);
  382. mutex_unlock(&sst_drv_ctx->sst_lock);
  383. dev_dbg(sst_drv_ctx->dev, "SST DBG:Stream freed\n");
  384. } else {
  385. mutex_unlock(&str_info->lock);
  386. retval = -EBADRQC;
  387. dev_dbg(sst_drv_ctx->dev, "SST DBG:BADQRC for stream\n");
  388. }
  389. return retval;
  390. }