q6asm.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
  3. // Copyright (c) 2018, Linaro Limited
  4. #include <linux/mutex.h>
  5. #include <linux/wait.h>
  6. #include <linux/module.h>
  7. #include <linux/soc/qcom/apr.h>
  8. #include <linux/device.h>
  9. #include <linux/of_platform.h>
  10. #include <linux/spinlock.h>
  11. #include <linux/kref.h>
  12. #include <linux/of.h>
  13. #include <linux/of_platform.h>
  14. #include <uapi/sound/asound.h>
  15. #include <linux/delay.h>
  16. #include <linux/slab.h>
  17. #include <linux/mm.h>
  18. #include "q6asm.h"
  19. #include "q6core.h"
  20. #include "q6dsp-errno.h"
  21. #include "q6dsp-common.h"
  22. #define ASM_STREAM_CMD_CLOSE 0x00010BCD
  23. #define ASM_STREAM_CMD_FLUSH 0x00010BCE
  24. #define ASM_SESSION_CMD_PAUSE 0x00010BD3
  25. #define ASM_DATA_CMD_EOS 0x00010BDB
  26. #define ASM_DATA_EVENT_RENDERED_EOS 0x00010C1C
  27. #define ASM_NULL_POPP_TOPOLOGY 0x00010C68
  28. #define ASM_STREAM_CMD_FLUSH_READBUFS 0x00010C09
  29. #define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10
  30. #define ASM_STREAM_POSTPROC_TOPO_ID_NONE 0x00010C68
  31. #define ASM_CMD_SHARED_MEM_MAP_REGIONS 0x00010D92
  32. #define ASM_CMDRSP_SHARED_MEM_MAP_REGIONS 0x00010D93
  33. #define ASM_CMD_SHARED_MEM_UNMAP_REGIONS 0x00010D94
  34. #define ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2 0x00010D98
  35. #define ASM_DATA_EVENT_WRITE_DONE_V2 0x00010D99
  36. #define ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2 0x00010DA3
  37. #define ASM_SESSION_CMD_RUN_V2 0x00010DAA
  38. #define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2 0x00010DA5
  39. #define ASM_DATA_CMD_WRITE_V2 0x00010DAB
  40. #define ASM_DATA_CMD_READ_V2 0x00010DAC
  41. #define ASM_SESSION_CMD_SUSPEND 0x00010DEC
  42. #define ASM_STREAM_CMD_OPEN_WRITE_V3 0x00010DB3
  43. #define ASM_STREAM_CMD_OPEN_READ_V3 0x00010DB4
  44. #define ASM_DATA_EVENT_READ_DONE_V2 0x00010D9A
  45. #define ASM_STREAM_CMD_OPEN_READWRITE_V2 0x00010D8D
  46. #define ASM_LEGACY_STREAM_SESSION 0
  47. /* Bit shift for the stream_perf_mode subfield. */
  48. #define ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ 29
  49. #define ASM_END_POINT_DEVICE_MATRIX 0
  50. #define ASM_DEFAULT_APP_TYPE 0
  51. #define ASM_SYNC_IO_MODE 0x0001
  52. #define ASM_ASYNC_IO_MODE 0x0002
  53. #define ASM_TUN_READ_IO_MODE 0x0004 /* tunnel read write mode */
  54. #define ASM_TUN_WRITE_IO_MODE 0x0008 /* tunnel read write mode */
  55. #define ASM_SHIFT_GAPLESS_MODE_FLAG 31
  56. #define ADSP_MEMORY_MAP_SHMEM8_4K_POOL 3
  57. struct avs_cmd_shared_mem_map_regions {
  58. u16 mem_pool_id;
  59. u16 num_regions;
  60. u32 property_flag;
  61. } __packed;
  62. struct avs_shared_map_region_payload {
  63. u32 shm_addr_lsw;
  64. u32 shm_addr_msw;
  65. u32 mem_size_bytes;
  66. } __packed;
  67. struct avs_cmd_shared_mem_unmap_regions {
  68. u32 mem_map_handle;
  69. } __packed;
  70. struct asm_data_cmd_media_fmt_update_v2 {
  71. u32 fmt_blk_size;
  72. } __packed;
  73. struct asm_multi_channel_pcm_fmt_blk_v2 {
  74. struct asm_data_cmd_media_fmt_update_v2 fmt_blk;
  75. u16 num_channels;
  76. u16 bits_per_sample;
  77. u32 sample_rate;
  78. u16 is_signed;
  79. u16 reserved;
  80. u8 channel_mapping[PCM_MAX_NUM_CHANNEL];
  81. } __packed;
  82. struct asm_stream_cmd_set_encdec_param {
  83. u32 param_id;
  84. u32 param_size;
  85. } __packed;
  86. struct asm_enc_cfg_blk_param_v2 {
  87. u32 frames_per_buf;
  88. u32 enc_cfg_blk_size;
  89. } __packed;
  90. struct asm_multi_channel_pcm_enc_cfg_v2 {
  91. struct asm_stream_cmd_set_encdec_param encdec;
  92. struct asm_enc_cfg_blk_param_v2 encblk;
  93. uint16_t num_channels;
  94. uint16_t bits_per_sample;
  95. uint32_t sample_rate;
  96. uint16_t is_signed;
  97. uint16_t reserved;
  98. uint8_t channel_mapping[8];
  99. } __packed;
  100. struct asm_data_cmd_read_v2 {
  101. u32 buf_addr_lsw;
  102. u32 buf_addr_msw;
  103. u32 mem_map_handle;
  104. u32 buf_size;
  105. u32 seq_id;
  106. } __packed;
  107. struct asm_data_cmd_read_v2_done {
  108. u32 status;
  109. u32 buf_addr_lsw;
  110. u32 buf_addr_msw;
  111. };
  112. struct asm_stream_cmd_open_read_v3 {
  113. u32 mode_flags;
  114. u32 src_endpointype;
  115. u32 preprocopo_id;
  116. u32 enc_cfg_id;
  117. u16 bits_per_sample;
  118. u16 reserved;
  119. } __packed;
  120. struct asm_data_cmd_write_v2 {
  121. u32 buf_addr_lsw;
  122. u32 buf_addr_msw;
  123. u32 mem_map_handle;
  124. u32 buf_size;
  125. u32 seq_id;
  126. u32 timestamp_lsw;
  127. u32 timestamp_msw;
  128. u32 flags;
  129. } __packed;
  130. struct asm_stream_cmd_open_write_v3 {
  131. uint32_t mode_flags;
  132. uint16_t sink_endpointype;
  133. uint16_t bits_per_sample;
  134. uint32_t postprocopo_id;
  135. uint32_t dec_fmt_id;
  136. } __packed;
  137. struct asm_session_cmd_run_v2 {
  138. u32 flags;
  139. u32 time_lsw;
  140. u32 time_msw;
  141. } __packed;
  142. struct audio_buffer {
  143. phys_addr_t phys;
  144. uint32_t size; /* size of buffer */
  145. };
  146. struct audio_port_data {
  147. struct audio_buffer *buf;
  148. uint32_t num_periods;
  149. uint32_t dsp_buf;
  150. uint32_t mem_map_handle;
  151. };
  152. struct q6asm {
  153. struct apr_device *adev;
  154. struct device *dev;
  155. struct q6core_svc_api_info ainfo;
  156. wait_queue_head_t mem_wait;
  157. spinlock_t slock;
  158. struct audio_client *session[MAX_SESSIONS + 1];
  159. };
  160. struct audio_client {
  161. int session;
  162. q6asm_cb cb;
  163. void *priv;
  164. uint32_t io_mode;
  165. struct apr_device *adev;
  166. struct mutex cmd_lock;
  167. spinlock_t lock;
  168. struct kref refcount;
  169. /* idx:1 out port, 0: in port */
  170. struct audio_port_data port[2];
  171. wait_queue_head_t cmd_wait;
  172. struct aprv2_ibasic_rsp_result_t result;
  173. int perf_mode;
  174. int stream_id;
  175. struct q6asm *q6asm;
  176. struct device *dev;
  177. };
  178. static inline void q6asm_add_hdr(struct audio_client *ac, struct apr_hdr *hdr,
  179. uint32_t pkt_size, bool cmd_flg,
  180. uint32_t stream_id)
  181. {
  182. hdr->hdr_field = APR_SEQ_CMD_HDR_FIELD;
  183. hdr->src_port = ((ac->session << 8) & 0xFF00) | (stream_id);
  184. hdr->dest_port = ((ac->session << 8) & 0xFF00) | (stream_id);
  185. hdr->pkt_size = pkt_size;
  186. if (cmd_flg)
  187. hdr->token = ac->session;
  188. }
  189. static int q6asm_apr_send_session_pkt(struct q6asm *a, struct audio_client *ac,
  190. struct apr_pkt *pkt, uint32_t rsp_opcode)
  191. {
  192. struct apr_hdr *hdr = &pkt->hdr;
  193. int rc;
  194. mutex_lock(&ac->cmd_lock);
  195. ac->result.opcode = 0;
  196. ac->result.status = 0;
  197. rc = apr_send_pkt(a->adev, pkt);
  198. if (rc < 0)
  199. goto err;
  200. if (rsp_opcode)
  201. rc = wait_event_timeout(a->mem_wait,
  202. (ac->result.opcode == hdr->opcode) ||
  203. (ac->result.opcode == rsp_opcode),
  204. 5 * HZ);
  205. else
  206. rc = wait_event_timeout(a->mem_wait,
  207. (ac->result.opcode == hdr->opcode),
  208. 5 * HZ);
  209. if (!rc) {
  210. dev_err(a->dev, "CMD timeout\n");
  211. rc = -ETIMEDOUT;
  212. } else if (ac->result.status > 0) {
  213. dev_err(a->dev, "DSP returned error[%x]\n",
  214. ac->result.status);
  215. rc = -EINVAL;
  216. }
  217. err:
  218. mutex_unlock(&ac->cmd_lock);
  219. return rc;
  220. }
  221. static int __q6asm_memory_unmap(struct audio_client *ac,
  222. phys_addr_t buf_add, int dir)
  223. {
  224. struct avs_cmd_shared_mem_unmap_regions *mem_unmap;
  225. struct q6asm *a = dev_get_drvdata(ac->dev->parent);
  226. struct apr_pkt *pkt;
  227. int rc, pkt_size;
  228. void *p;
  229. if (ac->port[dir].mem_map_handle == 0) {
  230. dev_err(ac->dev, "invalid mem handle\n");
  231. return -EINVAL;
  232. }
  233. pkt_size = APR_HDR_SIZE + sizeof(*mem_unmap);
  234. p = kzalloc(pkt_size, GFP_KERNEL);
  235. if (!p)
  236. return -ENOMEM;
  237. pkt = p;
  238. mem_unmap = p + APR_HDR_SIZE;
  239. pkt->hdr.hdr_field = APR_SEQ_CMD_HDR_FIELD;
  240. pkt->hdr.src_port = 0;
  241. pkt->hdr.dest_port = 0;
  242. pkt->hdr.pkt_size = pkt_size;
  243. pkt->hdr.token = ((ac->session << 8) | dir);
  244. pkt->hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS;
  245. mem_unmap->mem_map_handle = ac->port[dir].mem_map_handle;
  246. rc = q6asm_apr_send_session_pkt(a, ac, pkt, 0);
  247. if (rc < 0) {
  248. kfree(pkt);
  249. return rc;
  250. }
  251. ac->port[dir].mem_map_handle = 0;
  252. kfree(pkt);
  253. return 0;
  254. }
  255. static void q6asm_audio_client_free_buf(struct audio_client *ac,
  256. struct audio_port_data *port)
  257. {
  258. unsigned long flags;
  259. spin_lock_irqsave(&ac->lock, flags);
  260. port->num_periods = 0;
  261. kfree(port->buf);
  262. port->buf = NULL;
  263. spin_unlock_irqrestore(&ac->lock, flags);
  264. }
  265. /**
  266. * q6asm_unmap_memory_regions() - unmap memory regions in the dsp.
  267. *
  268. * @dir: direction of audio stream
  269. * @ac: audio client instanace
  270. *
  271. * Return: Will be an negative value on failure or zero on success
  272. */
  273. int q6asm_unmap_memory_regions(unsigned int dir, struct audio_client *ac)
  274. {
  275. struct audio_port_data *port;
  276. int cnt = 0;
  277. int rc = 0;
  278. port = &ac->port[dir];
  279. if (!port->buf) {
  280. rc = -EINVAL;
  281. goto err;
  282. }
  283. cnt = port->num_periods - 1;
  284. if (cnt >= 0) {
  285. rc = __q6asm_memory_unmap(ac, port->buf[dir].phys, dir);
  286. if (rc < 0) {
  287. dev_err(ac->dev, "%s: Memory_unmap_regions failed %d\n",
  288. __func__, rc);
  289. goto err;
  290. }
  291. }
  292. q6asm_audio_client_free_buf(ac, port);
  293. err:
  294. return rc;
  295. }
  296. EXPORT_SYMBOL_GPL(q6asm_unmap_memory_regions);
  297. static int __q6asm_memory_map_regions(struct audio_client *ac, int dir,
  298. size_t period_sz, unsigned int periods,
  299. bool is_contiguous)
  300. {
  301. struct avs_cmd_shared_mem_map_regions *cmd = NULL;
  302. struct avs_shared_map_region_payload *mregions = NULL;
  303. struct q6asm *a = dev_get_drvdata(ac->dev->parent);
  304. struct audio_port_data *port = NULL;
  305. struct audio_buffer *ab = NULL;
  306. struct apr_pkt *pkt;
  307. void *p;
  308. unsigned long flags;
  309. uint32_t num_regions, buf_sz;
  310. int rc, i, pkt_size;
  311. if (is_contiguous) {
  312. num_regions = 1;
  313. buf_sz = period_sz * periods;
  314. } else {
  315. buf_sz = period_sz;
  316. num_regions = periods;
  317. }
  318. /* DSP expects size should be aligned to 4K */
  319. buf_sz = ALIGN(buf_sz, 4096);
  320. pkt_size = APR_HDR_SIZE + sizeof(*cmd) +
  321. (sizeof(*mregions) * num_regions);
  322. p = kzalloc(pkt_size, GFP_KERNEL);
  323. if (!p)
  324. return -ENOMEM;
  325. pkt = p;
  326. cmd = p + APR_HDR_SIZE;
  327. mregions = p + APR_HDR_SIZE + sizeof(*cmd);
  328. pkt->hdr.hdr_field = APR_SEQ_CMD_HDR_FIELD;
  329. pkt->hdr.src_port = 0;
  330. pkt->hdr.dest_port = 0;
  331. pkt->hdr.pkt_size = pkt_size;
  332. pkt->hdr.token = ((ac->session << 8) | dir);
  333. pkt->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
  334. cmd->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
  335. cmd->num_regions = num_regions;
  336. cmd->property_flag = 0x00;
  337. spin_lock_irqsave(&ac->lock, flags);
  338. port = &ac->port[dir];
  339. for (i = 0; i < num_regions; i++) {
  340. ab = &port->buf[i];
  341. mregions->shm_addr_lsw = lower_32_bits(ab->phys);
  342. mregions->shm_addr_msw = upper_32_bits(ab->phys);
  343. mregions->mem_size_bytes = buf_sz;
  344. ++mregions;
  345. }
  346. spin_unlock_irqrestore(&ac->lock, flags);
  347. rc = q6asm_apr_send_session_pkt(a, ac, pkt,
  348. ASM_CMDRSP_SHARED_MEM_MAP_REGIONS);
  349. kfree(pkt);
  350. return rc;
  351. }
  352. /**
  353. * q6asm_map_memory_regions() - map memory regions in the dsp.
  354. *
  355. * @dir: direction of audio stream
  356. * @ac: audio client instanace
  357. * @phys: physcial address that needs mapping.
  358. * @period_sz: audio period size
  359. * @periods: number of periods
  360. *
  361. * Return: Will be an negative value on failure or zero on success
  362. */
  363. int q6asm_map_memory_regions(unsigned int dir, struct audio_client *ac,
  364. phys_addr_t phys,
  365. size_t period_sz, unsigned int periods)
  366. {
  367. struct audio_buffer *buf;
  368. unsigned long flags;
  369. int cnt;
  370. int rc;
  371. spin_lock_irqsave(&ac->lock, flags);
  372. if (ac->port[dir].buf) {
  373. dev_err(ac->dev, "Buffer already allocated\n");
  374. spin_unlock_irqrestore(&ac->lock, flags);
  375. return 0;
  376. }
  377. buf = kzalloc(((sizeof(struct audio_buffer)) * periods), GFP_ATOMIC);
  378. if (!buf) {
  379. spin_unlock_irqrestore(&ac->lock, flags);
  380. return -ENOMEM;
  381. }
  382. ac->port[dir].buf = buf;
  383. buf[0].phys = phys;
  384. buf[0].size = period_sz;
  385. for (cnt = 1; cnt < periods; cnt++) {
  386. if (period_sz > 0) {
  387. buf[cnt].phys = buf[0].phys + (cnt * period_sz);
  388. buf[cnt].size = period_sz;
  389. }
  390. }
  391. ac->port[dir].num_periods = periods;
  392. spin_unlock_irqrestore(&ac->lock, flags);
  393. rc = __q6asm_memory_map_regions(ac, dir, period_sz, periods, 1);
  394. if (rc < 0) {
  395. dev_err(ac->dev, "Memory_map_regions failed\n");
  396. q6asm_audio_client_free_buf(ac, &ac->port[dir]);
  397. }
  398. return rc;
  399. }
  400. EXPORT_SYMBOL_GPL(q6asm_map_memory_regions);
  401. static void q6asm_audio_client_release(struct kref *ref)
  402. {
  403. struct audio_client *ac;
  404. struct q6asm *a;
  405. unsigned long flags;
  406. ac = container_of(ref, struct audio_client, refcount);
  407. a = ac->q6asm;
  408. spin_lock_irqsave(&a->slock, flags);
  409. a->session[ac->session] = NULL;
  410. spin_unlock_irqrestore(&a->slock, flags);
  411. kfree(ac);
  412. }
  413. /**
  414. * q6asm_audio_client_free() - Freee allocated audio client
  415. *
  416. * @ac: audio client to free
  417. */
  418. void q6asm_audio_client_free(struct audio_client *ac)
  419. {
  420. kref_put(&ac->refcount, q6asm_audio_client_release);
  421. }
  422. EXPORT_SYMBOL_GPL(q6asm_audio_client_free);
  423. static struct audio_client *q6asm_get_audio_client(struct q6asm *a,
  424. int session_id)
  425. {
  426. struct audio_client *ac = NULL;
  427. unsigned long flags;
  428. spin_lock_irqsave(&a->slock, flags);
  429. if ((session_id <= 0) || (session_id > MAX_SESSIONS)) {
  430. dev_err(a->dev, "invalid session: %d\n", session_id);
  431. goto err;
  432. }
  433. /* check for valid session */
  434. if (!a->session[session_id])
  435. goto err;
  436. else if (a->session[session_id]->session != session_id)
  437. goto err;
  438. ac = a->session[session_id];
  439. kref_get(&ac->refcount);
  440. err:
  441. spin_unlock_irqrestore(&a->slock, flags);
  442. return ac;
  443. }
  444. static int32_t q6asm_stream_callback(struct apr_device *adev,
  445. struct apr_resp_pkt *data,
  446. int session_id)
  447. {
  448. struct q6asm *q6asm = dev_get_drvdata(&adev->dev);
  449. struct aprv2_ibasic_rsp_result_t *result;
  450. struct apr_hdr *hdr = &data->hdr;
  451. struct audio_port_data *port;
  452. struct audio_client *ac;
  453. uint32_t client_event = 0;
  454. int ret = 0;
  455. ac = q6asm_get_audio_client(q6asm, session_id);
  456. if (!ac)/* Audio client might already be freed by now */
  457. return 0;
  458. result = data->payload;
  459. switch (hdr->opcode) {
  460. case APR_BASIC_RSP_RESULT:
  461. switch (result->opcode) {
  462. case ASM_SESSION_CMD_PAUSE:
  463. client_event = ASM_CLIENT_EVENT_CMD_PAUSE_DONE;
  464. break;
  465. case ASM_SESSION_CMD_SUSPEND:
  466. client_event = ASM_CLIENT_EVENT_CMD_SUSPEND_DONE;
  467. break;
  468. case ASM_STREAM_CMD_FLUSH:
  469. client_event = ASM_CLIENT_EVENT_CMD_FLUSH_DONE;
  470. break;
  471. case ASM_SESSION_CMD_RUN_V2:
  472. client_event = ASM_CLIENT_EVENT_CMD_RUN_DONE;
  473. break;
  474. case ASM_STREAM_CMD_CLOSE:
  475. client_event = ASM_CLIENT_EVENT_CMD_CLOSE_DONE;
  476. break;
  477. case ASM_STREAM_CMD_FLUSH_READBUFS:
  478. client_event = ASM_CLIENT_EVENT_CMD_OUT_FLUSH_DONE;
  479. break;
  480. case ASM_STREAM_CMD_OPEN_WRITE_V3:
  481. case ASM_STREAM_CMD_OPEN_READ_V3:
  482. case ASM_STREAM_CMD_OPEN_READWRITE_V2:
  483. case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
  484. case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
  485. if (result->status != 0) {
  486. dev_err(ac->dev,
  487. "cmd = 0x%x returned error = 0x%x\n",
  488. result->opcode, result->status);
  489. ac->result = *result;
  490. wake_up(&ac->cmd_wait);
  491. ret = 0;
  492. goto done;
  493. }
  494. break;
  495. default:
  496. dev_err(ac->dev, "command[0x%x] not expecting rsp\n",
  497. result->opcode);
  498. break;
  499. }
  500. ac->result = *result;
  501. wake_up(&ac->cmd_wait);
  502. if (ac->cb)
  503. ac->cb(client_event, hdr->token,
  504. data->payload, ac->priv);
  505. ret = 0;
  506. goto done;
  507. case ASM_DATA_EVENT_WRITE_DONE_V2:
  508. client_event = ASM_CLIENT_EVENT_DATA_WRITE_DONE;
  509. if (ac->io_mode & ASM_SYNC_IO_MODE) {
  510. phys_addr_t phys;
  511. unsigned long flags;
  512. spin_lock_irqsave(&ac->lock, flags);
  513. port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK];
  514. if (!port->buf) {
  515. spin_unlock_irqrestore(&ac->lock, flags);
  516. ret = 0;
  517. goto done;
  518. }
  519. phys = port->buf[hdr->token].phys;
  520. if (lower_32_bits(phys) != result->opcode ||
  521. upper_32_bits(phys) != result->status) {
  522. dev_err(ac->dev, "Expected addr %pa\n",
  523. &port->buf[hdr->token].phys);
  524. spin_unlock_irqrestore(&ac->lock, flags);
  525. ret = -EINVAL;
  526. goto done;
  527. }
  528. spin_unlock_irqrestore(&ac->lock, flags);
  529. }
  530. break;
  531. case ASM_DATA_EVENT_READ_DONE_V2:
  532. client_event = ASM_CLIENT_EVENT_DATA_READ_DONE;
  533. if (ac->io_mode & ASM_SYNC_IO_MODE) {
  534. struct asm_data_cmd_read_v2_done *done = data->payload;
  535. unsigned long flags;
  536. phys_addr_t phys;
  537. spin_lock_irqsave(&ac->lock, flags);
  538. port = &ac->port[SNDRV_PCM_STREAM_CAPTURE];
  539. if (!port->buf) {
  540. spin_unlock_irqrestore(&ac->lock, flags);
  541. ret = 0;
  542. goto done;
  543. }
  544. phys = port->buf[hdr->token].phys;
  545. if (upper_32_bits(phys) != done->buf_addr_msw ||
  546. lower_32_bits(phys) != done->buf_addr_lsw) {
  547. dev_err(ac->dev, "Expected addr %pa %08x-%08x\n",
  548. &port->buf[hdr->token].phys,
  549. done->buf_addr_lsw,
  550. done->buf_addr_msw);
  551. spin_unlock_irqrestore(&ac->lock, flags);
  552. ret = -EINVAL;
  553. goto done;
  554. }
  555. spin_unlock_irqrestore(&ac->lock, flags);
  556. }
  557. break;
  558. case ASM_DATA_EVENT_RENDERED_EOS:
  559. client_event = ASM_CLIENT_EVENT_CMD_EOS_DONE;
  560. break;
  561. }
  562. if (ac->cb)
  563. ac->cb(client_event, hdr->token, data->payload, ac->priv);
  564. done:
  565. kref_put(&ac->refcount, q6asm_audio_client_release);
  566. return ret;
  567. }
  568. static int q6asm_srvc_callback(struct apr_device *adev,
  569. struct apr_resp_pkt *data)
  570. {
  571. struct q6asm *q6asm = dev_get_drvdata(&adev->dev);
  572. struct aprv2_ibasic_rsp_result_t *result;
  573. struct audio_port_data *port;
  574. struct audio_client *ac = NULL;
  575. struct apr_hdr *hdr = &data->hdr;
  576. struct q6asm *a;
  577. uint32_t sid = 0;
  578. uint32_t dir = 0;
  579. int session_id;
  580. session_id = (hdr->dest_port >> 8) & 0xFF;
  581. if (session_id)
  582. return q6asm_stream_callback(adev, data, session_id);
  583. sid = (hdr->token >> 8) & 0x0F;
  584. ac = q6asm_get_audio_client(q6asm, sid);
  585. if (!ac) {
  586. dev_err(&adev->dev, "Audio Client not active\n");
  587. return 0;
  588. }
  589. a = dev_get_drvdata(ac->dev->parent);
  590. dir = (hdr->token & 0x0F);
  591. port = &ac->port[dir];
  592. result = data->payload;
  593. switch (hdr->opcode) {
  594. case APR_BASIC_RSP_RESULT:
  595. switch (result->opcode) {
  596. case ASM_CMD_SHARED_MEM_MAP_REGIONS:
  597. case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:
  598. ac->result = *result;
  599. wake_up(&a->mem_wait);
  600. break;
  601. default:
  602. dev_err(&adev->dev, "command[0x%x] not expecting rsp\n",
  603. result->opcode);
  604. break;
  605. }
  606. goto done;
  607. case ASM_CMDRSP_SHARED_MEM_MAP_REGIONS:
  608. ac->result.status = 0;
  609. ac->result.opcode = hdr->opcode;
  610. port->mem_map_handle = result->opcode;
  611. wake_up(&a->mem_wait);
  612. break;
  613. case ASM_CMD_SHARED_MEM_UNMAP_REGIONS:
  614. ac->result.opcode = hdr->opcode;
  615. ac->result.status = 0;
  616. port->mem_map_handle = 0;
  617. wake_up(&a->mem_wait);
  618. break;
  619. default:
  620. dev_dbg(&adev->dev, "command[0x%x]success [0x%x]\n",
  621. result->opcode, result->status);
  622. break;
  623. }
  624. if (ac->cb)
  625. ac->cb(hdr->opcode, hdr->token, data->payload, ac->priv);
  626. done:
  627. kref_put(&ac->refcount, q6asm_audio_client_release);
  628. return 0;
  629. }
  630. /**
  631. * q6asm_get_session_id() - get session id for audio client
  632. *
  633. * @c: audio client pointer
  634. *
  635. * Return: Will be an session id of the audio client.
  636. */
  637. int q6asm_get_session_id(struct audio_client *c)
  638. {
  639. return c->session;
  640. }
  641. EXPORT_SYMBOL_GPL(q6asm_get_session_id);
  642. /**
  643. * q6asm_audio_client_alloc() - Allocate a new audio client
  644. *
  645. * @dev: Pointer to asm child device.
  646. * @cb: event callback.
  647. * @priv: private data associated with this client.
  648. * @stream_id: stream id
  649. * @perf_mode: performace mode for this client
  650. *
  651. * Return: Will be an error pointer on error or a valid audio client
  652. * on success.
  653. */
  654. struct audio_client *q6asm_audio_client_alloc(struct device *dev, q6asm_cb cb,
  655. void *priv, int stream_id,
  656. int perf_mode)
  657. {
  658. struct q6asm *a = dev_get_drvdata(dev->parent);
  659. struct audio_client *ac;
  660. unsigned long flags;
  661. ac = q6asm_get_audio_client(a, stream_id + 1);
  662. if (ac) {
  663. dev_err(dev, "Audio Client already active\n");
  664. return ac;
  665. }
  666. ac = kzalloc(sizeof(*ac), GFP_KERNEL);
  667. if (!ac)
  668. return ERR_PTR(-ENOMEM);
  669. spin_lock_irqsave(&a->slock, flags);
  670. a->session[stream_id + 1] = ac;
  671. spin_unlock_irqrestore(&a->slock, flags);
  672. ac->session = stream_id + 1;
  673. ac->cb = cb;
  674. ac->dev = dev;
  675. ac->q6asm = a;
  676. ac->priv = priv;
  677. ac->io_mode = ASM_SYNC_IO_MODE;
  678. ac->perf_mode = perf_mode;
  679. /* DSP expects stream id from 1 */
  680. ac->stream_id = 1;
  681. ac->adev = a->adev;
  682. kref_init(&ac->refcount);
  683. init_waitqueue_head(&ac->cmd_wait);
  684. mutex_init(&ac->cmd_lock);
  685. spin_lock_init(&ac->lock);
  686. return ac;
  687. }
  688. EXPORT_SYMBOL_GPL(q6asm_audio_client_alloc);
  689. static int q6asm_ac_send_cmd_sync(struct audio_client *ac, struct apr_pkt *pkt)
  690. {
  691. struct apr_hdr *hdr = &pkt->hdr;
  692. int rc;
  693. mutex_lock(&ac->cmd_lock);
  694. ac->result.opcode = 0;
  695. ac->result.status = 0;
  696. rc = apr_send_pkt(ac->adev, pkt);
  697. if (rc < 0)
  698. goto err;
  699. rc = wait_event_timeout(ac->cmd_wait,
  700. (ac->result.opcode == hdr->opcode), 5 * HZ);
  701. if (!rc) {
  702. dev_err(ac->dev, "CMD timeout\n");
  703. rc = -ETIMEDOUT;
  704. goto err;
  705. }
  706. if (ac->result.status > 0) {
  707. dev_err(ac->dev, "DSP returned error[%x]\n",
  708. ac->result.status);
  709. rc = -EINVAL;
  710. } else {
  711. rc = 0;
  712. }
  713. err:
  714. mutex_unlock(&ac->cmd_lock);
  715. return rc;
  716. }
  717. /**
  718. * q6asm_open_write() - Open audio client for writing
  719. *
  720. * @ac: audio client pointer
  721. * @format: audio sample format
  722. * @bits_per_sample: bits per sample
  723. *
  724. * Return: Will be an negative value on error or zero on success
  725. */
  726. int q6asm_open_write(struct audio_client *ac, uint32_t format,
  727. uint16_t bits_per_sample)
  728. {
  729. struct asm_stream_cmd_open_write_v3 *open;
  730. struct apr_pkt *pkt;
  731. void *p;
  732. int rc, pkt_size;
  733. pkt_size = APR_HDR_SIZE + sizeof(*open);
  734. p = kzalloc(pkt_size, GFP_KERNEL);
  735. if (!p)
  736. return -ENOMEM;
  737. pkt = p;
  738. open = p + APR_HDR_SIZE;
  739. q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id);
  740. pkt->hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_V3;
  741. open->mode_flags = 0x00;
  742. open->mode_flags |= ASM_LEGACY_STREAM_SESSION;
  743. /* source endpoint : matrix */
  744. open->sink_endpointype = ASM_END_POINT_DEVICE_MATRIX;
  745. open->bits_per_sample = bits_per_sample;
  746. open->postprocopo_id = ASM_NULL_POPP_TOPOLOGY;
  747. switch (format) {
  748. case FORMAT_LINEAR_PCM:
  749. open->dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
  750. break;
  751. default:
  752. dev_err(ac->dev, "Invalid format 0x%x\n", format);
  753. rc = -EINVAL;
  754. goto err;
  755. }
  756. rc = q6asm_ac_send_cmd_sync(ac, pkt);
  757. if (rc < 0)
  758. goto err;
  759. ac->io_mode |= ASM_TUN_WRITE_IO_MODE;
  760. err:
  761. kfree(pkt);
  762. return rc;
  763. }
  764. EXPORT_SYMBOL_GPL(q6asm_open_write);
  765. static int __q6asm_run(struct audio_client *ac, uint32_t flags,
  766. uint32_t msw_ts, uint32_t lsw_ts, bool wait)
  767. {
  768. struct asm_session_cmd_run_v2 *run;
  769. struct apr_pkt *pkt;
  770. int pkt_size, rc;
  771. void *p;
  772. pkt_size = APR_HDR_SIZE + sizeof(*run);
  773. p = kzalloc(pkt_size, GFP_ATOMIC);
  774. if (!p)
  775. return -ENOMEM;
  776. pkt = p;
  777. run = p + APR_HDR_SIZE;
  778. q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id);
  779. pkt->hdr.opcode = ASM_SESSION_CMD_RUN_V2;
  780. run->flags = flags;
  781. run->time_lsw = lsw_ts;
  782. run->time_msw = msw_ts;
  783. if (wait) {
  784. rc = q6asm_ac_send_cmd_sync(ac, pkt);
  785. } else {
  786. rc = apr_send_pkt(ac->adev, pkt);
  787. if (rc == pkt_size)
  788. rc = 0;
  789. }
  790. kfree(pkt);
  791. return rc;
  792. }
  793. /**
  794. * q6asm_run() - start the audio client
  795. *
  796. * @ac: audio client pointer
  797. * @flags: flags associated with write
  798. * @msw_ts: timestamp msw
  799. * @lsw_ts: timestamp lsw
  800. *
  801. * Return: Will be an negative value on error or zero on success
  802. */
  803. int q6asm_run(struct audio_client *ac, uint32_t flags,
  804. uint32_t msw_ts, uint32_t lsw_ts)
  805. {
  806. return __q6asm_run(ac, flags, msw_ts, lsw_ts, true);
  807. }
  808. EXPORT_SYMBOL_GPL(q6asm_run);
  809. /**
  810. * q6asm_run_nowait() - start the audio client withou blocking
  811. *
  812. * @ac: audio client pointer
  813. * @flags: flags associated with write
  814. * @msw_ts: timestamp msw
  815. * @lsw_ts: timestamp lsw
  816. *
  817. * Return: Will be an negative value on error or zero on success
  818. */
  819. int q6asm_run_nowait(struct audio_client *ac, uint32_t flags,
  820. uint32_t msw_ts, uint32_t lsw_ts)
  821. {
  822. return __q6asm_run(ac, flags, msw_ts, lsw_ts, false);
  823. }
  824. EXPORT_SYMBOL_GPL(q6asm_run_nowait);
  825. /**
  826. * q6asm_media_format_block_multi_ch_pcm() - setup pcm configuration
  827. *
  828. * @ac: audio client pointer
  829. * @rate: audio sample rate
  830. * @channels: number of audio channels.
  831. * @channel_map: channel map pointer
  832. * @bits_per_sample: bits per sample
  833. *
  834. * Return: Will be an negative value on error or zero on success
  835. */
  836. int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
  837. uint32_t rate, uint32_t channels,
  838. u8 channel_map[PCM_MAX_NUM_CHANNEL],
  839. uint16_t bits_per_sample)
  840. {
  841. struct asm_multi_channel_pcm_fmt_blk_v2 *fmt;
  842. struct apr_pkt *pkt;
  843. u8 *channel_mapping;
  844. void *p;
  845. int rc, pkt_size;
  846. pkt_size = APR_HDR_SIZE + sizeof(*fmt);
  847. p = kzalloc(pkt_size, GFP_KERNEL);
  848. if (!p)
  849. return -ENOMEM;
  850. pkt = p;
  851. fmt = p + APR_HDR_SIZE;
  852. q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id);
  853. pkt->hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
  854. fmt->fmt_blk.fmt_blk_size = sizeof(*fmt) - sizeof(fmt->fmt_blk);
  855. fmt->num_channels = channels;
  856. fmt->bits_per_sample = bits_per_sample;
  857. fmt->sample_rate = rate;
  858. fmt->is_signed = 1;
  859. channel_mapping = fmt->channel_mapping;
  860. if (channel_map) {
  861. memcpy(channel_mapping, channel_map, PCM_MAX_NUM_CHANNEL);
  862. } else {
  863. if (q6dsp_map_channels(channel_mapping, channels)) {
  864. dev_err(ac->dev, " map channels failed %d\n", channels);
  865. rc = -EINVAL;
  866. goto err;
  867. }
  868. }
  869. rc = q6asm_ac_send_cmd_sync(ac, pkt);
  870. err:
  871. kfree(pkt);
  872. return rc;
  873. }
  874. EXPORT_SYMBOL_GPL(q6asm_media_format_block_multi_ch_pcm);
  875. /**
  876. * q6asm_enc_cfg_blk_pcm_format_support() - setup pcm configuration for capture
  877. *
  878. * @ac: audio client pointer
  879. * @rate: audio sample rate
  880. * @channels: number of audio channels.
  881. * @bits_per_sample: bits per sample
  882. *
  883. * Return: Will be an negative value on error or zero on success
  884. */
  885. int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac,
  886. uint32_t rate, uint32_t channels, uint16_t bits_per_sample)
  887. {
  888. struct asm_multi_channel_pcm_enc_cfg_v2 *enc_cfg;
  889. struct apr_pkt *pkt;
  890. u8 *channel_mapping;
  891. u32 frames_per_buf = 0;
  892. int pkt_size, rc;
  893. void *p;
  894. pkt_size = APR_HDR_SIZE + sizeof(*enc_cfg);
  895. p = kzalloc(pkt_size, GFP_KERNEL);
  896. if (!p)
  897. return -ENOMEM;
  898. pkt = p;
  899. enc_cfg = p + APR_HDR_SIZE;
  900. q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id);
  901. pkt->hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
  902. enc_cfg->encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2;
  903. enc_cfg->encdec.param_size = sizeof(*enc_cfg) - sizeof(enc_cfg->encdec);
  904. enc_cfg->encblk.frames_per_buf = frames_per_buf;
  905. enc_cfg->encblk.enc_cfg_blk_size = enc_cfg->encdec.param_size -
  906. sizeof(struct asm_enc_cfg_blk_param_v2);
  907. enc_cfg->num_channels = channels;
  908. enc_cfg->bits_per_sample = bits_per_sample;
  909. enc_cfg->sample_rate = rate;
  910. enc_cfg->is_signed = 1;
  911. channel_mapping = enc_cfg->channel_mapping;
  912. if (q6dsp_map_channels(channel_mapping, channels)) {
  913. rc = -EINVAL;
  914. goto err;
  915. }
  916. rc = q6asm_ac_send_cmd_sync(ac, pkt);
  917. err:
  918. kfree(pkt);
  919. return rc;
  920. }
  921. EXPORT_SYMBOL_GPL(q6asm_enc_cfg_blk_pcm_format_support);
  922. /**
  923. * q6asm_read() - read data of period size from audio client
  924. *
  925. * @ac: audio client pointer
  926. *
  927. * Return: Will be an negative value on error or zero on success
  928. */
  929. int q6asm_read(struct audio_client *ac)
  930. {
  931. struct asm_data_cmd_read_v2 *read;
  932. struct audio_port_data *port;
  933. struct audio_buffer *ab;
  934. struct apr_pkt *pkt;
  935. unsigned long flags;
  936. int pkt_size;
  937. int rc = 0;
  938. void *p;
  939. pkt_size = APR_HDR_SIZE + sizeof(*read);
  940. p = kzalloc(pkt_size, GFP_ATOMIC);
  941. if (!p)
  942. return -ENOMEM;
  943. pkt = p;
  944. read = p + APR_HDR_SIZE;
  945. spin_lock_irqsave(&ac->lock, flags);
  946. port = &ac->port[SNDRV_PCM_STREAM_CAPTURE];
  947. q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, ac->stream_id);
  948. ab = &port->buf[port->dsp_buf];
  949. pkt->hdr.opcode = ASM_DATA_CMD_READ_V2;
  950. read->buf_addr_lsw = lower_32_bits(ab->phys);
  951. read->buf_addr_msw = upper_32_bits(ab->phys);
  952. read->mem_map_handle = port->mem_map_handle;
  953. read->buf_size = ab->size;
  954. read->seq_id = port->dsp_buf;
  955. pkt->hdr.token = port->dsp_buf;
  956. port->dsp_buf++;
  957. if (port->dsp_buf >= port->num_periods)
  958. port->dsp_buf = 0;
  959. spin_unlock_irqrestore(&ac->lock, flags);
  960. rc = apr_send_pkt(ac->adev, pkt);
  961. if (rc == pkt_size)
  962. rc = 0;
  963. else
  964. pr_err("read op[0x%x]rc[%d]\n", pkt->hdr.opcode, rc);
  965. kfree(pkt);
  966. return rc;
  967. }
  968. EXPORT_SYMBOL_GPL(q6asm_read);
  969. static int __q6asm_open_read(struct audio_client *ac,
  970. uint32_t format, uint16_t bits_per_sample)
  971. {
  972. struct asm_stream_cmd_open_read_v3 *open;
  973. struct apr_pkt *pkt;
  974. int pkt_size, rc;
  975. void *p;
  976. pkt_size = APR_HDR_SIZE + sizeof(*open);
  977. p = kzalloc(pkt_size, GFP_KERNEL);
  978. if (!p)
  979. return -ENOMEM;
  980. pkt = p;
  981. open = p + APR_HDR_SIZE;
  982. q6asm_add_hdr(ac, &pkt->hdr, pkt_size, true, ac->stream_id);
  983. pkt->hdr.opcode = ASM_STREAM_CMD_OPEN_READ_V3;
  984. /* Stream prio : High, provide meta info with encoded frames */
  985. open->src_endpointype = ASM_END_POINT_DEVICE_MATRIX;
  986. open->preprocopo_id = ASM_STREAM_POSTPROC_TOPO_ID_NONE;
  987. open->bits_per_sample = bits_per_sample;
  988. open->mode_flags = 0x0;
  989. open->mode_flags |= ASM_LEGACY_STREAM_SESSION <<
  990. ASM_SHIFT_STREAM_PERF_MODE_FLAG_IN_OPEN_READ;
  991. switch (format) {
  992. case FORMAT_LINEAR_PCM:
  993. open->mode_flags |= 0x00;
  994. open->enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2;
  995. break;
  996. default:
  997. pr_err("Invalid format[%d]\n", format);
  998. }
  999. rc = q6asm_ac_send_cmd_sync(ac, pkt);
  1000. kfree(pkt);
  1001. return rc;
  1002. }
  1003. /**
  1004. * q6asm_open_read() - Open audio client for reading
  1005. *
  1006. * @ac: audio client pointer
  1007. * @format: audio sample format
  1008. * @bits_per_sample: bits per sample
  1009. *
  1010. * Return: Will be an negative value on error or zero on success
  1011. */
  1012. int q6asm_open_read(struct audio_client *ac, uint32_t format,
  1013. uint16_t bits_per_sample)
  1014. {
  1015. return __q6asm_open_read(ac, format, bits_per_sample);
  1016. }
  1017. EXPORT_SYMBOL_GPL(q6asm_open_read);
  1018. /**
  1019. * q6asm_write_async() - non blocking write
  1020. *
  1021. * @ac: audio client pointer
  1022. * @len: lenght in bytes
  1023. * @msw_ts: timestamp msw
  1024. * @lsw_ts: timestamp lsw
  1025. * @wflags: flags associated with write
  1026. *
  1027. * Return: Will be an negative value on error or zero on success
  1028. */
  1029. int q6asm_write_async(struct audio_client *ac, uint32_t len, uint32_t msw_ts,
  1030. uint32_t lsw_ts, uint32_t wflags)
  1031. {
  1032. struct asm_data_cmd_write_v2 *write;
  1033. struct audio_port_data *port;
  1034. struct audio_buffer *ab;
  1035. unsigned long flags;
  1036. struct apr_pkt *pkt;
  1037. int pkt_size;
  1038. int rc = 0;
  1039. void *p;
  1040. pkt_size = APR_HDR_SIZE + sizeof(*write);
  1041. p = kzalloc(pkt_size, GFP_ATOMIC);
  1042. if (!p)
  1043. return -ENOMEM;
  1044. pkt = p;
  1045. write = p + APR_HDR_SIZE;
  1046. spin_lock_irqsave(&ac->lock, flags);
  1047. port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK];
  1048. q6asm_add_hdr(ac, &pkt->hdr, pkt_size, false, ac->stream_id);
  1049. ab = &port->buf[port->dsp_buf];
  1050. pkt->hdr.token = port->dsp_buf;
  1051. pkt->hdr.opcode = ASM_DATA_CMD_WRITE_V2;
  1052. write->buf_addr_lsw = lower_32_bits(ab->phys);
  1053. write->buf_addr_msw = upper_32_bits(ab->phys);
  1054. write->buf_size = len;
  1055. write->seq_id = port->dsp_buf;
  1056. write->timestamp_lsw = lsw_ts;
  1057. write->timestamp_msw = msw_ts;
  1058. write->mem_map_handle =
  1059. ac->port[SNDRV_PCM_STREAM_PLAYBACK].mem_map_handle;
  1060. if (wflags == NO_TIMESTAMP)
  1061. write->flags = (wflags & 0x800000FF);
  1062. else
  1063. write->flags = (0x80000000 | wflags);
  1064. port->dsp_buf++;
  1065. if (port->dsp_buf >= port->num_periods)
  1066. port->dsp_buf = 0;
  1067. spin_unlock_irqrestore(&ac->lock, flags);
  1068. rc = apr_send_pkt(ac->adev, pkt);
  1069. if (rc == pkt_size)
  1070. rc = 0;
  1071. kfree(pkt);
  1072. return rc;
  1073. }
  1074. EXPORT_SYMBOL_GPL(q6asm_write_async);
  1075. static void q6asm_reset_buf_state(struct audio_client *ac)
  1076. {
  1077. struct audio_port_data *port = NULL;
  1078. unsigned long flags;
  1079. spin_lock_irqsave(&ac->lock, flags);
  1080. port = &ac->port[SNDRV_PCM_STREAM_PLAYBACK];
  1081. port->dsp_buf = 0;
  1082. port = &ac->port[SNDRV_PCM_STREAM_CAPTURE];
  1083. port->dsp_buf = 0;
  1084. spin_unlock_irqrestore(&ac->lock, flags);
  1085. }
  1086. static int __q6asm_cmd(struct audio_client *ac, int cmd, bool wait)
  1087. {
  1088. int stream_id = ac->stream_id;
  1089. struct apr_pkt pkt;
  1090. int rc;
  1091. q6asm_add_hdr(ac, &pkt.hdr, APR_HDR_SIZE, true, stream_id);
  1092. switch (cmd) {
  1093. case CMD_PAUSE:
  1094. pkt.hdr.opcode = ASM_SESSION_CMD_PAUSE;
  1095. break;
  1096. case CMD_SUSPEND:
  1097. pkt.hdr.opcode = ASM_SESSION_CMD_SUSPEND;
  1098. break;
  1099. case CMD_FLUSH:
  1100. pkt.hdr.opcode = ASM_STREAM_CMD_FLUSH;
  1101. break;
  1102. case CMD_OUT_FLUSH:
  1103. pkt.hdr.opcode = ASM_STREAM_CMD_FLUSH_READBUFS;
  1104. break;
  1105. case CMD_EOS:
  1106. pkt.hdr.opcode = ASM_DATA_CMD_EOS;
  1107. break;
  1108. case CMD_CLOSE:
  1109. pkt.hdr.opcode = ASM_STREAM_CMD_CLOSE;
  1110. break;
  1111. default:
  1112. return -EINVAL;
  1113. }
  1114. if (wait)
  1115. rc = q6asm_ac_send_cmd_sync(ac, &pkt);
  1116. else
  1117. return apr_send_pkt(ac->adev, &pkt);
  1118. if (rc < 0)
  1119. return rc;
  1120. if (cmd == CMD_FLUSH)
  1121. q6asm_reset_buf_state(ac);
  1122. return 0;
  1123. }
  1124. /**
  1125. * q6asm_cmd() - run cmd on audio client
  1126. *
  1127. * @ac: audio client pointer
  1128. * @cmd: command to run on audio client.
  1129. *
  1130. * Return: Will be an negative value on error or zero on success
  1131. */
  1132. int q6asm_cmd(struct audio_client *ac, int cmd)
  1133. {
  1134. return __q6asm_cmd(ac, cmd, true);
  1135. }
  1136. EXPORT_SYMBOL_GPL(q6asm_cmd);
  1137. /**
  1138. * q6asm_cmd_nowait() - non blocking, run cmd on audio client
  1139. *
  1140. * @ac: audio client pointer
  1141. * @cmd: command to run on audio client.
  1142. *
  1143. * Return: Will be an negative value on error or zero on success
  1144. */
  1145. int q6asm_cmd_nowait(struct audio_client *ac, int cmd)
  1146. {
  1147. return __q6asm_cmd(ac, cmd, false);
  1148. }
  1149. EXPORT_SYMBOL_GPL(q6asm_cmd_nowait);
  1150. static int q6asm_probe(struct apr_device *adev)
  1151. {
  1152. struct device *dev = &adev->dev;
  1153. struct q6asm *q6asm;
  1154. q6asm = devm_kzalloc(dev, sizeof(*q6asm), GFP_KERNEL);
  1155. if (!q6asm)
  1156. return -ENOMEM;
  1157. q6core_get_svc_api_info(adev->svc_id, &q6asm->ainfo);
  1158. q6asm->dev = dev;
  1159. q6asm->adev = adev;
  1160. init_waitqueue_head(&q6asm->mem_wait);
  1161. spin_lock_init(&q6asm->slock);
  1162. dev_set_drvdata(dev, q6asm);
  1163. return of_platform_populate(dev->of_node, NULL, NULL, dev);
  1164. }
  1165. static int q6asm_remove(struct apr_device *adev)
  1166. {
  1167. of_platform_depopulate(&adev->dev);
  1168. return 0;
  1169. }
  1170. static const struct of_device_id q6asm_device_id[] = {
  1171. { .compatible = "qcom,q6asm" },
  1172. {},
  1173. };
  1174. MODULE_DEVICE_TABLE(of, q6asm_device_id);
  1175. static struct apr_driver qcom_q6asm_driver = {
  1176. .probe = q6asm_probe,
  1177. .remove = q6asm_remove,
  1178. .callback = q6asm_srvc_callback,
  1179. .driver = {
  1180. .name = "qcom-q6asm",
  1181. .of_match_table = of_match_ptr(q6asm_device_id),
  1182. },
  1183. };
  1184. module_apr_driver(qcom_q6asm_driver);
  1185. MODULE_DESCRIPTION("Q6 Audio Stream Manager driver");
  1186. MODULE_LICENSE("GPL v2");