audio_utils.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. /* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/module.h>
  14. #include <linux/fs.h>
  15. #include <linux/miscdevice.h>
  16. #include <linux/uaccess.h>
  17. #include <linux/sched.h>
  18. #include <linux/wait.h>
  19. #include <linux/dma-mapping.h>
  20. #include <linux/slab.h>
  21. #include <linux/atomic.h>
  22. #include <linux/compat.h>
  23. #include <asm/ioctls.h>
  24. #include "audio_utils.h"
  25. /*
  26. * Define maximum buffer size. Below values are chosen considering the higher
  27. * values used among all native drivers.
  28. */
  29. #define MAX_FRAME_SIZE 1536
  30. #define MAX_FRAMES 5
  31. #define META_SIZE (sizeof(struct meta_out_dsp))
  32. #define MAX_BUFFER_SIZE (1 + ((MAX_FRAME_SIZE + META_SIZE) * MAX_FRAMES))
  33. static int audio_in_pause(struct q6audio_in *audio)
  34. {
  35. int rc;
  36. rc = q6asm_cmd(audio->ac, CMD_PAUSE);
  37. if (rc < 0)
  38. pr_err("%s:session id %d: pause cmd failed rc=%d\n", __func__,
  39. audio->ac->session, rc);
  40. return rc;
  41. }
  42. static int audio_in_flush(struct q6audio_in *audio)
  43. {
  44. int rc;
  45. pr_debug("%s:session id %d: flush\n", __func__, audio->ac->session);
  46. /* Flush if session running */
  47. if (audio->enabled) {
  48. /* Implicitly issue a pause to the encoder before flushing */
  49. rc = audio_in_pause(audio);
  50. if (rc < 0) {
  51. pr_err("%s:session id %d: pause cmd failed rc=%d\n",
  52. __func__, audio->ac->session, rc);
  53. return rc;
  54. }
  55. rc = q6asm_cmd(audio->ac, CMD_FLUSH);
  56. if (rc < 0) {
  57. pr_err("%s:session id %d: flush cmd failed rc=%d\n",
  58. __func__, audio->ac->session, rc);
  59. return rc;
  60. }
  61. /* 2nd arg: 0 -> run immediately
  62. * 3rd arg: 0 -> msw_ts,
  63. * 4th arg: 0 ->lsw_ts
  64. */
  65. q6asm_run(audio->ac, 0x00, 0x00, 0x00);
  66. pr_debug("Rerun the session\n");
  67. }
  68. audio->rflush = 1;
  69. audio->wflush = 1;
  70. memset(audio->out_frame_info, 0, sizeof(audio->out_frame_info));
  71. wake_up(&audio->read_wait);
  72. /* get read_lock to ensure no more waiting read thread */
  73. mutex_lock(&audio->read_lock);
  74. audio->rflush = 0;
  75. mutex_unlock(&audio->read_lock);
  76. wake_up(&audio->write_wait);
  77. /* get write_lock to ensure no more waiting write thread */
  78. mutex_lock(&audio->write_lock);
  79. audio->wflush = 0;
  80. mutex_unlock(&audio->write_lock);
  81. pr_debug("%s:session id %d: in_bytes %d\n", __func__,
  82. audio->ac->session, atomic_read(&audio->in_bytes));
  83. pr_debug("%s:session id %d: in_samples %d\n", __func__,
  84. audio->ac->session, atomic_read(&audio->in_samples));
  85. atomic_set(&audio->in_bytes, 0);
  86. atomic_set(&audio->in_samples, 0);
  87. atomic_set(&audio->out_count, 0);
  88. return 0;
  89. }
  90. /* must be called with audio->lock held */
  91. int audio_in_enable(struct q6audio_in *audio)
  92. {
  93. if (audio->enabled)
  94. return 0;
  95. /* 2nd arg: 0 -> run immediately
  96. * 3rd arg: 0 -> msw_ts,
  97. * 4th arg: 0 ->lsw_ts
  98. */
  99. return q6asm_run(audio->ac, 0x00, 0x00, 0x00);
  100. }
  101. /* must be called with audio->lock held */
  102. int audio_in_disable(struct q6audio_in *audio)
  103. {
  104. int rc = 0;
  105. if (!audio->stopped) {
  106. audio->enabled = 0;
  107. audio->opened = 0;
  108. pr_debug("%s:session id %d: inbytes[%d] insamples[%d]\n",
  109. __func__, audio->ac->session,
  110. atomic_read(&audio->in_bytes),
  111. atomic_read(&audio->in_samples));
  112. rc = q6asm_cmd(audio->ac, CMD_CLOSE);
  113. if (rc < 0)
  114. pr_err("%s:session id %d: Failed to close the session rc=%d\n",
  115. __func__, audio->ac->session,
  116. rc);
  117. audio->stopped = 1;
  118. memset(audio->out_frame_info, 0,
  119. sizeof(audio->out_frame_info));
  120. wake_up(&audio->read_wait);
  121. wake_up(&audio->write_wait);
  122. }
  123. pr_debug("%s:session id %d: enabled[%d]\n", __func__,
  124. audio->ac->session, audio->enabled);
  125. return rc;
  126. }
  127. int audio_in_buf_alloc(struct q6audio_in *audio)
  128. {
  129. int rc = 0;
  130. switch (audio->buf_alloc) {
  131. case NO_BUF_ALLOC:
  132. if (audio->feedback == NON_TUNNEL_MODE) {
  133. rc = q6asm_audio_client_buf_alloc(IN,
  134. audio->ac,
  135. ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size),
  136. audio->pcm_cfg.buffer_count);
  137. if (rc < 0) {
  138. pr_err("%s:session id %d: Buffer Alloc failed\n",
  139. __func__,
  140. audio->ac->session);
  141. rc = -ENOMEM;
  142. break;
  143. }
  144. audio->buf_alloc |= BUF_ALLOC_IN;
  145. }
  146. rc = q6asm_audio_client_buf_alloc(OUT, audio->ac,
  147. ALIGN_BUF_SIZE(audio->str_cfg.buffer_size),
  148. audio->str_cfg.buffer_count);
  149. if (rc < 0) {
  150. pr_err("%s:session id %d: Buffer Alloc failed rc=%d\n",
  151. __func__, audio->ac->session, rc);
  152. rc = -ENOMEM;
  153. break;
  154. }
  155. audio->buf_alloc |= BUF_ALLOC_OUT;
  156. break;
  157. case BUF_ALLOC_IN:
  158. rc = q6asm_audio_client_buf_alloc(OUT, audio->ac,
  159. ALIGN_BUF_SIZE(audio->str_cfg.buffer_size),
  160. audio->str_cfg.buffer_count);
  161. if (rc < 0) {
  162. pr_err("%s:session id %d: Buffer Alloc failed rc=%d\n",
  163. __func__, audio->ac->session, rc);
  164. rc = -ENOMEM;
  165. break;
  166. }
  167. audio->buf_alloc |= BUF_ALLOC_OUT;
  168. break;
  169. case BUF_ALLOC_OUT:
  170. if (audio->feedback == NON_TUNNEL_MODE) {
  171. rc = q6asm_audio_client_buf_alloc(IN, audio->ac,
  172. ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size),
  173. audio->pcm_cfg.buffer_count);
  174. if (rc < 0) {
  175. pr_err("%s:session id %d: Buffer Alloc failed\n",
  176. __func__,
  177. audio->ac->session);
  178. rc = -ENOMEM;
  179. break;
  180. }
  181. audio->buf_alloc |= BUF_ALLOC_IN;
  182. }
  183. break;
  184. default:
  185. pr_debug("%s:session id %d: buf[%d]\n", __func__,
  186. audio->ac->session, audio->buf_alloc);
  187. }
  188. return rc;
  189. }
  190. int audio_in_set_config(struct file *file,
  191. struct msm_audio_config *cfg)
  192. {
  193. int rc = 0;
  194. struct q6audio_in *audio = file->private_data;
  195. if (audio->feedback != NON_TUNNEL_MODE) {
  196. pr_err("%s:session id %d: Not sufficient permission to change the record mode\n",
  197. __func__, audio->ac->session);
  198. rc = -EACCES;
  199. goto ret;
  200. }
  201. if ((cfg->buffer_count > PCM_BUF_COUNT) ||
  202. (cfg->buffer_count == 1))
  203. cfg->buffer_count = PCM_BUF_COUNT;
  204. audio->pcm_cfg.buffer_count = cfg->buffer_count;
  205. audio->pcm_cfg.buffer_size = cfg->buffer_size;
  206. audio->pcm_cfg.channel_count = cfg->channel_count;
  207. audio->pcm_cfg.sample_rate = cfg->sample_rate;
  208. if (audio->opened && audio->feedback == NON_TUNNEL_MODE) {
  209. rc = q6asm_audio_client_buf_alloc(IN, audio->ac,
  210. ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size),
  211. audio->pcm_cfg.buffer_count);
  212. if (rc < 0) {
  213. pr_err("%s:session id %d: Buffer Alloc failed\n",
  214. __func__, audio->ac->session);
  215. rc = -ENOMEM;
  216. goto ret;
  217. }
  218. }
  219. audio->buf_alloc |= BUF_ALLOC_IN;
  220. rc = 0;
  221. pr_debug("%s:session id %d: AUDIO_SET_CONFIG %d %d\n", __func__,
  222. audio->ac->session, audio->pcm_cfg.buffer_count,
  223. audio->pcm_cfg.buffer_size);
  224. ret:
  225. return rc;
  226. }
  227. /* ------------------- device --------------------- */
  228. static long audio_in_ioctl_shared(struct file *file,
  229. unsigned int cmd, unsigned long arg)
  230. {
  231. struct q6audio_in *audio = file->private_data;
  232. int rc = 0;
  233. switch (cmd) {
  234. case AUDIO_FLUSH: {
  235. /* Make sure we're stopped and we wake any threads
  236. * that might be blocked holding the read_lock.
  237. * While audio->stopped read threads will always
  238. * exit immediately.
  239. */
  240. rc = audio_in_flush(audio);
  241. if (rc < 0)
  242. pr_err("%s:session id %d: Flush Fail rc=%d\n",
  243. __func__, audio->ac->session, rc);
  244. else { /* Register back the flushed read buffer with DSP */
  245. int cnt = 0;
  246. while (cnt++ < audio->str_cfg.buffer_count)
  247. q6asm_read(audio->ac); /* Push buffer to DSP */
  248. pr_debug("register the read buffer\n");
  249. }
  250. break;
  251. }
  252. case AUDIO_PAUSE: {
  253. pr_debug("%s:session id %d: AUDIO_PAUSE\n", __func__,
  254. audio->ac->session);
  255. if (audio->enabled)
  256. audio_in_pause(audio);
  257. break;
  258. }
  259. case AUDIO_GET_SESSION_ID: {
  260. if (copy_to_user((void *) arg, &audio->ac->session,
  261. sizeof(u16))) {
  262. pr_err("%s: copy_to_user for AUDIO_GET_SESSION_ID failed\n",
  263. __func__);
  264. rc = -EFAULT;
  265. }
  266. break;
  267. }
  268. default:
  269. pr_err("%s: Unknown ioctl cmd = %d", __func__, cmd);
  270. rc = -EINVAL;
  271. }
  272. return rc;
  273. }
  274. long audio_in_ioctl(struct file *file,
  275. unsigned int cmd, unsigned long arg)
  276. {
  277. struct q6audio_in *audio = file->private_data;
  278. int rc = 0;
  279. if (cmd == AUDIO_GET_STATS) {
  280. struct msm_audio_stats stats;
  281. memset(&stats, 0, sizeof(stats));
  282. stats.byte_count = atomic_read(&audio->in_bytes);
  283. stats.sample_count = atomic_read(&audio->in_samples);
  284. if (copy_to_user((void *) arg, &stats, sizeof(stats)))
  285. return -EFAULT;
  286. return rc;
  287. }
  288. mutex_lock(&audio->lock);
  289. switch (cmd) {
  290. case AUDIO_FLUSH:
  291. case AUDIO_PAUSE:
  292. case AUDIO_GET_SESSION_ID:
  293. rc = audio_in_ioctl_shared(file, cmd, arg);
  294. break;
  295. case AUDIO_GET_STREAM_CONFIG: {
  296. struct msm_audio_stream_config cfg;
  297. memset(&cfg, 0, sizeof(cfg));
  298. cfg.buffer_size = audio->str_cfg.buffer_size;
  299. cfg.buffer_count = audio->str_cfg.buffer_count;
  300. if (copy_to_user((void *)arg, &cfg, sizeof(cfg)))
  301. rc = -EFAULT;
  302. pr_debug("%s:session id %d: AUDIO_GET_STREAM_CONFIG %d %d\n",
  303. __func__, audio->ac->session, cfg.buffer_size,
  304. cfg.buffer_count);
  305. break;
  306. }
  307. case AUDIO_SET_STREAM_CONFIG: {
  308. struct msm_audio_stream_config cfg;
  309. if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
  310. pr_err("%s: copy_from_user for AUDIO_SET_STREAM_CONFIG failed\n"
  311. , __func__);
  312. rc = -EFAULT;
  313. break;
  314. }
  315. /* Minimum single frame size,
  316. * but with in maximum frames number
  317. */
  318. if ((cfg.buffer_size < (audio->min_frame_size +
  319. sizeof(struct meta_out_dsp))) ||
  320. (cfg.buffer_count < FRAME_NUM)) {
  321. rc = -EINVAL;
  322. break;
  323. }
  324. if (cfg.buffer_size > MAX_BUFFER_SIZE) {
  325. rc = -EINVAL;
  326. break;
  327. }
  328. audio->str_cfg.buffer_size = cfg.buffer_size;
  329. audio->str_cfg.buffer_count = cfg.buffer_count;
  330. if (audio->opened) {
  331. rc = q6asm_audio_client_buf_alloc(OUT, audio->ac,
  332. ALIGN_BUF_SIZE(audio->str_cfg.buffer_size),
  333. audio->str_cfg.buffer_count);
  334. if (rc < 0) {
  335. pr_err("%s: session id %d: Buffer Alloc failed rc=%d\n",
  336. __func__, audio->ac->session, rc);
  337. rc = -ENOMEM;
  338. break;
  339. }
  340. }
  341. audio->buf_alloc |= BUF_ALLOC_OUT;
  342. rc = 0;
  343. pr_debug("%s:session id %d: AUDIO_SET_STREAM_CONFIG %d %d\n",
  344. __func__, audio->ac->session,
  345. audio->str_cfg.buffer_size,
  346. audio->str_cfg.buffer_count);
  347. break;
  348. }
  349. case AUDIO_SET_BUF_CFG: {
  350. struct msm_audio_buf_cfg cfg;
  351. if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
  352. rc = -EFAULT;
  353. break;
  354. }
  355. if ((audio->feedback == NON_TUNNEL_MODE) &&
  356. !cfg.meta_info_enable) {
  357. rc = -EFAULT;
  358. break;
  359. }
  360. /* Restrict the num of frames per buf to coincide with
  361. * default buf size
  362. */
  363. if (cfg.frames_per_buf > audio->max_frames_per_buf) {
  364. rc = -EFAULT;
  365. break;
  366. }
  367. audio->buf_cfg.meta_info_enable = cfg.meta_info_enable;
  368. audio->buf_cfg.frames_per_buf = cfg.frames_per_buf;
  369. pr_debug("%s:session id %d: Set-buf-cfg: meta[%d] framesperbuf[%d]\n",
  370. __func__,
  371. audio->ac->session, cfg.meta_info_enable,
  372. cfg.frames_per_buf);
  373. break;
  374. }
  375. case AUDIO_GET_BUF_CFG: {
  376. pr_debug("%s:session id %d: Get-buf-cfg: meta[%d] framesperbuf[%d]\n",
  377. __func__,
  378. audio->ac->session, audio->buf_cfg.meta_info_enable,
  379. audio->buf_cfg.frames_per_buf);
  380. if (copy_to_user((void *)arg, &audio->buf_cfg,
  381. sizeof(struct msm_audio_buf_cfg)))
  382. rc = -EFAULT;
  383. break;
  384. }
  385. case AUDIO_GET_CONFIG: {
  386. if (copy_to_user((void *)arg, &audio->pcm_cfg,
  387. sizeof(struct msm_audio_config)))
  388. rc = -EFAULT;
  389. break;
  390. }
  391. case AUDIO_SET_CONFIG: {
  392. struct msm_audio_config cfg;
  393. if (copy_from_user(&cfg, (void *)arg, sizeof(cfg))) {
  394. pr_err("%s: copy_from_user for AUDIO_SET_CONFIG failed\n",
  395. __func__);
  396. rc = -EFAULT;
  397. break;
  398. }
  399. rc = audio_in_set_config(file, &cfg);
  400. break;
  401. }
  402. default:
  403. /* call codec specific ioctl */
  404. rc = audio->enc_ioctl(file, cmd, arg);
  405. }
  406. mutex_unlock(&audio->lock);
  407. return rc;
  408. }
  409. #ifdef CONFIG_COMPAT
  410. struct msm_audio_stats32 {
  411. u32 byte_count;
  412. u32 sample_count;
  413. u32 unused[2];
  414. };
  415. struct msm_audio_stream_config32 {
  416. u32 buffer_size;
  417. u32 buffer_count;
  418. };
  419. struct msm_audio_config32 {
  420. u32 buffer_size;
  421. u32 buffer_count;
  422. u32 channel_count;
  423. u32 sample_rate;
  424. u32 type;
  425. u32 meta_field;
  426. u32 bits;
  427. u32 unused[3];
  428. };
  429. struct msm_audio_buf_cfg32 {
  430. u32 meta_info_enable;
  431. u32 frames_per_buf;
  432. };
  433. enum {
  434. AUDIO_GET_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, 3,
  435. struct msm_audio_config32),
  436. AUDIO_SET_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, 4,
  437. struct msm_audio_config32),
  438. AUDIO_GET_STATS_32 = _IOR(AUDIO_IOCTL_MAGIC, 5,
  439. struct msm_audio_stats32),
  440. AUDIO_SET_STREAM_CONFIG_32 = _IOW(AUDIO_IOCTL_MAGIC, 80,
  441. struct msm_audio_stream_config32),
  442. AUDIO_GET_STREAM_CONFIG_32 = _IOR(AUDIO_IOCTL_MAGIC, 81,
  443. struct msm_audio_stream_config32),
  444. AUDIO_SET_BUF_CFG_32 = _IOW(AUDIO_IOCTL_MAGIC, 94,
  445. struct msm_audio_buf_cfg32),
  446. AUDIO_GET_BUF_CFG_32 = _IOW(AUDIO_IOCTL_MAGIC, 93,
  447. struct msm_audio_buf_cfg32),
  448. };
  449. long audio_in_compat_ioctl(struct file *file,
  450. unsigned int cmd, unsigned long arg)
  451. {
  452. struct q6audio_in *audio = file->private_data;
  453. int rc = 0;
  454. if (cmd == AUDIO_GET_STATS_32) {
  455. struct msm_audio_stats32 stats_32;
  456. memset(&stats_32, 0, sizeof(stats_32));
  457. stats_32.byte_count = atomic_read(&audio->in_bytes);
  458. stats_32.sample_count = atomic_read(&audio->in_samples);
  459. if (copy_to_user((void *) arg, &stats_32, sizeof(stats_32))) {
  460. pr_err("%s: copy_to_user failed for AUDIO_GET_STATS_32\n",
  461. __func__);
  462. return -EFAULT;
  463. }
  464. return rc;
  465. }
  466. mutex_lock(&audio->lock);
  467. switch (cmd) {
  468. case AUDIO_FLUSH:
  469. case AUDIO_PAUSE:
  470. case AUDIO_GET_SESSION_ID:
  471. rc = audio_in_ioctl_shared(file, cmd, arg);
  472. break;
  473. case AUDIO_GET_STREAM_CONFIG_32: {
  474. struct msm_audio_stream_config32 cfg_32;
  475. memset(&cfg_32, 0, sizeof(cfg_32));
  476. cfg_32.buffer_size = audio->str_cfg.buffer_size;
  477. cfg_32.buffer_count = audio->str_cfg.buffer_count;
  478. if (copy_to_user((void *)arg, &cfg_32, sizeof(cfg_32))) {
  479. pr_err("%s: Copy to user failed\n", __func__);
  480. rc = -EFAULT;
  481. }
  482. pr_debug("%s:session id %d: AUDIO_GET_STREAM_CONFIG %d %d\n",
  483. __func__, audio->ac->session,
  484. cfg_32.buffer_size,
  485. cfg_32.buffer_count);
  486. break;
  487. }
  488. case AUDIO_SET_STREAM_CONFIG_32: {
  489. struct msm_audio_stream_config32 cfg_32;
  490. struct msm_audio_stream_config cfg;
  491. if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) {
  492. pr_err("%s: copy_from_user for AUDIO_SET_STREAM_CONFIG_32 failed\n",
  493. __func__);
  494. rc = -EFAULT;
  495. break;
  496. }
  497. cfg.buffer_size = cfg_32.buffer_size;
  498. cfg.buffer_count = cfg_32.buffer_count;
  499. /* Minimum single frame size,
  500. * but with in maximum frames number
  501. */
  502. if ((cfg.buffer_size < (audio->min_frame_size +
  503. sizeof(struct meta_out_dsp))) ||
  504. (cfg.buffer_count < FRAME_NUM)) {
  505. rc = -EINVAL;
  506. break;
  507. }
  508. audio->str_cfg.buffer_size = cfg.buffer_size;
  509. audio->str_cfg.buffer_count = cfg.buffer_count;
  510. if (audio->opened) {
  511. rc = q6asm_audio_client_buf_alloc(OUT, audio->ac,
  512. ALIGN_BUF_SIZE(audio->str_cfg.buffer_size),
  513. audio->str_cfg.buffer_count);
  514. if (rc < 0) {
  515. pr_err("%s: session id %d:\n",
  516. __func__, audio->ac->session);
  517. pr_err("Buffer Alloc failed rc=%d\n", rc);
  518. rc = -ENOMEM;
  519. break;
  520. }
  521. }
  522. audio->buf_alloc |= BUF_ALLOC_OUT;
  523. pr_debug("%s:session id %d: AUDIO_SET_STREAM_CONFIG %d %d\n",
  524. __func__, audio->ac->session,
  525. audio->str_cfg.buffer_size,
  526. audio->str_cfg.buffer_count);
  527. break;
  528. }
  529. case AUDIO_SET_BUF_CFG_32: {
  530. struct msm_audio_buf_cfg32 cfg_32;
  531. struct msm_audio_buf_cfg cfg;
  532. if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) {
  533. pr_err("%s: copy_from_user for AUDIO_SET_BUG_CFG_32 failed",
  534. __func__);
  535. rc = -EFAULT;
  536. break;
  537. }
  538. cfg.meta_info_enable = cfg_32.meta_info_enable;
  539. cfg.frames_per_buf = cfg_32.frames_per_buf;
  540. if ((audio->feedback == NON_TUNNEL_MODE) &&
  541. !cfg.meta_info_enable) {
  542. rc = -EFAULT;
  543. break;
  544. }
  545. /* Restrict the num of frames per buf to coincide with
  546. * default buf size
  547. */
  548. if (cfg.frames_per_buf > audio->max_frames_per_buf) {
  549. rc = -EFAULT;
  550. break;
  551. }
  552. audio->buf_cfg.meta_info_enable = cfg.meta_info_enable;
  553. audio->buf_cfg.frames_per_buf = cfg.frames_per_buf;
  554. pr_debug("%s:session id %d: Set-buf-cfg: meta[%d] framesperbuf[%d]\n",
  555. __func__, audio->ac->session, cfg.meta_info_enable,
  556. cfg.frames_per_buf);
  557. break;
  558. }
  559. case AUDIO_GET_BUF_CFG_32: {
  560. struct msm_audio_buf_cfg32 cfg_32;
  561. pr_debug("%s:session id %d: Get-buf-cfg: meta[%d] framesperbuf[%d]\n",
  562. __func__,
  563. audio->ac->session, audio->buf_cfg.meta_info_enable,
  564. audio->buf_cfg.frames_per_buf);
  565. cfg_32.meta_info_enable = audio->buf_cfg.meta_info_enable;
  566. cfg_32.frames_per_buf = audio->buf_cfg.frames_per_buf;
  567. if (copy_to_user((void *)arg, &cfg_32,
  568. sizeof(struct msm_audio_buf_cfg32))) {
  569. pr_err("%s: Copy to user failed\n", __func__);
  570. rc = -EFAULT;
  571. }
  572. break;
  573. }
  574. case AUDIO_GET_CONFIG_32: {
  575. struct msm_audio_config32 cfg_32;
  576. memset(&cfg_32, 0, sizeof(cfg_32));
  577. cfg_32.buffer_size = audio->pcm_cfg.buffer_size;
  578. cfg_32.buffer_count = audio->pcm_cfg.buffer_count;
  579. cfg_32.channel_count = audio->pcm_cfg.channel_count;
  580. cfg_32.sample_rate = audio->pcm_cfg.sample_rate;
  581. cfg_32.type = audio->pcm_cfg.type;
  582. cfg_32.meta_field = audio->pcm_cfg.meta_field;
  583. cfg_32.bits = audio->pcm_cfg.bits;
  584. if (copy_to_user((void *)arg, &cfg_32,
  585. sizeof(struct msm_audio_config32))) {
  586. pr_err("%s: Copy to user failed\n", __func__);
  587. rc = -EFAULT;
  588. }
  589. break;
  590. }
  591. case AUDIO_SET_CONFIG_32: {
  592. struct msm_audio_config32 cfg_32;
  593. struct msm_audio_config cfg;
  594. if (copy_from_user(&cfg_32, (void *)arg, sizeof(cfg_32))) {
  595. pr_err("%s: copy_from_user for AUDIO_SET_CONFIG_32 failed\n",
  596. __func__);
  597. rc = -EFAULT;
  598. break;
  599. }
  600. cfg.buffer_size = cfg_32.buffer_size;
  601. cfg.buffer_count = cfg_32.buffer_count;
  602. cfg.channel_count = cfg_32.channel_count;
  603. cfg.sample_rate = cfg_32.sample_rate;
  604. cfg.type = cfg_32.type;
  605. cfg.meta_field = cfg_32.meta_field;
  606. cfg.bits = cfg_32.bits;
  607. rc = audio_in_set_config(file, &cfg);
  608. break;
  609. }
  610. default:
  611. /* call codec specific ioctl */
  612. rc = audio->enc_compat_ioctl(file, cmd, arg);
  613. }
  614. mutex_unlock(&audio->lock);
  615. return rc;
  616. }
  617. #endif
  618. ssize_t audio_in_read(struct file *file,
  619. char __user *buf,
  620. size_t count, loff_t *pos)
  621. {
  622. struct q6audio_in *audio = file->private_data;
  623. const char __user *start = buf;
  624. unsigned char *data;
  625. uint32_t offset = 0;
  626. uint32_t size = 0;
  627. int rc = 0;
  628. uint32_t idx;
  629. struct meta_out_dsp meta;
  630. uint32_t bytes_to_copy = 0;
  631. uint32_t mfield_size = (audio->buf_cfg.meta_info_enable == 0) ? 0 :
  632. (sizeof(unsigned char) +
  633. (sizeof(struct meta_out_dsp)*(audio->buf_cfg.frames_per_buf)));
  634. memset(&meta, 0, sizeof(meta));
  635. pr_debug("%s:session id %d: read - %zd\n", __func__, audio->ac->session,
  636. count);
  637. if (audio->reset_event)
  638. return -ENETRESET;
  639. if (!audio->enabled)
  640. return -EFAULT;
  641. mutex_lock(&audio->read_lock);
  642. while (count > 0) {
  643. rc = wait_event_interruptible(
  644. audio->read_wait,
  645. ((atomic_read(&audio->out_count) > 0) ||
  646. (audio->stopped) ||
  647. audio->rflush || audio->eos_rsp ||
  648. audio->event_abort));
  649. if (audio->event_abort) {
  650. rc = -EIO;
  651. break;
  652. }
  653. if (rc < 0)
  654. break;
  655. if ((audio->stopped && !(atomic_read(&audio->out_count))) ||
  656. audio->rflush) {
  657. pr_debug("%s:session id %d: driver in stop state or flush,No more buf to read",
  658. __func__,
  659. audio->ac->session);
  660. rc = 0;/* End of File */
  661. break;
  662. }
  663. if (!(atomic_read(&audio->out_count)) &&
  664. (audio->eos_rsp == 1) &&
  665. (count >= (sizeof(unsigned char) +
  666. sizeof(struct meta_out_dsp)))) {
  667. unsigned char num_of_frames;
  668. pr_info("%s:session id %d: eos %d at output\n",
  669. __func__, audio->ac->session, audio->eos_rsp);
  670. if (buf != start)
  671. break;
  672. num_of_frames = 0xFF;
  673. if (copy_to_user(buf, &num_of_frames,
  674. sizeof(unsigned char))) {
  675. rc = -EFAULT;
  676. break;
  677. }
  678. buf += sizeof(unsigned char);
  679. meta.frame_size = 0xFFFF;
  680. meta.encoded_pcm_samples = 0xFFFF;
  681. meta.msw_ts = 0x00;
  682. meta.lsw_ts = 0x00;
  683. meta.nflags = AUD_EOS_SET;
  684. audio->eos_rsp = 0;
  685. if (copy_to_user(buf, &meta, sizeof(meta))) {
  686. rc = -EFAULT;
  687. break;
  688. }
  689. buf += sizeof(meta);
  690. break;
  691. }
  692. data = (unsigned char *)q6asm_is_cpu_buf_avail(OUT, audio->ac,
  693. &size, &idx);
  694. if ((count >= (size + mfield_size)) && data) {
  695. if (audio->buf_cfg.meta_info_enable) {
  696. if (copy_to_user(buf,
  697. &audio->out_frame_info[idx][0],
  698. sizeof(unsigned char))) {
  699. rc = -EFAULT;
  700. break;
  701. }
  702. bytes_to_copy =
  703. (size + audio->out_frame_info[idx][1]);
  704. /* Number of frames information copied */
  705. buf += sizeof(unsigned char);
  706. count -= sizeof(unsigned char);
  707. } else {
  708. offset = audio->out_frame_info[idx][1];
  709. bytes_to_copy = size;
  710. }
  711. pr_debug("%s:session id %d: offset=%d nr of frames= %d\n",
  712. __func__, audio->ac->session,
  713. audio->out_frame_info[idx][1],
  714. audio->out_frame_info[idx][0]);
  715. if (copy_to_user(buf, &data[offset], bytes_to_copy)) {
  716. rc = -EFAULT;
  717. break;
  718. }
  719. count -= bytes_to_copy;
  720. buf += bytes_to_copy;
  721. } else {
  722. pr_err("%s:session id %d: short read data[%pK] bytesavail[%d]bytesrequest[%zd]\n",
  723. __func__,
  724. audio->ac->session,
  725. data, size, count);
  726. }
  727. atomic_dec(&audio->out_count);
  728. q6asm_read(audio->ac);
  729. break;
  730. }
  731. mutex_unlock(&audio->read_lock);
  732. pr_debug("%s:session id %d: read: %zd bytes\n", __func__,
  733. audio->ac->session, (buf-start));
  734. if (buf > start)
  735. return buf - start;
  736. return rc;
  737. }
  738. static int extract_meta_info(char *buf, unsigned long *msw_ts,
  739. unsigned long *lsw_ts, unsigned int *flags)
  740. {
  741. struct meta_in *meta = (struct meta_in *)buf;
  742. *msw_ts = meta->ntimestamp.highpart;
  743. *lsw_ts = meta->ntimestamp.lowpart;
  744. *flags = meta->nflags;
  745. return 0;
  746. }
  747. ssize_t audio_in_write(struct file *file,
  748. const char __user *buf,
  749. size_t count, loff_t *pos)
  750. {
  751. struct q6audio_in *audio = file->private_data;
  752. const char __user *start = buf;
  753. size_t xfer = 0;
  754. char *cpy_ptr;
  755. int rc = 0;
  756. unsigned char *data;
  757. uint32_t size = 0;
  758. uint32_t idx = 0;
  759. uint32_t nflags = 0;
  760. unsigned long msw_ts = 0;
  761. unsigned long lsw_ts = 0;
  762. uint32_t mfield_size = (audio->buf_cfg.meta_info_enable == 0) ? 0 :
  763. sizeof(struct meta_in);
  764. pr_debug("%s:session id %d: to write[%zd]\n", __func__,
  765. audio->ac->session, count);
  766. if (audio->reset_event)
  767. return -ENETRESET;
  768. if (!audio->enabled)
  769. return -EFAULT;
  770. mutex_lock(&audio->write_lock);
  771. while (count > 0) {
  772. rc = wait_event_interruptible(audio->write_wait,
  773. ((atomic_read(&audio->in_count) > 0) ||
  774. (audio->stopped) ||
  775. (audio->wflush) || (audio->event_abort)));
  776. if (audio->event_abort) {
  777. rc = -EIO;
  778. break;
  779. }
  780. if (rc < 0)
  781. break;
  782. if (audio->stopped || audio->wflush) {
  783. pr_debug("%s: session id %d: stop or flush\n", __func__,
  784. audio->ac->session);
  785. rc = -EBUSY;
  786. break;
  787. }
  788. /* if no PCM data, might have only eos buffer
  789. * such case do not hold cpu buffer
  790. */
  791. if ((buf == start) && (count == mfield_size)) {
  792. char eos_buf[sizeof(struct meta_in)];
  793. /* Processing beginning of user buffer */
  794. if (copy_from_user(eos_buf, buf, mfield_size)) {
  795. rc = -EFAULT;
  796. break;
  797. }
  798. /* Check if EOS flag is set and buffer has
  799. * contains just meta field
  800. */
  801. extract_meta_info(eos_buf, &msw_ts, &lsw_ts,
  802. &nflags);
  803. buf += mfield_size;
  804. /* send the EOS and return */
  805. pr_debug("%s:session id %d: send EOS 0x%8x\n",
  806. __func__,
  807. audio->ac->session, nflags);
  808. break;
  809. }
  810. data = (unsigned char *)q6asm_is_cpu_buf_avail(IN, audio->ac,
  811. &size, &idx);
  812. if (!data) {
  813. pr_debug("%s:session id %d: No buf available\n",
  814. __func__, audio->ac->session);
  815. continue;
  816. }
  817. cpy_ptr = data;
  818. if (audio->buf_cfg.meta_info_enable) {
  819. if (buf == start) {
  820. /* Processing beginning of user buffer */
  821. if (copy_from_user(cpy_ptr, buf, mfield_size)) {
  822. rc = -EFAULT;
  823. break;
  824. }
  825. /* Check if EOS flag is set and buffer has
  826. * contains just meta field
  827. */
  828. extract_meta_info(cpy_ptr, &msw_ts, &lsw_ts,
  829. &nflags);
  830. buf += mfield_size;
  831. count -= mfield_size;
  832. } else {
  833. pr_debug("%s:session id %d: continuous buffer\n",
  834. __func__, audio->ac->session);
  835. }
  836. }
  837. xfer = (count > (audio->pcm_cfg.buffer_size)) ?
  838. (audio->pcm_cfg.buffer_size) : count;
  839. if (copy_from_user(cpy_ptr, buf, xfer)) {
  840. rc = -EFAULT;
  841. break;
  842. }
  843. rc = q6asm_write(audio->ac, xfer, msw_ts, lsw_ts, 0x00);
  844. if (rc < 0) {
  845. rc = -EFAULT;
  846. break;
  847. }
  848. atomic_dec(&audio->in_count);
  849. count -= xfer;
  850. buf += xfer;
  851. }
  852. mutex_unlock(&audio->write_lock);
  853. pr_debug("%s:session id %d: eos_condition 0x%x buf[0x%pK] start[0x%pK]\n",
  854. __func__, audio->ac->session,
  855. nflags, buf, start);
  856. if (nflags & AUD_EOS_SET) {
  857. rc = q6asm_cmd(audio->ac, CMD_EOS);
  858. pr_info("%s:session id %d: eos %d at input\n", __func__,
  859. audio->ac->session, audio->eos_rsp);
  860. }
  861. pr_debug("%s:session id %d: Written %zd Avail Buf[%d]", __func__,
  862. audio->ac->session, (buf - start - mfield_size),
  863. atomic_read(&audio->in_count));
  864. if (!rc) {
  865. if (buf > start)
  866. return buf - start;
  867. }
  868. return rc;
  869. }
  870. int audio_in_release(struct inode *inode, struct file *file)
  871. {
  872. struct q6audio_in *audio = file->private_data;
  873. pr_info("%s: session id %d\n", __func__, audio->ac->session);
  874. mutex_lock(&audio->lock);
  875. audio_in_disable(audio);
  876. q6asm_audio_client_free(audio->ac);
  877. mutex_unlock(&audio->lock);
  878. kfree(audio->enc_cfg);
  879. kfree(audio->codec_cfg);
  880. kfree(audio);
  881. return 0;
  882. }