sst_stream.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  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_pcm_params *pcm_params;
  38. struct snd_sst_params *str_params;
  39. struct snd_sst_tstamp fw_tstamp;
  40. struct stream_info *str_info;
  41. int i, num_ch, str_id;
  42. dev_dbg(sst_drv_ctx->dev, "Enter\n");
  43. str_params = (struct snd_sst_params *)params;
  44. str_id = str_params->stream_id;
  45. str_info = get_stream_info(sst_drv_ctx, str_id);
  46. if (!str_info)
  47. return -EINVAL;
  48. memset(&str_info->alloc_param, 0, sizeof(str_info->alloc_param));
  49. str_info->alloc_param.operation = str_params->ops;
  50. str_info->alloc_param.codec_type = str_params->codec;
  51. str_info->alloc_param.sg_count = str_params->aparams.sg_count;
  52. str_info->alloc_param.ring_buf_info[0].addr =
  53. str_params->aparams.ring_buf_info[0].addr;
  54. str_info->alloc_param.ring_buf_info[0].size =
  55. str_params->aparams.ring_buf_info[0].size;
  56. str_info->alloc_param.frag_size = str_params->aparams.frag_size;
  57. memcpy(&str_info->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. pcm_params = &str_info->alloc_param.codec_params.uc.pcm_params;
  67. for (i = 0; i < 8; i++) {
  68. if (i < num_ch)
  69. pcm_params->channel_map[i] = i;
  70. else
  71. pcm_params->channel_map[i] = 0xff;
  72. }
  73. sst_drv_ctx->streams[str_id].status = STREAM_INIT;
  74. sst_drv_ctx->streams[str_id].prev = STREAM_UN_INIT;
  75. sst_drv_ctx->streams[str_id].pipe_id = str_params->device_type;
  76. sst_drv_ctx->streams[str_id].task_id = str_params->task;
  77. sst_drv_ctx->streams[str_id].num_ch = num_ch;
  78. if (sst_drv_ctx->info.lpe_viewpt_rqd)
  79. str_info->alloc_param.ts = sst_drv_ctx->info.mailbox_start +
  80. sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
  81. else
  82. str_info->alloc_param.ts = sst_drv_ctx->mailbox_add +
  83. sst_drv_ctx->tstamp + (str_id * sizeof(fw_tstamp));
  84. dev_dbg(sst_drv_ctx->dev, "alloc tstamp location = 0x%x\n",
  85. str_info->alloc_param.ts);
  86. dev_dbg(sst_drv_ctx->dev, "assigned pipe id 0x%x to task %d\n",
  87. str_info->pipe_id, str_info->task_id);
  88. return sst_realloc_stream(sst_drv_ctx, str_id);
  89. }
  90. /**
  91. * sst_realloc_stream - Send msg for (re-)allocating a stream using the
  92. * @sst_drv_ctx intel_sst_drv context pointer
  93. * @str_id: stream ID
  94. *
  95. * Send a msg for (re-)allocating a stream using the parameters previously
  96. * passed to sst_alloc_stream_mrfld() for the same stream ID.
  97. * Return: 0 or negative errno value.
  98. */
  99. int sst_realloc_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  100. {
  101. struct snd_sst_alloc_response *response;
  102. struct stream_info *str_info;
  103. void *data = NULL;
  104. int ret;
  105. str_info = get_stream_info(sst_drv_ctx, str_id);
  106. if (!str_info)
  107. return -EINVAL;
  108. dev_dbg(sst_drv_ctx->dev, "Alloc for str %d pipe %#x\n",
  109. str_id, str_info->pipe_id);
  110. ret = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
  111. IPC_IA_ALLOC_STREAM_MRFLD, str_info->pipe_id,
  112. sizeof(str_info->alloc_param), &str_info->alloc_param,
  113. &data, true, true, false, true);
  114. if (ret < 0) {
  115. dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
  116. /* alloc failed, so reset the state to uninit */
  117. str_info->status = STREAM_UN_INIT;
  118. str_id = ret;
  119. } else if (data) {
  120. response = (struct snd_sst_alloc_response *)data;
  121. ret = response->str_type.result;
  122. if (!ret)
  123. goto out;
  124. dev_err(sst_drv_ctx->dev, "FW alloc failed ret %d\n", ret);
  125. if (ret == SST_ERR_STREAM_IN_USE) {
  126. dev_err(sst_drv_ctx->dev,
  127. "FW not in clean state, send free for:%d\n", str_id);
  128. sst_free_stream(sst_drv_ctx, str_id);
  129. }
  130. str_id = -ret;
  131. }
  132. out:
  133. kfree(data);
  134. return str_id;
  135. }
  136. /**
  137. * sst_start_stream - Send msg for a starting stream
  138. * @str_id: stream ID
  139. *
  140. * This function is called by any function which wants to start
  141. * a stream.
  142. */
  143. int sst_start_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  144. {
  145. int retval = 0;
  146. struct stream_info *str_info;
  147. u16 data = 0;
  148. dev_dbg(sst_drv_ctx->dev, "sst_start_stream for %d\n", str_id);
  149. str_info = get_stream_info(sst_drv_ctx, str_id);
  150. if (!str_info)
  151. return -EINVAL;
  152. if (str_info->status != STREAM_RUNNING)
  153. return -EBADRQC;
  154. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
  155. IPC_CMD, IPC_IA_START_STREAM_MRFLD, str_info->pipe_id,
  156. sizeof(u16), &data, NULL, true, true, true, false);
  157. return retval;
  158. }
  159. int sst_send_byte_stream_mrfld(struct intel_sst_drv *sst_drv_ctx,
  160. struct snd_sst_bytes_v2 *bytes)
  161. { struct ipc_post *msg = NULL;
  162. u32 length;
  163. int pvt_id, ret = 0;
  164. struct sst_block *block = NULL;
  165. dev_dbg(sst_drv_ctx->dev,
  166. "type:%u ipc_msg:%u block:%u task_id:%u pipe: %#x length:%#x\n",
  167. bytes->type, bytes->ipc_msg, bytes->block, bytes->task_id,
  168. bytes->pipe_id, bytes->len);
  169. if (sst_create_ipc_msg(&msg, true))
  170. return -ENOMEM;
  171. pvt_id = sst_assign_pvt_id(sst_drv_ctx);
  172. sst_fill_header_mrfld(&msg->mrfld_header, bytes->ipc_msg,
  173. bytes->task_id, 1, pvt_id);
  174. msg->mrfld_header.p.header_high.part.res_rqd = bytes->block;
  175. length = bytes->len;
  176. msg->mrfld_header.p.header_low_payload = length;
  177. dev_dbg(sst_drv_ctx->dev, "length is %d\n", length);
  178. memcpy(msg->mailbox_data, &bytes->bytes, bytes->len);
  179. if (bytes->block) {
  180. block = sst_create_block(sst_drv_ctx, bytes->ipc_msg, pvt_id);
  181. if (block == NULL) {
  182. kfree(msg);
  183. ret = -ENOMEM;
  184. goto out;
  185. }
  186. }
  187. sst_add_to_dispatch_list_and_post(sst_drv_ctx, msg);
  188. dev_dbg(sst_drv_ctx->dev, "msg->mrfld_header.p.header_low_payload:%d",
  189. msg->mrfld_header.p.header_low_payload);
  190. if (bytes->block) {
  191. ret = sst_wait_timeout(sst_drv_ctx, block);
  192. if (ret) {
  193. dev_err(sst_drv_ctx->dev, "fw returned err %d\n", ret);
  194. sst_free_block(sst_drv_ctx, block);
  195. goto out;
  196. }
  197. }
  198. if (bytes->type == SND_SST_BYTES_GET) {
  199. /*
  200. * copy the reply and send back
  201. * we need to update only sz and payload
  202. */
  203. if (bytes->block) {
  204. unsigned char *r = block->data;
  205. dev_dbg(sst_drv_ctx->dev, "read back %d bytes",
  206. bytes->len);
  207. memcpy(bytes->bytes, r, bytes->len);
  208. }
  209. }
  210. if (bytes->block)
  211. sst_free_block(sst_drv_ctx, block);
  212. out:
  213. test_and_clear_bit(pvt_id, &sst_drv_ctx->pvt_id);
  214. return ret;
  215. }
  216. /**
  217. * sst_pause_stream - Send msg for a pausing stream
  218. * @str_id: stream ID
  219. *
  220. * This function is called by any function which wants to pause
  221. * an already running stream.
  222. */
  223. int sst_pause_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  224. {
  225. int retval = 0;
  226. struct stream_info *str_info;
  227. dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_pause_stream for %d\n", str_id);
  228. str_info = get_stream_info(sst_drv_ctx, str_id);
  229. if (!str_info)
  230. return -EINVAL;
  231. if (str_info->status == STREAM_PAUSED)
  232. return 0;
  233. if (str_info->status == STREAM_RUNNING ||
  234. str_info->status == STREAM_INIT) {
  235. if (str_info->prev == STREAM_UN_INIT)
  236. return -EBADRQC;
  237. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
  238. IPC_IA_PAUSE_STREAM_MRFLD, str_info->pipe_id,
  239. 0, NULL, NULL, true, true, false, true);
  240. if (retval == 0) {
  241. str_info->prev = str_info->status;
  242. str_info->status = STREAM_PAUSED;
  243. } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
  244. retval = -EINVAL;
  245. mutex_lock(&sst_drv_ctx->sst_lock);
  246. sst_clean_stream(str_info);
  247. mutex_unlock(&sst_drv_ctx->sst_lock);
  248. }
  249. } else {
  250. retval = -EBADRQC;
  251. dev_dbg(sst_drv_ctx->dev, "SST DBG:BADRQC for stream\n");
  252. }
  253. return retval;
  254. }
  255. /**
  256. * sst_resume_stream - Send msg for resuming stream
  257. * @str_id: stream ID
  258. *
  259. * This function is called by any function which wants to resume
  260. * an already paused stream.
  261. */
  262. int sst_resume_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  263. {
  264. int retval = 0;
  265. struct stream_info *str_info;
  266. dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_resume_stream for %d\n", str_id);
  267. str_info = get_stream_info(sst_drv_ctx, str_id);
  268. if (!str_info)
  269. return -EINVAL;
  270. if (str_info->status == STREAM_RUNNING)
  271. return 0;
  272. if (str_info->resume_status == STREAM_PAUSED &&
  273. str_info->resume_prev == STREAM_RUNNING) {
  274. /*
  275. * Stream was running before suspend and re-created on resume,
  276. * start it to get back to running state.
  277. */
  278. dev_dbg(sst_drv_ctx->dev, "restart recreated stream after resume\n");
  279. str_info->status = STREAM_RUNNING;
  280. str_info->prev = STREAM_PAUSED;
  281. retval = sst_start_stream(sst_drv_ctx, str_id);
  282. str_info->resume_status = STREAM_UN_INIT;
  283. } else if (str_info->resume_status == STREAM_PAUSED &&
  284. str_info->resume_prev == STREAM_INIT) {
  285. /*
  286. * Stream was idle before suspend and re-created on resume,
  287. * keep it as is.
  288. */
  289. dev_dbg(sst_drv_ctx->dev, "leaving recreated stream idle after resume\n");
  290. str_info->status = STREAM_INIT;
  291. str_info->prev = STREAM_PAUSED;
  292. str_info->resume_status = STREAM_UN_INIT;
  293. } else if (str_info->status == STREAM_PAUSED) {
  294. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
  295. IPC_CMD, IPC_IA_RESUME_STREAM_MRFLD,
  296. str_info->pipe_id, 0, NULL, NULL,
  297. true, true, false, true);
  298. if (!retval) {
  299. if (str_info->prev == STREAM_RUNNING)
  300. str_info->status = STREAM_RUNNING;
  301. else
  302. str_info->status = STREAM_INIT;
  303. str_info->prev = STREAM_PAUSED;
  304. } else if (retval == -SST_ERR_INVALID_STREAM_ID) {
  305. retval = -EINVAL;
  306. mutex_lock(&sst_drv_ctx->sst_lock);
  307. sst_clean_stream(str_info);
  308. mutex_unlock(&sst_drv_ctx->sst_lock);
  309. }
  310. } else {
  311. retval = -EBADRQC;
  312. dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream\n");
  313. }
  314. return retval;
  315. }
  316. /**
  317. * sst_drop_stream - Send msg for stopping stream
  318. * @str_id: stream ID
  319. *
  320. * This function is called by any function which wants to stop
  321. * a stream.
  322. */
  323. int sst_drop_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  324. {
  325. int retval = 0;
  326. struct stream_info *str_info;
  327. dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drop_stream for %d\n", str_id);
  328. str_info = get_stream_info(sst_drv_ctx, str_id);
  329. if (!str_info)
  330. return -EINVAL;
  331. if (str_info->status != STREAM_UN_INIT) {
  332. str_info->prev = STREAM_UN_INIT;
  333. str_info->status = STREAM_INIT;
  334. str_info->cumm_bytes = 0;
  335. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id,
  336. IPC_CMD, IPC_IA_DROP_STREAM_MRFLD,
  337. str_info->pipe_id, 0, NULL, NULL,
  338. true, true, true, false);
  339. } else {
  340. retval = -EBADRQC;
  341. dev_dbg(sst_drv_ctx->dev, "BADQRC for stream, state %x\n",
  342. str_info->status);
  343. }
  344. return retval;
  345. }
  346. /**
  347. * sst_drain_stream - Send msg for draining stream
  348. * @str_id: stream ID
  349. *
  350. * This function is called by any function which wants to drain
  351. * a stream.
  352. */
  353. int sst_drain_stream(struct intel_sst_drv *sst_drv_ctx,
  354. int str_id, bool partial_drain)
  355. {
  356. int retval = 0;
  357. struct stream_info *str_info;
  358. dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_drain_stream for %d\n", str_id);
  359. str_info = get_stream_info(sst_drv_ctx, str_id);
  360. if (!str_info)
  361. return -EINVAL;
  362. if (str_info->status != STREAM_RUNNING &&
  363. str_info->status != STREAM_INIT &&
  364. str_info->status != STREAM_PAUSED) {
  365. dev_err(sst_drv_ctx->dev, "SST ERR: BADQRC for stream = %d\n",
  366. str_info->status);
  367. return -EBADRQC;
  368. }
  369. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
  370. IPC_IA_DRAIN_STREAM_MRFLD, str_info->pipe_id,
  371. sizeof(u8), &partial_drain, NULL, true, true, false, false);
  372. /*
  373. * with new non blocked drain implementation in core we dont need to
  374. * wait for respsonse, and need to only invoke callback for drain
  375. * complete
  376. */
  377. return retval;
  378. }
  379. /**
  380. * sst_free_stream - Frees a stream
  381. * @str_id: stream ID
  382. *
  383. * This function is called by any function which wants to free
  384. * a stream.
  385. */
  386. int sst_free_stream(struct intel_sst_drv *sst_drv_ctx, int str_id)
  387. {
  388. int retval = 0;
  389. struct stream_info *str_info;
  390. dev_dbg(sst_drv_ctx->dev, "SST DBG:sst_free_stream for %d\n", str_id);
  391. mutex_lock(&sst_drv_ctx->sst_lock);
  392. if (sst_drv_ctx->sst_state == SST_RESET) {
  393. mutex_unlock(&sst_drv_ctx->sst_lock);
  394. return -ENODEV;
  395. }
  396. mutex_unlock(&sst_drv_ctx->sst_lock);
  397. str_info = get_stream_info(sst_drv_ctx, str_id);
  398. if (!str_info)
  399. return -EINVAL;
  400. mutex_lock(&str_info->lock);
  401. if (str_info->status != STREAM_UN_INIT) {
  402. str_info->prev = str_info->status;
  403. str_info->status = STREAM_UN_INIT;
  404. mutex_unlock(&str_info->lock);
  405. dev_dbg(sst_drv_ctx->dev, "Free for str %d pipe %#x\n",
  406. str_id, str_info->pipe_id);
  407. retval = sst_prepare_and_post_msg(sst_drv_ctx, str_info->task_id, IPC_CMD,
  408. IPC_IA_FREE_STREAM_MRFLD, str_info->pipe_id, 0,
  409. NULL, NULL, true, true, false, true);
  410. dev_dbg(sst_drv_ctx->dev, "sst: wait for free returned %d\n",
  411. retval);
  412. mutex_lock(&sst_drv_ctx->sst_lock);
  413. sst_clean_stream(str_info);
  414. mutex_unlock(&sst_drv_ctx->sst_lock);
  415. dev_dbg(sst_drv_ctx->dev, "SST DBG:Stream freed\n");
  416. } else {
  417. mutex_unlock(&str_info->lock);
  418. retval = -EBADRQC;
  419. dev_dbg(sst_drv_ctx->dev, "SST DBG:BADQRC for stream\n");
  420. }
  421. return retval;
  422. }