audio_in_acts.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079
  1. /*
  2. * Copyright (c) 2020 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief Audio IN(ADC/I2S-RX/SPDIF-RX) core management layer
  9. */
  10. #include <kernel.h>
  11. #include <device.h>
  12. #include <string.h>
  13. #include <errno.h>
  14. #include <soc.h>
  15. #include <board_cfg.h>
  16. #include <drivers/dma.h>
  17. #include <drivers/audio/audio_in.h>
  18. #include "phy_audio_common.h"
  19. #include <logging/log.h>
  20. LOG_MODULE_REGISTER(ain, CONFIG_LOG_DEFAULT_LEVEL);
  21. #define AIN_SESSION_MAGIC (0x11223344)
  22. #define AIN_SESSION_CHECK_MAGIC(x) ((x) == AIN_SESSION_MAGIC)
  23. #ifdef CONFIG_AUDIO_IN_ADC_SUPPORT
  24. #define AIN_ADC_SESSION_MAX (1) /* 1 ADC channels */
  25. #else
  26. #define AIN_ADC_SESSION_MAX (1)
  27. #endif
  28. #ifdef CONFIG_AUDIO_IN_I2SRX_SUPPORT
  29. #define AIN_I2SRX_SESSION_MAX (1) /* 1 I2SRX channel */
  30. #else
  31. #define AIN_I2SRX_SESSION_MAX (0)
  32. #endif
  33. #ifdef CONFIG_AUDIO_IN_SPDIFRX_SUPPORT
  34. #define AIN_SPDIFRX_SESSION_MAX (1) /* 1 SPDIFRX channel */
  35. #else
  36. #define AIN_SPDIFRX_SESSION_MAX (0)
  37. #endif
  38. #define AIN_SESSION_MAX (AIN_ADC_SESSION_MAX + AIN_I2SRX_SESSION_MAX + AIN_SPDIFRX_SESSION_MAX) /* totally max sessions */
  39. #define AIN_SESSION_OPEN (1 << 0) /* Session open flag */
  40. #define AIN_SESSION_CONFIG (1 << 1) /* Session config flag */
  41. #define AIN_SESSION_START (1 << 2) /* Session start flag */
  42. #define AIN_SESSION_BIND (1 << 3) /* Session start flag */
  43. #define DMA_IRQ_TC (0) /* DMA completion flag */
  44. #define DMA_IRQ_HF (1) /* DMA half-full flag */
  45. /**
  46. * struct ain_dynamic_debug_t
  47. * @brief audio in session dynamic debug structure
  48. */
  49. typedef struct {
  50. uint32_t timestamp; /* record the per-second timestamp */
  51. uint32_t per_second_size; /* record the per-second play size */
  52. uint8_t dump_len; /* dump the length of buffer per-second */
  53. uint8_t performance: 1; /* enable flag of showing the play performance */
  54. } ain_dynamic_debug_t;
  55. /*
  56. * struct ain_session_t
  57. * @brief audio in session structure
  58. */
  59. typedef struct {
  60. int magic; /* session magic value as AIN_SESSION_MAGIC */
  61. int dma_chan; /* DMA channel handle */
  62. uint16_t input_dev; /* input audio device */
  63. uint16_t channel_type; /* Indicates the channel type selection */
  64. uint8_t flags; /* session flags */
  65. uint8_t id; /* the session id */
  66. uint8_t dma_width; /* dma width */
  67. int (*callback)(void *cb_data, uint32_t reason); /* The callback function which called when #AIN_DMA_IRQ_HF or #AIN_DMA_IRQ_TC events happened */
  68. void *cb_data; /* callback user data */
  69. uint8_t *reload_addr; /* Reload buffer address to transfer */
  70. uint32_t reload_len; /* The length of the reload buffer */
  71. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  72. ain_dynamic_debug_t debug; /* dynamic debug */
  73. #endif
  74. uint8_t dma_separated_en : 1; /* the flag of DMA interleaved mode enable or not */
  75. uint8_t dma_separated_mode : 2; /* the DMA interleaved mode which specifies the data format stored in memory */
  76. } ain_session_t;
  77. /*
  78. * struct aout_drv_data
  79. * @brief audio in driver data which are software related
  80. */
  81. struct ain_drv_data {
  82. struct k_sem lock;
  83. struct device *dma_dev;
  84. struct device *adc0_dev; /* ADC0 device handler */
  85. struct device *i2srx0_dev; /* I2SRX0 device handler */
  86. struct device *spdifrx0_dev; /* SPFIRX0 device handler */
  87. struct device *anc0_dev; /* ANC0 device handler */
  88. uint32_t adc_sess_stack[AIN_ADC_SESSION_MAX + 1]; /* stack to store sync wait sessions */
  89. uint8_t adc_sess_stack_cur; /* current curtor of adc session stack */
  90. uint8_t adc_ref_counter; /* ADC channels start reference counter */
  91. uint8_t anc_en_flag : 1; /* the flag of ANC enable */
  92. };
  93. /*
  94. * struct aout_config_data
  95. * @brief audio in config data which are the hardward related
  96. */
  97. struct ain_config_data {
  98. const char *adc0_name; /* physical ADC0 device name */
  99. const char *i2srx0_name; /* physical I2SRX0 device name */
  100. const char *spdifrx0_name; /* physical SPDIFRX0 device name */
  101. };
  102. static ain_session_t ain_sessions[AIN_SESSION_MAX];
  103. /*
  104. * @brief checkout if there is the same channel within audio in sessions
  105. */
  106. static bool audio_in_session_check(uint16_t type)
  107. {
  108. int i;
  109. ain_session_t *sess = ain_sessions;
  110. uint8_t max_sess, sess_opened = 0;
  111. if (AUDIO_CHANNEL_ADC & type) {
  112. max_sess = AIN_ADC_SESSION_MAX;
  113. } else if (AUDIO_CHANNEL_I2SRX & type) {
  114. max_sess = AIN_I2SRX_SESSION_MAX;
  115. } else if (AUDIO_CHANNEL_SPDIFRX & type) {
  116. max_sess = AIN_SPDIFRX_SESSION_MAX;
  117. } else {
  118. LOG_ERR("Invalid session type %d", type);
  119. return true;
  120. }
  121. for (i = 0; i < AIN_SESSION_MAX; i++, sess++) {
  122. if (AIN_SESSION_CHECK_MAGIC(sess->magic)
  123. && (sess->flags & AIN_SESSION_OPEN)
  124. && (sess->channel_type & type)) {
  125. sess_opened++;
  126. LOG_DBG("Found aout channel type %d in use", type);
  127. }
  128. }
  129. /* check if the number of opened sessions is bigger than the max limit */
  130. if (sess_opened >= max_sess) {
  131. LOG_ERR("channel type:%d session max %d and opened %d",
  132. type, max_sess, sess_opened);
  133. return true;
  134. }
  135. return false;
  136. }
  137. /*
  138. * @brief Get audio in session by specified channel
  139. */
  140. static ain_session_t *audio_in_session_get(uint16_t type)
  141. {
  142. ain_session_t *sess = ain_sessions;
  143. int i;
  144. if (audio_in_session_check(type))
  145. return NULL;
  146. for (i = 0; i < AIN_SESSION_MAX; i++, sess++) {
  147. if (!(sess->flags & AIN_SESSION_OPEN)) {
  148. memset(sess, 0, sizeof(ain_session_t));
  149. sess->magic = AIN_SESSION_MAGIC;
  150. sess->flags = AIN_SESSION_OPEN;
  151. sess->channel_type = type;
  152. sess->id = i;
  153. return sess;
  154. }
  155. }
  156. return NULL;
  157. }
  158. /*
  159. * @brief Put audio in session by given session address
  160. */
  161. static void audio_in_session_put(ain_session_t *s)
  162. {
  163. ain_session_t *sess = ain_sessions;
  164. int i;
  165. for (i = 0; i < AIN_SESSION_MAX; i++, sess++) {
  166. if ((uint32_t)s == (uint32_t)sess) {
  167. memset(s, 0, sizeof(ain_session_t));
  168. break;
  169. }
  170. }
  171. }
  172. /* @brief audio in session lock */
  173. static inline void audio_in_lock(struct device *dev)
  174. {
  175. struct ain_drv_data *data = dev->data;
  176. k_sem_take(&data->lock, K_FOREVER);
  177. }
  178. /* @brief audio in session unlock */
  179. static inline void audio_in_unlock(struct device *dev)
  180. {
  181. struct ain_drv_data *data = dev->data;
  182. k_sem_give(&data->lock);
  183. }
  184. /* @brief bind the audio in session to dma start at the same time */
  185. static int audio_in_session_bind(struct device *dev, ain_session_t *this, ain_session_t *bind)
  186. {
  187. struct ain_drv_data *data = dev->data;
  188. if ((!bind) || (!AIN_SESSION_CHECK_MAGIC(bind->magic))) {
  189. LOG_ERR("Invalid session:%p", bind);
  190. return -EINVAL;
  191. }
  192. /* check if the session does not config or already start */
  193. if (!(bind->flags & AIN_SESSION_CONFIG) || (bind->flags & AIN_SESSION_START)) {
  194. LOG_ERR("Invalid session status:0x%x", bind->flags);
  195. return -EPERM;
  196. }
  197. if (this == bind) {
  198. LOG_ERR("Bind the same session@%p", this);
  199. return -EPERM;
  200. }
  201. if (bind->flags & AIN_SESSION_BIND) {
  202. LOG_INF("Already bind session@%p", bind);
  203. return 0;
  204. }
  205. if (bind->channel_type != AUDIO_CHANNEL_ADC) {
  206. LOG_ERR("For now only support ADC to bind channels");
  207. return -EPERM;
  208. }
  209. bind->flags |= AIN_SESSION_BIND;
  210. ++data->adc_ref_counter;
  211. LOG_INF("session@%p binded", bind);
  212. return 0;
  213. }
  214. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  215. /* @brief show the audio in performance */
  216. static void audio_in_debug_perf(ain_session_t *session, uint8_t *buffer, uint32_t len)
  217. {
  218. uint32_t delta;
  219. if (session->debug.performance) {
  220. delta = (uint32_t)k_cyc_to_ns_floor64(k_cycle_get_32() - session->debug.timestamp);
  221. session->debug.per_second_size += len;
  222. if (delta > 1000000000UL) {
  223. session->debug.timestamp = k_cycle_get_32();
  224. printk("** in session@%p - %dB/s **\n",
  225. session, session->debug.per_second_size);
  226. session->debug.per_second_size = 0;
  227. if (session->debug.dump_len) {
  228. AUDIO_DUMP_MEM(buffer, session->debug.dump_len);
  229. }
  230. }
  231. }
  232. }
  233. /* @brief control all sessions to enable or disable performance statistics */
  234. static int audio_in_debug_perf_all_sessions(uint8_t is_en)
  235. {
  236. int i;
  237. ain_session_t *sess = ain_sessions;
  238. for (i = 0; i < AIN_SESSION_MAX; i++, sess++) {
  239. if (AIN_SESSION_CHECK_MAGIC(sess->magic)
  240. && (sess->flags & AIN_SESSION_OPEN)) {
  241. LOG_INF("session@%p perf debug status %d", sess, is_en);
  242. sess->debug.performance = is_en;
  243. sess->debug.per_second_size = 0;
  244. sess->debug.timestamp = 0;
  245. sess->debug.dump_len = 0;
  246. }
  247. }
  248. return 0;
  249. }
  250. /* @brief control all sessions to set the dump length per second */
  251. static int audio_in_debug_dump_length(uint8_t length)
  252. {
  253. int i;
  254. ain_session_t *sess = ain_sessions;
  255. for (i = 0; i < AIN_SESSION_MAX; i++, sess++) {
  256. if (AIN_SESSION_CHECK_MAGIC(sess->magic)
  257. && (sess->flags & AIN_SESSION_OPEN)) {
  258. sess->debug.dump_len = length;
  259. }
  260. }
  261. return 0;
  262. }
  263. #endif
  264. /* @brief Enable the ADC channel */
  265. #ifdef CONFIG_AUDIO_IN_ADC_SUPPORT
  266. static int audio_in_enable_adc(struct device *dev, ain_param_t *param)
  267. {
  268. struct ain_drv_data *data = dev->data;
  269. struct device *adc = data->adc0_dev;
  270. if (!adc) {
  271. LOG_ERR("Physical ADC device is not esixted");
  272. return -EFAULT;
  273. }
  274. if ((param->channel_width != CHANNEL_WIDTH_16BITS)
  275. && (param->channel_width != CHANNEL_WIDTH_24BITS)) {
  276. LOG_ERR("Invalid channel width %d", param->channel_width);
  277. return -EINVAL;
  278. }
  279. return phy_audio_enable(adc, (void *)param);
  280. }
  281. #endif
  282. /* @brief Enable the I2SRX channel */
  283. #ifdef CONFIG_AUDIO_IN_I2SRX_SUPPORT
  284. static int audio_in_enable_i2srx(struct device *dev, ain_param_t *param)
  285. {
  286. struct ain_drv_data *data = dev->data;
  287. struct device *i2srx = data->i2srx0_dev;
  288. if (!i2srx) {
  289. LOG_ERR("Physical I2SRX device is not esixted");
  290. return -EFAULT;
  291. }
  292. if ((param->channel_width != CHANNEL_WIDTH_16BITS)
  293. && (param->channel_width != CHANNEL_WIDTH_20BITS)
  294. && (param->channel_width != CHANNEL_WIDTH_24BITS)) {
  295. LOG_ERR("Invalid channel width %d", param->channel_width);
  296. return -EINVAL;
  297. }
  298. return phy_audio_enable(i2srx, (void *)param);
  299. }
  300. #endif
  301. /* @brief Enable the SPDIFRX channel */
  302. #ifdef CONFIG_AUDIO_IN_SPDIFRX_SUPPORT
  303. static int audio_in_enable_spdifrx(struct device *dev, ain_param_t *param)
  304. {
  305. struct ain_drv_data *data = dev->data;
  306. struct device *spdifrx = data->spdifrx0_dev;
  307. if (!spdifrx) {
  308. LOG_ERR("Physical SPDIFRX device is not esixted");
  309. return -EFAULT;
  310. }
  311. if ((param->channel_width != CHANNEL_WIDTH_16BITS)
  312. && (param->channel_width != CHANNEL_WIDTH_24BITS)) {
  313. LOG_ERR("Invalid channel width %d", param->channel_width);
  314. return -EINVAL;
  315. }
  316. return phy_audio_enable(spdifrx, (void *)param);
  317. }
  318. #endif
  319. /* @brief DMA irq callback on reload method */
  320. static void audio_in_dma_reload(const struct device *dev, void *user_data,
  321. uint32_t channel, int status)
  322. {
  323. ain_session_t *session = (ain_session_t *)user_data;
  324. uint32_t ret_reson;
  325. uint32_t key, delta, len;
  326. uint16_t time = CONFIG_ADC_STARTUP_DISCARD_TIME;
  327. static uint32_t timestamp = 0;
  328. static bool already_discard = false;
  329. ARG_UNUSED(dev);
  330. ARG_UNUSED(channel);
  331. if(session ==NULL)
  332. {
  333. LOG_WRN("session is NULL");
  334. return;
  335. }
  336. len = session->reload_len / 2;
  337. if (!timestamp) {
  338. timestamp = k_cycle_get_32();
  339. LOG_DBG("discard data start time:%u ns",k_cyc_to_ns_floor32(timestamp));
  340. }
  341. if ((!already_discard) && time) {
  342. delta = (uint32_t)k_cyc_to_ns_floor64(k_cycle_get_32() - timestamp);
  343. if (delta > (time * 1000000UL)) {
  344. already_discard = true;
  345. }
  346. LOG_DBG("discard data end time:%u ns", k_cyc_to_ns_floor32(k_cycle_get_32()));
  347. }
  348. if (session && AIN_SESSION_CHECK_MAGIC(session->magic)) {
  349. if (session->callback) {
  350. key = irq_lock();
  351. if (status == DMA_IRQ_HF) {
  352. ret_reson = AIN_DMA_IRQ_HF;
  353. if (!already_discard && time)
  354. memset(session->reload_addr, 0, len);
  355. } else {
  356. ret_reson = AIN_DMA_IRQ_TC;
  357. if (!already_discard && time)
  358. memset(session->reload_addr + len, 0, len);
  359. }
  360. session->callback(session->cb_data, ret_reson);
  361. irq_unlock(key);
  362. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  363. audio_in_debug_perf(session, session->reload_addr,
  364. session->reload_len / 2);
  365. #endif
  366. }
  367. }
  368. }
  369. /* @brief audio out dma enable separated mode */
  370. static int audio_in_dma_separated_enable(struct device *dev,
  371. ain_session_t *session, audio_interleave_mode_e *p_mode)
  372. {
  373. ARG_UNUSED(dev);
  374. if (!session || !p_mode) {
  375. LOG_ERR("Invalid parameter");
  376. return -EINVAL;
  377. }
  378. session->dma_separated_en = 1;
  379. session->dma_separated_mode = *p_mode;
  380. LOG_INF("Enable AIN DMA separated mode:%d", session->dma_separated_mode);
  381. return 0;
  382. }
  383. /* @brief prepare the DMA configuration for the audio in transfer */
  384. static int audio_in_dma_prepare(struct device *dev, ain_session_t *session)
  385. {
  386. struct ain_drv_data *data = dev->data;
  387. struct dma_config dma_cfg = {0};
  388. struct dma_block_config dma_block_cfg = {0};
  389. struct audio_in_dma_info info = {0};
  390. dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY;
  391. /* Only support the DMA reload mode */
  392. dma_block_cfg.dest_reload_en = 1;
  393. dma_cfg.head_block = &dma_block_cfg;
  394. dma_cfg.source_data_size = session->dma_width;
  395. if (AUDIO_CHANNEL_ADC == session->channel_type) {
  396. info.input_dev = session->input_dev;
  397. if (phy_audio_control(data->adc0_dev, PHY_CMD_GET_AIN_DMA_INFO, &info)) {
  398. LOG_ERR("Failed to get ADC DMA info");
  399. return -EFAULT;
  400. }
  401. uint32_t level;
  402. uint32_t fifo_cmd = PHY_FIFO_CMD(session->input_dev, 0);
  403. if (!phy_audio_control(data->adc0_dev,
  404. PHY_CMD_FIFO_DRQ_LEVEL_GET, &fifo_cmd)) {
  405. level = PHY_GET_FIFO_CMD_VAL(fifo_cmd);
  406. LOG_DBG("DRQ level %d", level);
  407. /* When DRQ level < 8 levels shall use DMA single mode */
  408. if (level < 8)
  409. dma_cfg.source_burst_length = 1;
  410. } else {
  411. LOG_ERR("Failed to get DRQ level");
  412. return -EFAULT;
  413. }
  414. } else if (AUDIO_CHANNEL_I2SRX == session->channel_type) {
  415. if (phy_audio_control(data->i2srx0_dev, PHY_CMD_GET_AIN_DMA_INFO, &info)) {
  416. LOG_ERR("Failed to get I2SRX DMA info");
  417. return -EFAULT;
  418. }
  419. } else if (AUDIO_CHANNEL_SPDIFRX == session->channel_type) {
  420. if (phy_audio_control(data->spdifrx0_dev, PHY_CMD_GET_AIN_DMA_INFO, &info)) {
  421. LOG_ERR("Failed to get SPDIFRX DMA info");
  422. return -EFAULT;
  423. }
  424. } else {
  425. LOG_ERR("invalid channel type 0x%x\n", session->channel_type);
  426. return -EINVAL;
  427. }
  428. if (!data->dma_dev) {
  429. data->dma_dev = (struct device *)device_get_binding(info.dma_info.dma_dev_name);
  430. if (!data->dma_dev) {
  431. LOG_ERR("Bind DMA device %s error", info.dma_info.dma_dev_name);
  432. return -ENOENT;
  433. }
  434. }
  435. /* request dma channel handle */
  436. session->dma_chan = dma_request(data->dma_dev, 0xFF);
  437. if (session->dma_chan < 0) {
  438. LOG_ERR("Failed to request dma channel");
  439. return -ENXIO;
  440. }
  441. dma_cfg.dma_slot = info.dma_info.dma_id;
  442. /* Use the DMA irq to notify the status of transfer */
  443. if (session->callback) {
  444. dma_cfg.dma_callback = audio_in_dma_reload;
  445. dma_cfg.user_data = (void *)session;
  446. dma_cfg.complete_callback_en = 1;
  447. }
  448. if (session->dma_separated_en) {
  449. dma_cfg.reserved = 1;
  450. }
  451. if (dma_config(data->dma_dev, session->dma_chan, &dma_cfg)) {
  452. LOG_ERR("DMA config error");
  453. return -EFAULT;
  454. }
  455. if (session->reload_addr) {
  456. LOG_INF("reload addr:0x%x, reload len:%d\n", (uint32_t)session->reload_addr, session->reload_len);
  457. if (session->dma_separated_en) {
  458. uint32_t dma_length = (session->reload_len << 1);
  459. if (session->dma_separated_mode == LEFT_MONO_RIGHT_MUTE_MODE) {
  460. dma_reload(data->dma_dev, session->dma_chan, AUDIO_IN_DMA_RESERVED_ADDRESS,
  461. (uint32_t)session->reload_addr, dma_length);
  462. } else if (session->dma_separated_mode == LEFT_RIGHT_SEPERATE){
  463. dma_reload(data->dma_dev, session->dma_chan,
  464. (uint32_t)(session->reload_addr + session->reload_len),
  465. (uint32_t)session->reload_addr, dma_length);
  466. } else if (session->dma_separated_mode == LEFT_MUTE_RIGHT_MONO_MODE){
  467. dma_reload(data->dma_dev, session->dma_chan, (uint32_t)session->reload_addr,
  468. AUDIO_IN_DMA_RESERVED_ADDRESS, dma_length);
  469. }
  470. } else {
  471. dma_reload(data->dma_dev, session->dma_chan,
  472. 0, (uint32_t)session->reload_addr, session->reload_len);
  473. }
  474. }
  475. return 0;
  476. }
  477. /* @brief audio out enable and return the session handler */
  478. static void *acts_audio_in_open(struct device *dev, ain_param_t *param)
  479. {
  480. ain_session_t * session = NULL;
  481. uint8_t channel_type;
  482. int ret;
  483. void *rtn_sess = NULL;
  484. if (!param) {
  485. LOG_ERR("NULL parameter");
  486. return NULL;
  487. }
  488. audio_in_lock(dev);
  489. channel_type = param->channel_type;
  490. session = audio_in_session_get(channel_type);
  491. if (!session) {
  492. LOG_ERR("Failed to get audio session (type:%d)", channel_type);
  493. goto out;
  494. }
  495. if (param->reload_setting.reload_addr && !param->reload_setting.reload_len) {
  496. LOG_ERR("Reload parameter error addr:0x%x, len:0x%x",
  497. (uint32_t)param->reload_setting.reload_addr, param->reload_setting.reload_len);
  498. audio_in_session_put(session);
  499. goto out;
  500. }
  501. session->callback = param->callback;
  502. session->cb_data = param->cb_data;
  503. session->reload_addr = param->reload_setting.reload_addr;
  504. session->reload_len = param->reload_setting.reload_len;
  505. session->dma_width = (CHANNEL_WIDTH_16BITS == param->channel_width) ? 2 : 4;
  506. if (channel_type == AUDIO_CHANNEL_ADC) {
  507. #ifdef CONFIG_AUDIO_IN_ADC_SUPPORT
  508. ret = audio_in_enable_adc(dev, param);
  509. if (!ret)
  510. session->input_dev = param->adc_setting->device;
  511. #else
  512. ret = -ENXIO;
  513. #endif
  514. } else if (channel_type == AUDIO_CHANNEL_I2SRX) {
  515. #ifdef CONFIG_AUDIO_IN_I2SRX_SUPPORT
  516. ret = audio_in_enable_i2srx(dev, param);
  517. #else
  518. ret = -ENXIO;
  519. #endif
  520. } else if (channel_type == AUDIO_CHANNEL_SPDIFRX) {
  521. #ifdef CONFIG_AUDIO_IN_SPDIFRX_SUPPORT
  522. ret = audio_in_enable_spdifrx(dev, param);
  523. #else
  524. ret = -ENXIO;
  525. #endif
  526. } else {
  527. LOG_ERR("Invalid channel type %d", channel_type);
  528. audio_in_session_put(session);
  529. goto out;
  530. }
  531. if (ret) {
  532. LOG_ERR("Enable channel type %d error:%d", channel_type, ret);
  533. audio_in_session_put(session);
  534. goto out;
  535. }
  536. session->flags |= AIN_SESSION_CONFIG;
  537. /* The session address is the audio in handler */
  538. rtn_sess = (void *)session;
  539. LOG_INF("channel@%d sess:%p type:%d input_dev:0x%x opened",
  540. session->id, session, channel_type, session->input_dev);
  541. out:
  542. audio_in_unlock(dev);
  543. return rtn_sess;
  544. }
  545. /* @brief Disable the ADC channel */
  546. #ifdef CONFIG_AUDIO_IN_ADC_SUPPORT
  547. static int audio_in_disable_adc(struct device *dev, ain_session_t *session)
  548. {
  549. struct ain_drv_data *data = dev->data;
  550. struct device *adc = data->adc0_dev;
  551. uint16_t input_dev = session->input_dev;
  552. if (!adc) {
  553. LOG_ERR("Physical ADC device is not esixted");
  554. return -EFAULT;
  555. }
  556. if ((session->flags & AIN_SESSION_BIND)
  557. && !(session->flags & AIN_SESSION_START)) {
  558. /* the session already bind but not start yet */
  559. if (data->adc_ref_counter)
  560. --data->adc_ref_counter;
  561. }
  562. if (!data->adc_ref_counter)
  563. data->adc_sess_stack_cur = 0;
  564. return phy_audio_disable(adc, &input_dev);
  565. }
  566. #endif
  567. /* @brief Disable the I2SRX channel */
  568. #ifdef CONFIG_AUDIO_IN_I2SRX_SUPPORT
  569. static int audio_in_disable_i2srx(struct device *dev, ain_session_t *session)
  570. {
  571. struct ain_drv_data *data = dev->data;
  572. struct device *i2srx = data->i2srx0_dev;
  573. if (!i2srx) {
  574. LOG_ERR("Physical I2SRX device is not esixted");
  575. return -EFAULT;
  576. }
  577. return phy_audio_disable(i2srx, NULL);
  578. }
  579. #endif
  580. /* @brief Disable the SPDIFRX channel */
  581. #ifdef CONFIG_AUDIO_IN_SPDIFRX_SUPPORT
  582. static int audio_in_disable_spdifrx(struct device *dev, ain_session_t *session)
  583. {
  584. struct ain_drv_data *data = dev->data;
  585. struct device *spdifrx = data->spdifrx0_dev;
  586. if (!spdifrx) {
  587. LOG_ERR("Physical SPDIFRX device is not esixted");
  588. return -EFAULT;
  589. }
  590. return phy_audio_disable(spdifrx, NULL);
  591. }
  592. #endif
  593. /* @brief Disable audio in channel by specified session handler */
  594. static int acts_audio_in_close(struct device *dev, void *handle)
  595. {
  596. struct ain_drv_data *data = dev->data;
  597. uint8_t channel_type;
  598. int ret;
  599. ain_session_t *session = (ain_session_t *)handle;
  600. if (!handle) {
  601. LOG_ERR("Invalid handle");
  602. return -EINVAL;
  603. }
  604. audio_in_lock(dev);
  605. if (!AIN_SESSION_CHECK_MAGIC(session->magic)) {
  606. LOG_ERR("Session magic error:0x%x", session->magic);
  607. ret = -EFAULT;
  608. goto out;
  609. }
  610. channel_type = session->channel_type;
  611. if (channel_type == AUDIO_CHANNEL_ADC) {
  612. #ifdef CONFIG_AUDIO_IN_ADC_SUPPORT
  613. ret = audio_in_disable_adc(dev, session);
  614. #else
  615. ret = -ENXIO;
  616. #endif
  617. } else if (channel_type == AUDIO_CHANNEL_I2SRX) {
  618. #ifdef CONFIG_AUDIO_IN_I2SRX_SUPPORT
  619. ret = audio_in_disable_i2srx(dev, session);
  620. #else
  621. ret = -ENXIO;
  622. #endif
  623. } else if (channel_type == AUDIO_CHANNEL_SPDIFRX) {
  624. #ifdef CONFIG_AUDIO_IN_SPDIFRX_SUPPORT
  625. ret = audio_in_disable_spdifrx(dev, session);
  626. #else
  627. ret = -ENXIO;
  628. #endif
  629. } else {
  630. LOG_ERR("Invalid channel type %d", channel_type);
  631. ret = -EINVAL;
  632. goto out;
  633. }
  634. if (ret) {
  635. LOG_ERR("Disable channel type %d error:%d", channel_type, ret);
  636. goto out;
  637. }
  638. /* stop and free dma channel resource */
  639. if (data->dma_dev && session->dma_chan) {
  640. dma_stop(data->dma_dev, session->dma_chan);
  641. dma_free(data->dma_dev, session->dma_chan);
  642. }
  643. LOG_INF("session#%d@%p closed", session->id, session);
  644. audio_in_session_put(session);
  645. out:
  646. audio_in_unlock(dev);
  647. return ret;
  648. }
  649. static int acts_audio_in_control(struct device *dev, void *handle, int cmd, void *param)
  650. {
  651. struct ain_drv_data *data = dev->data;
  652. ain_session_t *session = (ain_session_t *)handle;
  653. uint8_t channel_type = session->channel_type;
  654. int ret;
  655. LOG_DBG("session#0x%x cmd 0x%x", (uint32_t)handle, cmd);
  656. if (cmd == AIN_CMD_ANC_CONTROL) {
  657. audio_in_lock(dev);
  658. ret = phy_audio_control(data->adc0_dev, AIN_CMD_ANC_CONTROL, param);
  659. audio_in_unlock(dev);
  660. return ret;
  661. }
  662. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  663. if (AIN_CMD_DEBUG_PERFORMANCE_CTL_ALL == cmd)
  664. return audio_in_debug_perf_all_sessions(*(uint8_t *)param);
  665. if (AIN_CMD_DEBUG_DUMP_LENGTH_ALL == cmd)
  666. return audio_in_debug_dump_length(*(uint8_t *)param);
  667. #endif
  668. if (!AIN_SESSION_CHECK_MAGIC(session->magic)) {
  669. LOG_ERR("Session magic error:0x%x", session->magic);
  670. return -EFAULT;
  671. }
  672. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  673. if (AIN_CMD_DEBUG_PERFORMANCE_CTL == cmd) {
  674. session->debug.performance = *(uint8_t *)param;
  675. session->debug.per_second_size = 0;
  676. session->debug.timestamp = 0;
  677. session->debug.dump_len = 0;
  678. return 0;
  679. }
  680. if (AIN_CMD_DEBUG_DUMP_LENGTH == cmd) {
  681. session->debug.dump_len = *(uint8_t *)param;
  682. return 0;
  683. }
  684. #endif
  685. if (cmd == AIN_CMD_BIND_CHANNEL)
  686. return audio_in_session_bind(dev, session, (ain_session_t *)param);
  687. if (cmd == AIN_CMD_SET_SEPARATED_MODE) {
  688. return audio_in_dma_separated_enable(dev, session,
  689. (audio_interleave_mode_e *)param);
  690. }
  691. if (channel_type == AUDIO_CHANNEL_ADC) {
  692. #ifdef CONFIG_AUDIO_IN_ADC_SUPPORT
  693. if (AIN_CMD_SET_ADC_GAIN == cmd) {
  694. adc_setting_t setting = {0};
  695. adc_gain *gain = (adc_gain *)param;
  696. setting.device = session->input_dev;
  697. memcpy(&setting.gain, gain, sizeof(adc_gain));
  698. ret = phy_audio_control(data->adc0_dev, PHY_CMD_ADC_GAIN_CONFIG, &setting);
  699. } else if ((AIN_CMD_GET_ADC_LEFT_GAIN_RANGE == cmd)
  700. || (AIN_CMD_GET_ADC_RIGHT_GAIN_RANGE == cmd)) {
  701. adc_gain_range *range = (adc_gain_range *)param;
  702. /* use the 'min' to send the input device info to phy-adc device */
  703. range->min = (int16_t)session->input_dev;
  704. ret = phy_audio_control(data->adc0_dev, cmd, param);
  705. } else if (AIN_CMD_GET_ADC_FIFO_DRQ_LEVEL == cmd) {
  706. uint32_t fifo_cmd = PHY_FIFO_CMD(session->input_dev, 0);
  707. ret = phy_audio_control(data->adc0_dev,
  708. PHY_CMD_FIFO_DRQ_LEVEL_GET, &fifo_cmd);
  709. if (!ret)
  710. *(uint8_t *)param = PHY_GET_FIFO_CMD_VAL(fifo_cmd);
  711. } else if (AIN_CMD_SET_ADC_FIFO_DRQ_LEVEL == cmd) {
  712. uint8_t level = *(uint8_t *)param;
  713. uint32_t fifo_cmd = PHY_FIFO_CMD(session->input_dev, level);
  714. ret = phy_audio_control(data->adc0_dev,
  715. PHY_CMD_FIFO_DRQ_LEVEL_SET, &fifo_cmd);
  716. } else {
  717. ret = phy_audio_control(data->adc0_dev, cmd, param);
  718. }
  719. #else
  720. ret = -ENXIO;
  721. #endif
  722. } else if (channel_type == AUDIO_CHANNEL_I2SRX) {
  723. #ifdef CONFIG_AUDIO_IN_I2SRX_SUPPORT
  724. ret = phy_audio_control(data->i2srx0_dev, cmd, param);
  725. #else
  726. ret = -ENXIO;
  727. #endif
  728. } else if (channel_type == AUDIO_CHANNEL_SPDIFRX) {
  729. #ifdef CONFIG_AUDIO_IN_SPDIFRX_SUPPORT
  730. ret = phy_audio_control(data->spdifrx0_dev, cmd, param);
  731. #else
  732. ret = -ENXIO;
  733. #endif
  734. } else {
  735. LOG_ERR("Invalid channel type %d", channel_type);
  736. ret = -EINVAL;
  737. }
  738. return ret;
  739. }
  740. /* @brief Start the audio input transfering */
  741. static int acts_audio_in_start(struct device *dev, void *handle)
  742. {
  743. struct ain_drv_data *data = dev->data;
  744. ain_session_t *session = (ain_session_t *)handle;
  745. int ret;
  746. if (!handle) {
  747. LOG_ERR("Invalid handle");
  748. return -EINVAL;
  749. }
  750. if (!AIN_SESSION_CHECK_MAGIC(session->magic)) {
  751. LOG_ERR("Session magic error:0x%x", session->magic);
  752. return -EFAULT;
  753. }
  754. /* In DMA reload mode only start one time is enough */
  755. if (session->flags & AIN_SESSION_START) {
  756. LOG_DBG("session%p already started", session);
  757. return 0;
  758. }
  759. if (AUDIO_CHANNEL_ADC == session->channel_type) {
  760. if (data->adc_ref_counter) {
  761. if (data->adc_sess_stack_cur >= AIN_ADC_SESSION_MAX) {
  762. /* unlikely branch */
  763. LOG_ERR("FIXME: invlaid stack cur%d", data->adc_sess_stack_cur);
  764. return -EFAULT;
  765. }
  766. data->adc_sess_stack[data->adc_sess_stack_cur++] = (uint32_t)session;
  767. --data->adc_ref_counter;
  768. LOG_INF("session@%p save to wait stack[%d]", session, data->adc_ref_counter);
  769. return 0;
  770. }
  771. struct aduio_in_adc_en adc_en = {0};
  772. uint16_t input_dev[AIN_ADC_SESSION_MAX] = {0};
  773. adc_en.input_dev_array = input_dev;
  774. if (data->adc_sess_stack_cur > 0) {
  775. uint8_t i;
  776. ain_session_t *_sess = NULL;
  777. data->adc_sess_stack[data->adc_sess_stack_cur++] = (uint32_t)session;
  778. for (i = 0; i < data->adc_sess_stack_cur; i++) {
  779. _sess = (ain_session_t *)data->adc_sess_stack[i];
  780. if (!(_sess->flags & AIN_SESSION_CONFIG)
  781. || (_sess->flags & AIN_SESSION_START)
  782. || (_sess->channel_type != AUDIO_CHANNEL_ADC)) {
  783. /* unlikely branch */
  784. LOG_ERR("FIXME: invalid session@%p status:0x%x", _sess, _sess->flags);
  785. data->adc_sess_stack_cur = 0;
  786. return -ESRCH;
  787. }
  788. input_dev[i] = _sess->input_dev;
  789. }
  790. adc_en.input_dev_num = data->adc_sess_stack_cur;
  791. /* always set start flag regardless of the result of start */
  792. session->flags |= AIN_SESSION_START;
  793. ret = phy_audio_control(data->adc0_dev, PHY_CMD_ADC_DIGITAL_ENABLE, &adc_en);
  794. if (ret) {
  795. LOG_ERR("Failed to enable ADC err=%d", ret);
  796. data->adc_sess_stack_cur = 0;
  797. return ret;
  798. }
  799. for (i = 0; i < data->adc_sess_stack_cur; i++) {
  800. _sess = (ain_session_t *)data->adc_sess_stack[i];
  801. ret = audio_in_dma_prepare(dev, _sess);
  802. if (ret) {
  803. LOG_ERR("session@%p DMA prepare error=%d", session, ret);
  804. continue;
  805. }
  806. ret = dma_start(data->dma_dev, _sess->dma_chan);
  807. if (ret) {
  808. LOG_ERR("session@%p DMA start error:%d", _sess, ret);
  809. } else {
  810. LOG_INF("session@%p started", _sess);
  811. }
  812. }
  813. data->adc_sess_stack_cur = 0;
  814. } else {
  815. input_dev[0] = session->input_dev;
  816. adc_en.input_dev_num = 1;
  817. ret = phy_audio_control(data->adc0_dev, PHY_CMD_ADC_DIGITAL_ENABLE, &adc_en);
  818. if (ret) {
  819. LOG_ERR("Failed to enable ADC err=%d", ret);
  820. return ret;
  821. }
  822. ret = audio_in_dma_prepare(dev, session);
  823. if (ret) {
  824. LOG_ERR("session@%p DMA prepare error=%d", session, ret);
  825. return ret;
  826. }
  827. ret = dma_start(data->dma_dev, session->dma_chan);
  828. if (ret) {
  829. LOG_ERR("session@%p DMA start error:%d", session, ret);
  830. } else {
  831. LOG_INF("session@%p started", session);
  832. }
  833. }
  834. } else {
  835. session->flags |= AIN_SESSION_START;
  836. ret = audio_in_dma_prepare(dev, session);
  837. if (ret) {
  838. LOG_ERR("session@%p DMA prepare error=%d", session, ret);
  839. return ret;
  840. }
  841. ret = dma_start(data->dma_dev, session->dma_chan);
  842. if (ret) {
  843. LOG_ERR("session@%p DMA start error:%d", session, ret);
  844. } else {
  845. LOG_INF("session@%p started", session);
  846. }
  847. }
  848. return ret;
  849. }
  850. static int acts_audio_in_stop(struct device *dev, void *handle)
  851. {
  852. struct ain_drv_data *data = dev->data;
  853. ain_session_t *session = (ain_session_t *)handle;
  854. int ret = 0;
  855. if (session && AIN_SESSION_CHECK_MAGIC(session->magic)) {
  856. LOG_INF("session#%p, audio in stop", session);
  857. if (data->dma_dev && session->dma_chan)
  858. ret = dma_stop(data->dma_dev, session->dma_chan);
  859. }
  860. return ret;
  861. }
  862. const struct ain_driver_api ain_drv_api = {
  863. .ain_open = acts_audio_in_open,
  864. .ain_close = acts_audio_in_close,
  865. .ain_control = acts_audio_in_control,
  866. .ain_start = acts_audio_in_start,
  867. .ain_stop = acts_audio_in_stop
  868. };
  869. /* @brief audio-in channles initialization */
  870. static int audio_in_init(const struct device *dev)
  871. {
  872. const struct ain_config_data *cfg = dev->config;
  873. struct ain_drv_data *data = dev->data;
  874. memset(data, 0, sizeof(struct ain_drv_data));
  875. k_sem_init(&data->lock, 1, 1);
  876. #ifdef CONFIG_AUDIO_IN_ADC_SUPPORT
  877. data->adc0_dev = (struct device *)device_get_binding(cfg->adc0_name);
  878. if (!data->adc0_dev) {
  879. LOG_ERR("no ADC device(%s)", cfg->adc0_name);
  880. }
  881. #endif
  882. #ifdef CONFIG_AUDIO_IN_I2SRX_SUPPORT
  883. data->i2srx0_dev = (struct device *)device_get_binding(cfg->i2srx0_name);
  884. if (!data->i2srx0_dev) {
  885. LOG_ERR("no I2SRX device(%s)", cfg->i2srx0_name);
  886. }
  887. #endif
  888. #ifdef CONFIG_AUDIO_IN_SPDIFRX_SUPPORT
  889. data->spdifrx0_dev = (struct device *)device_get_binding(cfg->spdifrx0_name);
  890. if (!data->spdifrx0_dev) {
  891. LOG_ERR("no SPDIFRX device(%s)", cfg->spdifrx0_name);
  892. }
  893. #endif
  894. /* disable AVDD pulldown */
  895. sys_write32(sys_read32(AUDIOLDO_CTL) & ~(1 << 4), AUDIOLDO_CTL);
  896. printk("ACTS-AUDIO IN initialized\n");
  897. return 0;
  898. }
  899. static struct ain_drv_data audio_in_drv_data;
  900. static struct ain_config_data audio_in_config_data = {
  901. #ifdef CONFIG_AUDIO_IN_ADC_SUPPORT
  902. .adc0_name = CONFIG_AUDIO_ADC_0_NAME,
  903. #endif
  904. #ifdef CONFIG_AUDIO_IN_I2SRX_SUPPORT
  905. .i2srx0_name = CONFIG_AUDIO_I2SRX_0_NAME,
  906. #endif
  907. #ifdef CONFIG_AUDIO_IN_SPDIFRX_SUPPORT
  908. .spdifrx0_name = CONFIG_AUDIO_SPDIFRX_0_NAME,
  909. #endif
  910. };
  911. DEVICE_DEFINE(audio_in, CONFIG_AUDIO_IN_ACTS_DEV_NAME, audio_in_init,
  912. NULL,
  913. &audio_in_drv_data, &audio_in_config_data,
  914. POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &ain_drv_api);