audio_out_acts.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784
  1. /*
  2. * Copyright (c) 2020 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief Audio OUTPUT Channels (DAC/I2S-TX/SPDIF-TX/PDM-TX) core management layer.
  9. */
  10. #include <kernel.h>
  11. #include <device.h>
  12. #include <ksched.h>
  13. #include <string.h>
  14. #include <errno.h>
  15. #include <soc.h>
  16. #include <board_cfg.h>
  17. #include <drivers/dma.h>
  18. #include <drivers/audio/audio_out.h>
  19. #include "phy_audio_common.h"
  20. #include <logging/log.h>
  21. LOG_MODULE_REGISTER(aout, LOG_LEVEL_DBG);
  22. #ifdef CONFIG_BOARD_EXTERNAL_PA_ENABLE
  23. #include <board.h>
  24. #endif
  25. /* Audio out session resource definitions */
  26. #define AOUT_SESSION_MAGIC (0x1a2b3c4d)
  27. #define AOUT_SESSION_CHECK_MAGIC(x) ((x) == AOUT_SESSION_MAGIC)
  28. /* Audio output channel sessions which depends on different chipsets */
  29. #ifdef CONFIG_SOC_SERIES_PEARLRIVER
  30. #define AOUT_DAC_SESSION_MAX (0) /* 0 DAC */
  31. #define AOUT_I2STX_SESSION_MAX (1) /* 1 I2STX */
  32. #define AOUT_SPDIFTX_SESSION_MAX (0) /* 0 SPDIFTX */
  33. #define AOUT_PDMTX_SESSION_MAX (1) /* 1 PDMTX */
  34. #else
  35. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  36. #define AOUT_DAC_SESSION_MAX (2) /* 2 DAC */
  37. #else
  38. #define AOUT_DAC_SESSION_MAX (0)
  39. #endif
  40. #ifdef CONFIG_AUDIO_OUT_I2STX_SUPPORT
  41. #define AOUT_I2STX_SESSION_MAX (2) /* 1 I2STX */
  42. #else
  43. #define AOUT_I2STX_SESSION_MAX (0)
  44. #endif
  45. #ifdef CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT
  46. #define AOUT_SPDIFTX_SESSION_MAX (2) /* 1 SPDIFTX */
  47. #else
  48. #define AOUT_SPDIFTX_SESSION_MAX (0)
  49. #endif
  50. #define AOUT_PDMTX_SESSION_MAX (0) /* 0 PDMTX */
  51. #endif
  52. #define AOUT_SESSION_MAX (AOUT_DAC_SESSION_MAX + AOUT_I2STX_SESSION_MAX + \
  53. AOUT_SPDIFTX_SESSION_MAX + AOUT_PDMTX_SESSION_MAX) /* totally max sessions */
  54. #define AOUT_SESSION_OPEN (1 << 0) /* session open flag */
  55. #define AOUT_SESSION_CONFIG (1 << 1) /* session config flag */
  56. #define AOUT_SESSION_START (1 << 2) /* session start flag */
  57. #define AOUT_SESSION_WAIT_PA_TIMEOUT (2000) /* timeout of waitting pa session */
  58. #define DMA_IRQ_TC (0) /* DMA completion flag */
  59. #define DMA_IRQ_HF (1) /* DMA half-full flag */
  60. /* audio out io-commands following by the AUDIO FIFO usage */
  61. #define AOUT_IS_FIFO_CMD(x) ((x) & AOUT_FIFO_CMD_FLAG)
  62. /**
  63. * struct aout_dynamic_debug_t
  64. * @brief audio out session dynamic debug structure
  65. */
  66. typedef struct {
  67. uint32_t timestamp; /* record the per-second timestamp */
  68. uint32_t per_second_size; /* record the per-second play size */
  69. uint8_t dump_len; /* show the length of buffer per-second */
  70. uint8_t performance: 1; /* enable flag of showing the play performance */
  71. } aout_dynamic_debug_t;
  72. /**
  73. * struct aout_session_t
  74. * @brief audio out session structure
  75. */
  76. typedef struct {
  77. int magic; /* session magic value as AOUT_SESSION_MAGIC */
  78. int dma_chan; /* DMA channel handler */
  79. audio_outfifo_sel_e outfifo_type; /* indicator of the audio output fifo type */
  80. uint16_t channel_type; /* indicator of the channel type selection */
  81. uint16_t flags; /* session flags */
  82. int (*callback)(void *cb_data, uint32_t reason); /* callback function of the channel data link */
  83. void *cb_data; /* callback user data */
  84. uint8_t *reload_addr; /* reload buffer address to transfer */
  85. uint32_t reload_len; /* the length of the reload buffer */
  86. uint8_t sample_rate; /* the channel sample rate setting */
  87. uint8_t id; /* the session id */
  88. uint8_t dma_width; /* dma width */
  89. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  90. aout_dynamic_debug_t debug; /* dynamic debug */
  91. #endif
  92. uint8_t reload_en : 1; /* the flag of reload mode enable or not */
  93. uint8_t dma_separated_en : 1; /* the flag of DMA interleaved mode enable or not */
  94. uint8_t dsp_fifo_src : 1;
  95. } aout_session_t;
  96. /**
  97. * struct aout_drv_data
  98. * @brief The software related data that used by audio out driver.
  99. */
  100. struct aout_drv_data {
  101. struct k_sem lock; /* the semaphore to lock the channel resource */
  102. struct device *dma_dev; /* DMA device handler */
  103. struct device *dac0_dev; /* DAC0 device handler */
  104. struct device *i2stx0_dev; /* I2STX0 device handler */
  105. struct device *spdiftx0_dev; /* SPFITX0 device handler */
  106. struct device *pdmtx0_dev; /* PDMTX0 device handler */
  107. #ifdef CONFIG_AUDIO_PA_AW87390_SUPPORT
  108. struct device *pa_aw87390_dev;
  109. #endif
  110. uint8_t pa_session_indicator : 1; /* indicates the stage of the pa session operations */
  111. uint8_t dac_fifo_ref_counter : 2; /* DAC FIFO request by other's module reference counter */
  112. uint8_t external_pa_opened : 1; /* If 1 to indicate the external PA has already opened */
  113. };
  114. /**
  115. * struct aout_config_data
  116. * @brief The hardware related data that used by audio out driver.
  117. */
  118. struct aout_config_data {
  119. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  120. const char *dac0_name; /* physical DAC0 device name */
  121. #endif
  122. #ifdef CONFIG_AUDIO_OUT_I2STX_SUPPORT
  123. const char *i2stx0_name; /* physical I2STX0 device name */
  124. #endif
  125. #ifdef CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT
  126. const char *spdiftx0_name; /* physical SPDIFTX device name */
  127. #endif
  128. #ifdef CONFIG_AUDIO_OUT_PDMTX_SUPPORT
  129. const char *pdmtx0_name; /* physical PDMTX device name */
  130. #endif
  131. #ifdef CONFIG_AUDIO_PA_AW87390_SUPPORT
  132. const char *pa_aw87390_name;
  133. #endif
  134. };
  135. /* audio out sessions */
  136. static aout_session_t aout_sessions[AOUT_SESSION_MAX];
  137. /*
  138. * @brief check if there is the same channel within audio out sessions.
  139. * Moreover check whether the session type is invalid or not.
  140. */
  141. static bool audio_out_session_check(uint16_t type)
  142. {
  143. int i;
  144. aout_session_t *sess = aout_sessions;
  145. uint8_t max_sess, sess_opened = 0;
  146. if (AUDIO_CHANNEL_DAC & type) {
  147. max_sess = AOUT_DAC_SESSION_MAX;
  148. } else if (AUDIO_CHANNEL_I2STX & type) {
  149. max_sess = AOUT_I2STX_SESSION_MAX;
  150. } else if (AUDIO_CHANNEL_SPDIFTX & type) {
  151. max_sess = AOUT_SPDIFTX_SESSION_MAX;
  152. } else if (AUDIO_CHANNEL_PDMTX & type) {
  153. max_sess = AOUT_PDMTX_SESSION_MAX;
  154. } else {
  155. LOG_ERR("Invalid session type %d", type);
  156. return true;
  157. }
  158. /* check if max session is 0 */
  159. if (!max_sess) {
  160. LOG_ERR("type#%d max session (%d) forbidden", type, max_sess);
  161. return true;
  162. }
  163. /* find the session that already opened */
  164. for (i = 0; i < AOUT_SESSION_MAX; i++, sess++) {
  165. if (AOUT_SESSION_CHECK_MAGIC(sess->magic)
  166. && (sess->flags & AOUT_SESSION_OPEN)
  167. && (sess->channel_type & type)) {
  168. sess_opened++;
  169. LOG_DBG("Found aout channel type %d in use", type);
  170. }
  171. }
  172. /* check if the number of opened sessions is bigger than the max limit */
  173. if (sess_opened >= max_sess) {
  174. LOG_ERR("channel type:%d session max %d and opened %d",
  175. type, max_sess, sess_opened);
  176. return true;
  177. }
  178. return false;
  179. }
  180. /*
  181. * @brief Get audio out session by specified channel type.
  182. */
  183. static aout_session_t *audio_out_session_get(uint16_t type)
  184. {
  185. aout_session_t *sess = aout_sessions;
  186. int i;
  187. if (audio_out_session_check(type))
  188. return NULL;
  189. for (i = 0; i < AOUT_SESSION_MAX; i++, sess++) {
  190. if (!(sess->flags & AOUT_SESSION_OPEN)) {
  191. memset(sess, 0, sizeof(aout_session_t));
  192. sess->magic = AOUT_SESSION_MAGIC;
  193. sess->flags = AOUT_SESSION_OPEN;
  194. sess->channel_type = type;
  195. sess->id = i;
  196. sess->dma_chan = -1;
  197. sess->dsp_fifo_src = 0;
  198. return sess;
  199. }
  200. }
  201. return NULL;
  202. }
  203. /*
  204. * @brief Put audio out session by given session address
  205. */
  206. static void audio_out_session_put(aout_session_t *s)
  207. {
  208. aout_session_t *sess = aout_sessions;
  209. int i;
  210. for (i = 0; i < AOUT_SESSION_MAX; i++, sess++) {
  211. if ((uint32_t)s == (uint32_t)sess) {
  212. memset(s, 0, sizeof(aout_session_t));
  213. break;
  214. }
  215. }
  216. }
  217. /* @brief audio out session lock */
  218. static inline void audio_out_lock(struct device *dev)
  219. {
  220. struct aout_drv_data *data = dev->data;
  221. k_sem_take(&data->lock, K_FOREVER);
  222. }
  223. /* @brief audio out session unlock */
  224. static inline void audio_out_unlock(struct device *dev)
  225. {
  226. struct aout_drv_data *data = dev->data;
  227. k_sem_give(&data->lock);
  228. }
  229. #if defined(CONFIG_AUDIO_OUT_DAC_SUPPORT) || defined(CONFIG_AUDIO_POWERON_OPEN_I2STX)
  230. /* @brief the dummy callback for aout inner driver usage */
  231. static int acts_audio_dummy_callback(void *cb_data, uint32_t reason)
  232. {
  233. ARG_UNUSED(cb_data);
  234. ARG_UNUSED(reason);
  235. return 0;
  236. }
  237. #endif
  238. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  239. /* @brief wait the pa operations finish */
  240. static int acts_audio_wait_pa_session(struct device *dev, uint32_t timeout_ms)
  241. {
  242. struct aout_drv_data *data = dev->data;
  243. uint32_t start_time, curr_time;
  244. start_time = k_cycle_get_32();
  245. while (data->pa_session_indicator) {
  246. curr_time = k_cycle_get_32();
  247. if (k_cyc_to_us_floor32(curr_time - start_time)
  248. >= (timeout_ms * 1000)) {
  249. LOG_ERR("wait pa session timeout");
  250. return -ETIMEDOUT;
  251. }
  252. /* PM works in IDLE thread and not allow to sleep */
  253. if (!z_is_idle_thread_object(_current))
  254. k_sleep(K_MSEC(2));
  255. }
  256. return 0;
  257. }
  258. /* @brief open a pa session to power charge the DAC digital and analog part */
  259. static void *acts_audio_open_pa_session(struct device *dev)
  260. {
  261. aout_param_t aout_setting = {0};
  262. dac_setting_t dac_setting = {0};
  263. void *handle;
  264. aout_setting.sample_rate = SAMPLE_RATE_48KHZ;
  265. aout_setting.channel_type = AUDIO_CHANNEL_DAC;
  266. aout_setting.channel_width = CHANNEL_WIDTH_16BITS;
  267. aout_setting.callback = acts_audio_dummy_callback;
  268. aout_setting.cb_data = (void *)dev;
  269. dac_setting.channel_mode = MONO_MODE;
  270. aout_setting.dac_setting = &dac_setting;
  271. handle = audio_out_open(dev, &aout_setting);
  272. #ifdef CONFIG_BOARD_EXTERNAL_PA_ENABLE
  273. struct aout_drv_data *data = dev->data;
  274. if (handle)
  275. data->pa_session_indicator = 1;
  276. #endif
  277. return handle;
  278. }
  279. /* @brief close the pa session */
  280. static void acts_audio_close_pa_session(struct device *dev, void *hdl)
  281. {
  282. audio_out_close(dev, hdl);
  283. #ifdef CONFIG_BOARD_EXTERNAL_PA_ENABLE
  284. struct aout_drv_data *data = dev->data;
  285. data->pa_session_indicator = 0;
  286. #endif
  287. }
  288. #ifdef CONFIG_BOARD_EXTERNAL_PA_ENABLE
  289. /* @brief open external PA */
  290. static void acts_audio_open_external_pa(struct device *dev, bool force)
  291. {
  292. struct aout_drv_data *data = dev->data;
  293. if (((!data->external_pa_opened) && (!data->pa_session_indicator)) || (force)) {
  294. board_extern_pa_ctl(CONFIG_EXTERN_PA_CLASS, true);
  295. data->external_pa_opened = 1;
  296. }
  297. }
  298. /* @brief close external PA */
  299. static void acts_audio_close_external_pa(struct device *dev)
  300. {
  301. struct aout_drv_data *data = dev->data;
  302. if (data->external_pa_opened) {
  303. board_extern_pa_ctl(CONFIG_EXTERN_PA_CLASS, false);
  304. data->external_pa_opened = 0;
  305. }
  306. }
  307. #endif
  308. /* @brief open the DAC internal and external PA */
  309. static int acts_audio_open_pa(struct device *dev, bool open_exteranl_pa)
  310. {
  311. void *pa_session = NULL;
  312. uint32_t pcm_data = 0;
  313. uint8_t i = 0;
  314. struct aout_drv_data *data = dev->data;
  315. phy_audio_control(data->dac0_dev, AOUT_CMD_OPEN_PA, NULL);
  316. pa_session = acts_audio_open_pa_session(dev);
  317. if (!pa_session) {
  318. LOG_ERR("Failed to open pa session");
  319. return -ENXIO;
  320. }
  321. /* FIXME: it is necessary to send some samples(zero data) when startup
  322. * to avoid the noise with probability.
  323. */
  324. for (i = 0; i < 16; i++) // TODO check this issue!!
  325. audio_out_write(dev, pa_session, (uint8_t *)&pcm_data, 4);
  326. #ifdef CONFIG_BOARD_EXTERNAL_PA_ENABLE
  327. if (open_exteranl_pa)
  328. acts_audio_open_external_pa(dev, true);
  329. #endif
  330. acts_audio_close_pa_session(dev, pa_session);
  331. LOG_INF("Open PA successfully");
  332. return 0;
  333. }
  334. /* @brief close DAC internal and external PA */
  335. static int acts_audio_close_pa(struct device *dev)
  336. {
  337. void *pa_session = NULL;
  338. struct aout_drv_data *data = dev->data;
  339. pa_session = acts_audio_open_pa_session(dev);
  340. if (!pa_session) {
  341. LOG_ERR("Failed to open pa session");
  342. return -ENXIO;
  343. }
  344. /* close external pa */
  345. #ifdef CONFIG_BOARD_EXTERNAL_PA_ENABLE
  346. acts_audio_close_external_pa(dev);
  347. #endif
  348. acts_audio_close_pa_session(dev, pa_session);
  349. /* close internal pa */
  350. phy_audio_control(data->dac0_dev, AOUT_CMD_CLOSE_PA, NULL);
  351. LOG_INF("Close PA successfully");
  352. return 0;
  353. }
  354. static int acts_audio_pa_class_select(struct device *dev, uint8_t pa_class)
  355. {
  356. ARG_UNUSED(dev);
  357. #ifdef CONFIG_BOARD_EXTERNAL_PA_ENABLE
  358. return board_extern_pa_ctl(pa_class, true);
  359. #else
  360. return -1;
  361. #endif
  362. }
  363. #endif
  364. #ifdef CONFIG_AUDIO_POWERON_OPEN_I2STX
  365. static int acts_audio_open_i2stx_dev(struct device *dev)
  366. {
  367. aout_param_t aout_setting = {0};
  368. i2stx_setting_t i2stx_setting = {0};
  369. void *handle;
  370. aout_setting.sample_rate = SAMPLE_RATE_48KHZ;
  371. aout_setting.channel_type = AUDIO_CHANNEL_I2STX;
  372. aout_setting.channel_width = CHANNEL_WIDTH_16BITS;
  373. aout_setting.callback = acts_audio_dummy_callback;
  374. aout_setting.cb_data = (void *)dev;
  375. i2stx_setting.mode = I2S_MASTER_MODE;
  376. aout_setting.i2stx_setting = &i2stx_setting;
  377. handle = audio_out_open(dev, &aout_setting);
  378. /* close interface will not disable i2stx truly*/
  379. audio_out_close(dev, handle);
  380. return 0;
  381. }
  382. static int acts_audio_close_i2stx_dev(struct device *dev)
  383. {
  384. struct aout_drv_data *data = dev->data;
  385. phy_audio_control(data->i2stx, AOUT_CMD_CLOSE_I2STX_DEVICE, NULL);
  386. return 0;
  387. }
  388. #endif
  389. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  390. /* @brief show the audio out performance */
  391. static void audio_out_debug_perf(aout_session_t *session, uint8_t *buffer, uint32_t len)
  392. {
  393. uint32_t delta;
  394. if (session->debug.performance) {
  395. delta = (uint32_t)k_cyc_to_ns_floor64(k_cycle_get_32() - session->debug.timestamp);
  396. session->debug.per_second_size += len;
  397. if (delta > 1000000000UL) {
  398. session->debug.timestamp = k_cycle_get_32();
  399. LOG_INF("** out session@%p - %dB/s **\n",
  400. session, session->debug.per_second_size);
  401. session->debug.per_second_size = 0;
  402. if (session->debug.dump_len) {
  403. AUDIO_DUMP_MEM(buffer, session->debug.dump_len);
  404. }
  405. }
  406. }
  407. }
  408. /* @brief control all sessions to enable or disable performance statistics */
  409. static int audio_out_debug_perf_all_sessions(uint8_t is_en)
  410. {
  411. int i;
  412. aout_session_t *sess = aout_sessions;
  413. for (i = 0; i < AOUT_SESSION_MAX; i++, sess++) {
  414. if (AOUT_SESSION_CHECK_MAGIC(sess->magic)
  415. && (sess->flags & AOUT_SESSION_OPEN)) {
  416. LOG_INF("session@%p perf debug status %d", sess, is_en);
  417. sess->debug.performance = is_en;
  418. sess->debug.per_second_size = 0;
  419. sess->debug.timestamp = 0;
  420. sess->debug.dump_len = 0;
  421. }
  422. }
  423. return 0;
  424. }
  425. /* @brief control all sessions to set the dump length per second */
  426. static int audio_out_debug_dump_length(uint8_t length)
  427. {
  428. int i;
  429. aout_session_t *sess = aout_sessions;
  430. for (i = 0; i < AOUT_SESSION_MAX; i++, sess++) {
  431. if (AOUT_SESSION_CHECK_MAGIC(sess->magic)
  432. && (sess->flags & AOUT_SESSION_OPEN)) {
  433. sess->debug.dump_len = length;
  434. }
  435. }
  436. return 0;
  437. }
  438. #endif
  439. /* @brief Enable the DAC channel */
  440. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  441. static int audio_out_enable_dac(struct device *dev, aout_session_t *session, aout_param_t *param)
  442. {
  443. uint8_t channel_type = param->channel_type;
  444. struct aout_drv_data *data = dev->data;
  445. struct device *dac = data->dac0_dev;
  446. dac_setting_t *dac_setting = param->dac_setting;
  447. if (!dac) {
  448. LOG_ERR("no dac device");
  449. return -ENXIO;
  450. }
  451. if (!dac_setting) {
  452. LOG_ERR("DAC setting is NULL");
  453. return -EINVAL;
  454. }
  455. /* Check the DAC FIFO usage */
  456. if ((param->outfifo_type != AOUT_FIFO_DAC0)
  457. && (param->outfifo_type != AOUT_FIFO_DAC1)) {
  458. LOG_ERR("Channel fifo type invalid %d", param->outfifo_type);
  459. return -EINVAL;
  460. }
  461. if ((param->channel_width != CHANNEL_WIDTH_16BITS)
  462. && (param->channel_width != CHANNEL_WIDTH_24BITS)) {
  463. LOG_ERR("Invalid channel width %d", param->channel_width);
  464. return -EINVAL;
  465. }
  466. /* Linkage with I2STX */
  467. if (channel_type & AUDIO_CHANNEL_I2STX) {
  468. if (!data->i2stx0_dev) {
  469. LOG_ERR("no i2stx device");
  470. return -ENXIO;
  471. }
  472. if (phy_audio_enable(data->i2stx0_dev, (void *)param)) {
  473. LOG_ERR("Failed to enable I2STX");
  474. return -EFAULT;
  475. }
  476. else
  477. return 0;
  478. }
  479. /* Linkage with SPDIFTX */
  480. if (channel_type & AUDIO_CHANNEL_SPDIFTX) {
  481. if (!data->spdiftx0_dev) {
  482. LOG_ERR("no spdiftx device");
  483. return -ENXIO;
  484. }
  485. if (!phy_audio_enable(data->spdiftx0_dev, (void *)param))
  486. phy_audio_control(dac, PHY_CMD_CLAIM_WITH_128FS, NULL);
  487. }
  488. return phy_audio_enable(dac, (void *)param);
  489. }
  490. #endif
  491. /* @brief Claim the use of the DAC/I2STX/PDMTX FIFO */
  492. #if defined(CONFIG_AUDIO_OUT_I2STX_SUPPORT) \
  493. || defined(CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT)
  494. static int audio_out_fifo_request(struct device *dev, aout_param_t *param)
  495. {
  496. if (!dev)
  497. return -EINVAL;
  498. if (phy_audio_control(dev, PHY_CMD_FIFO_GET, param)) {
  499. LOG_ERR("Request FIFO failed");
  500. return -EBUSY;
  501. }
  502. return 0;
  503. }
  504. /* @brief Release the use of the DAC/I2STX FIFO */
  505. static int audio_out_fifo_release(struct device *dev, uint8_t idx)
  506. {
  507. if (!dev)
  508. return -EINVAL;
  509. if (phy_audio_control(dev, PHY_CMD_FIFO_PUT, &idx)) {
  510. LOG_ERR("Release DAC FIFO failed");
  511. return -EFAULT;
  512. }
  513. return 0;
  514. }
  515. #endif
  516. /* @brief Enable the I2STX channel */
  517. #ifdef CONFIG_AUDIO_OUT_I2STX_SUPPORT
  518. static int audio_out_enable_i2stx(struct device *dev, aout_session_t *session, aout_param_t *param)
  519. {
  520. uint8_t channel_type = param->channel_type;
  521. struct aout_drv_data *data = dev->data;
  522. struct device *i2stx = data->i2stx0_dev;
  523. i2stx_setting_t *i2stx_setting = param->i2stx_setting;
  524. int ret;
  525. if (!i2stx) {
  526. LOG_ERR("no i2s-tx device");
  527. return -ENXIO;
  528. }
  529. if (!i2stx_setting) {
  530. LOG_ERR("I2STX setting is NULL");
  531. return -EINVAL;
  532. }
  533. /* Check the DAC FIFO usage */
  534. if ((param->outfifo_type != AOUT_FIFO_DAC0)
  535. && (param->outfifo_type != AOUT_FIFO_DAC1)
  536. && (param->outfifo_type != AOUT_FIFO_I2STX0)) {
  537. LOG_ERR("Channel fifo type invalid %d", param->outfifo_type);
  538. return -EINVAL;
  539. }
  540. if ((param->channel_width != CHANNEL_WIDTH_16BITS)
  541. && (param->channel_width != CHANNEL_WIDTH_24BITS)
  542. && (param->channel_width != CHANNEL_WIDTH_20BITS)) {
  543. LOG_ERR("Invalid channel width %d", param->channel_width);
  544. return -EINVAL;
  545. }
  546. /* Linkage with SPDIFTX */
  547. if (channel_type & AUDIO_CHANNEL_SPDIFTX) {
  548. if (!data->spdiftx0_dev) {
  549. LOG_ERR("no spdiftx device");
  550. return -ENXIO;
  551. }
  552. if (!phy_audio_enable(data->spdiftx0_dev, param))
  553. phy_audio_control(data->dac0_dev, PHY_CMD_CLAIM_WITH_128FS, NULL);
  554. }
  555. if ((AOUT_FIFO_DAC0 == param->outfifo_type)
  556. || (AOUT_FIFO_DAC1 == param->outfifo_type)) {
  557. if (audio_out_fifo_request(data->dac0_dev, param)) {
  558. LOG_ERR("Failed to take DAC FIFO");
  559. return -ENXIO;
  560. }
  561. ++data->dac_fifo_ref_counter;
  562. }
  563. ret = phy_audio_enable(i2stx, (void *)param);
  564. if (ret) {
  565. if ((AOUT_FIFO_DAC0 == param->outfifo_type)
  566. || (AOUT_FIFO_DAC1 == param->outfifo_type)) {
  567. audio_out_fifo_release(data->dac0_dev, param->outfifo_type);
  568. --data->dac_fifo_ref_counter;
  569. }
  570. }
  571. return ret;
  572. }
  573. #endif
  574. /* @brief Enable the SPDIFTX channel */
  575. #ifdef CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT
  576. static int audio_out_enable_spdiftx(struct device *dev, aout_session_t *session, aout_param_t *param)
  577. {
  578. struct aout_drv_data *data = dev->data;
  579. struct device *spdiftx = data->spdiftx0_dev;
  580. spdiftx_setting_t *spdiftx_setting = param->spdiftx_setting;
  581. audio_dma_width_e width;
  582. int ret;
  583. if ((param->channel_width != CHANNEL_WIDTH_16BITS)
  584. && (param->channel_width != CHANNEL_WIDTH_24BITS)) {
  585. LOG_ERR("Invalid channel width %d", param->channel_width);
  586. return -EINVAL;
  587. }
  588. if (param->channel_width == CHANNEL_WIDTH_16BITS)
  589. width = DMA_WIDTH_16BITS;
  590. else
  591. width = DMA_WIDTH_32BITS;
  592. if (!spdiftx) {
  593. LOG_ERR("Physical SPDIFTX device is not esixted");
  594. return -EFAULT;
  595. }
  596. if (!spdiftx_setting) {
  597. LOG_ERR("SPDIFTX setting is NULL");
  598. return -EINVAL;
  599. }
  600. /* Check the DAC FIFO usage */
  601. if ((param->outfifo_type != AOUT_FIFO_DAC0)
  602. && (param->outfifo_type != AOUT_FIFO_DAC1)
  603. && (param->outfifo_type != AOUT_FIFO_I2STX0)
  604. && (param->outfifo_type != AOUT_FIFO_DAC1_ONLY_SPDIF)) {
  605. LOG_ERR("Channel fifo type invalid %d", param->outfifo_type);
  606. return -EINVAL;
  607. }
  608. if ((AOUT_FIFO_DAC0 == param->outfifo_type)
  609. || (AOUT_FIFO_DAC1 == param->outfifo_type)
  610. || (AOUT_FIFO_DAC1_ONLY_SPDIF == param->outfifo_type)) {
  611. if (!data->dac0_dev) {
  612. LOG_ERR("no dac device");
  613. return -ENXIO;
  614. }
  615. if (audio_out_fifo_request(data->dac0_dev, param)) {
  616. LOG_ERR("Failed to take DAC FIFO");
  617. return -ENXIO;
  618. }
  619. ++data->dac_fifo_ref_counter;
  620. } else if (AOUT_FIFO_I2STX0 == param->outfifo_type) {
  621. if (!data->i2stx0_dev) {
  622. LOG_ERR("no i2stx device");
  623. return -ENXIO;
  624. }
  625. if (audio_out_fifo_request(data->i2stx0_dev, param)) {
  626. LOG_ERR("Failed to take I2STX FIFO");
  627. return -ENXIO;
  628. }
  629. }
  630. phy_audio_control(data->dac0_dev, PHY_CMD_CLAIM_WITH_128FS, NULL);
  631. ret = phy_audio_enable(spdiftx, (void *)param);
  632. if (ret) {
  633. if ((AOUT_FIFO_DAC0 == param->outfifo_type)
  634. || (AOUT_FIFO_DAC1 == param->outfifo_type)
  635. || (AOUT_FIFO_DAC1_ONLY_SPDIF == param->outfifo_type)) {
  636. audio_out_fifo_release(data->dac0_dev, param->outfifo_type);
  637. --data->dac_fifo_ref_counter;
  638. }
  639. else if (AOUT_FIFO_I2STX0 == param->outfifo_type)
  640. audio_out_fifo_release(data->i2stx0_dev, param->outfifo_type);
  641. }
  642. return ret;
  643. }
  644. #endif
  645. /* @brief Enable the PDMTX channel */
  646. #ifdef CONFIG_AUDIO_OUT_PDMTX_SUPPORT
  647. static int audio_out_enable_pdmtx(struct device *dev, aout_session_t *session, aout_param_t *param)
  648. {
  649. uint8_t channel_type = param->channel_type;
  650. struct aout_drv_data *data = dev->data;
  651. struct device *pdmtx = data->pdmtx0_dev;
  652. int ret;
  653. if (!pdmtx) {
  654. LOG_ERR("no pdm-tx device");
  655. return -ENXIO;
  656. }
  657. if (channel_type != AUDIO_CHANNEL_PDMTX) {
  658. LOG_ERR("invalid channel type:0x%x", channel_type);
  659. return -EINVAL;
  660. }
  661. /* Check the DAC FIFO usage */
  662. if (param->outfifo_type != AOUT_FIFO_I2STX0) {
  663. LOG_ERR("Channel fifo type invalid %d", param->outfifo_type);
  664. return -EINVAL;
  665. }
  666. if (param->channel_width != CHANNEL_WIDTH_16BITS) {
  667. LOG_ERR("Invalid channel width %d", param->channel_width);
  668. return -EINVAL;
  669. }
  670. ret = phy_audio_enable(pdmtx, (void *)param);
  671. if (ret)
  672. LOG_ERR("physical pdmtx enable error:%d", ret);
  673. return ret;
  674. }
  675. #endif
  676. /* @brief DMA irq callback on direct method */
  677. static void audio_out_dma_direct(const struct device *dev, void *user_data,
  678. uint32_t channel, int status)
  679. {
  680. aout_session_t *session = (aout_session_t *)user_data;
  681. uint32_t key;
  682. ARG_UNUSED(dev);
  683. ARG_UNUSED(channel);
  684. if (session && AOUT_SESSION_CHECK_MAGIC(session->magic)) {
  685. /* Only notify when DMA transfer completly */
  686. if ((status == DMA_IRQ_TC) && session->callback) {
  687. key = irq_lock();
  688. session->callback(session->cb_data, AOUT_DMA_IRQ_TC);
  689. irq_unlock(key);
  690. }
  691. }
  692. }
  693. /* @brief DMA irq callback on reload method */
  694. static void audio_out_dma_reload(const struct device *dev, void *user_data,
  695. uint32_t channel, int status)
  696. {
  697. aout_session_t *session = (aout_session_t *)user_data;
  698. uint32_t ret_reason;
  699. int ret;
  700. ARG_UNUSED(dev);
  701. ARG_UNUSED(channel);
  702. if (session && AOUT_SESSION_CHECK_MAGIC(session->magic)) {
  703. if (session->callback) {
  704. if (status == DMA_IRQ_HF) {
  705. ret_reason = AOUT_DMA_IRQ_HF;
  706. } else if (status == DMA_IRQ_TC){
  707. ret_reason = AOUT_DMA_IRQ_TC;
  708. } else {
  709. LOG_ERR("Unknown DMA reson %d", status);
  710. return ;
  711. }
  712. ret = session->callback(session->cb_data, ret_reason);
  713. if (ret < 0)
  714. LOG_DBG("reload callback error:%d", ret);
  715. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  716. audio_out_debug_perf(session, session->reload_addr,
  717. session->reload_len / 2);
  718. #endif
  719. }
  720. }
  721. }
  722. /* @brief audio out dma enable interleaved mode */
  723. static void audio_out_dma_separated_enable(struct device *dev, aout_session_t *session)
  724. {
  725. ARG_UNUSED(dev);
  726. if (session) {
  727. LOG_INF("Enable AOUT DMA separated mode");
  728. session->dma_separated_en = 1;
  729. }
  730. }
  731. /* @brief prepare the DMA configuration for the audio out transfer */
  732. static int audio_out_dma_prepare(struct device *dev, aout_session_t *session)
  733. {
  734. struct aout_drv_data *data = dev->data;
  735. struct dma_config dma_cfg = {0};
  736. struct dma_block_config dma_block_cfg = {0};
  737. struct audio_out_dma_info info = {0};
  738. /* check already configured */
  739. if (session->flags & AOUT_SESSION_CONFIG)
  740. return 0;
  741. dma_cfg.channel_direction = MEMORY_TO_PERIPHERAL;
  742. dma_cfg.source_burst_length = 8;
  743. dma_cfg.dest_burst_length = 8;
  744. dma_block_cfg.source_reload_en = session->reload_en;
  745. dma_cfg.head_block = &dma_block_cfg;
  746. dma_cfg.source_data_size = session->dma_width;
  747. info.fifo_type = session->outfifo_type;
  748. if ((AOUT_FIFO_DAC0 == session->outfifo_type)
  749. || (AOUT_FIFO_DAC1 == session->outfifo_type)
  750. || (AOUT_FIFO_DAC1_ONLY_SPDIF == session->outfifo_type)) {
  751. if (phy_audio_control(data->dac0_dev, PHY_CMD_GET_AOUT_DMA_INFO, &info)) {
  752. LOG_ERR("Failed to get DAC DMA info");
  753. return -EFAULT;
  754. }
  755. uint8_t level, fifo_type = session->outfifo_type;
  756. if (fifo_type == AOUT_FIFO_DAC1_ONLY_SPDIF)
  757. fifo_type = AOUT_FIFO_DAC1;
  758. uint32_t fifo_cmd = PHY_FIFO_CMD(fifo_type, 0);
  759. if (!phy_audio_control(data->dac0_dev,
  760. PHY_CMD_FIFO_DRQ_LEVEL_GET, &fifo_cmd)) {
  761. level = PHY_GET_FIFO_CMD_VAL(fifo_cmd);
  762. LOG_DBG("DRQ level %d", level);
  763. /* When DRQ level < 8 levels shall use DMA single mode */
  764. if (level < 3)
  765. dma_cfg.dest_burst_length = 1;
  766. } else {
  767. LOG_ERR("Failed to get DRQ level");
  768. return -EFAULT;
  769. }
  770. } else if (AOUT_FIFO_I2STX0 == session->outfifo_type) {
  771. if (phy_audio_control(data->i2stx0_dev, PHY_CMD_GET_AOUT_DMA_INFO, &info)) {
  772. LOG_ERR("Failed to get I2STX DMA info");
  773. return -EFAULT;
  774. }
  775. }
  776. if (!data->dma_dev) {
  777. data->dma_dev = (struct device *)device_get_binding(info.dma_info.dma_dev_name);
  778. if (!data->dma_dev) {
  779. LOG_ERR("Bind DMA device %s error", info.dma_info.dma_dev_name);
  780. return -ENOENT;
  781. }
  782. }
  783. /* request dma channel handle */
  784. session->dma_chan = dma_request(data->dma_dev, 0xFF);
  785. if (session->dma_chan < 0) {
  786. LOG_ERR("Failed to request dma channel");
  787. return -ENXIO;
  788. }
  789. dma_cfg.dma_slot = info.dma_info.dma_id;
  790. #ifdef CONFIG_AUDIO_OUT_DAC_PCMBUF_SUPPORT
  791. if ((AOUT_FIFO_DAC0 != session->outfifo_type)
  792. && (AOUT_FIFO_DAC1 != session->outfifo_type))
  793. #endif
  794. {
  795. if (session->callback) {
  796. if (session->reload_en)
  797. dma_cfg.dma_callback = audio_out_dma_reload;
  798. else
  799. dma_cfg.dma_callback = audio_out_dma_direct;
  800. dma_cfg.user_data = session;
  801. dma_cfg.complete_callback_en = 1;
  802. }
  803. }
  804. if (session->dma_separated_en) {
  805. dma_cfg.reserved = 1;
  806. }
  807. if (dma_config(data->dma_dev, session->dma_chan, &dma_cfg)) {
  808. LOG_ERR("DMA config error");
  809. return -EFAULT;
  810. }
  811. if (session->reload_en) {
  812. if (session->dma_separated_en) {
  813. dma_reload(data->dma_dev, session->dma_chan,
  814. (uint32_t)session->reload_addr,
  815. (uint32_t)session->reload_addr, session->reload_len * 2);
  816. } else {
  817. dma_reload(data->dma_dev, session->dma_chan,
  818. (uint32_t)session->reload_addr, 0, session->reload_len);
  819. }
  820. }
  821. LOG_DBG("request DMA channel:0x%x, DMA slot:%d", session->dma_chan, dma_cfg.dma_slot);
  822. session->flags |= AOUT_SESSION_CONFIG;
  823. return 0;
  824. }
  825. /* @brief audio out open and return the session handler */
  826. static void *acts_audio_out_open(struct device *dev, aout_param_t *param)
  827. {
  828. aout_session_t *session = NULL;
  829. struct aout_drv_data *data = dev->data;
  830. struct device *dac = data->dac0_dev;
  831. dac_fifosrc_setting_t def_dac_fifosrc;
  832. uint8_t channel_type;
  833. int ret;
  834. if (!param) {
  835. LOG_ERR("NULL parameter");
  836. return NULL;
  837. }
  838. #ifdef CONFIG_AUDIO_PA_AW87390_SUPPORT
  839. phy_audio_enable(data->pa_aw87390_dev,NULL);
  840. #endif
  841. /* There is a 120ms yield scheduer under extern pa operation and need to wait until the pa session close */
  842. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  843. if (acts_audio_wait_pa_session(dev, AOUT_SESSION_WAIT_PA_TIMEOUT))
  844. return NULL;
  845. #endif
  846. audio_out_lock(dev);
  847. channel_type = param->channel_type;
  848. session = audio_out_session_get(channel_type);
  849. if (!session) {
  850. LOG_ERR("Failed to get audio session (type:%d)", channel_type);
  851. audio_out_unlock(dev);
  852. return NULL;
  853. }
  854. if (!param->callback) {
  855. LOG_ERR("Channel callback is NULL");
  856. goto err;
  857. }
  858. session->outfifo_type = param->outfifo_type;
  859. session->sample_rate = param->sample_rate;
  860. session->channel_type = channel_type;
  861. session->callback = param->callback;
  862. session->cb_data = param->cb_data;
  863. def_dac_fifosrc.fifo_idx = session->id;
  864. def_dac_fifosrc.fifo_from_dsp = session->dsp_fifo_src;
  865. def_dac_fifosrc.dsp_audio_set_param = NULL;
  866. session->dma_width = (CHANNEL_WIDTH_16BITS == param->channel_width) ? 2 : 4;
  867. if (param->reload_setting) {
  868. if ((!param->reload_setting->reload_addr)
  869. || (!param->reload_setting->reload_len)) {
  870. LOG_ERR("Invalid reload parameter addr:0x%x, len:0x%x",
  871. (uint32_t)param->reload_setting->reload_addr,
  872. param->reload_setting->reload_len);
  873. goto err;
  874. }
  875. session->reload_en = 1;
  876. session->reload_addr = param->reload_setting->reload_addr;
  877. session->reload_len = param->reload_setting->reload_len;
  878. LOG_INF("In reload mode [0x%08x %d]",
  879. (uint32_t)session->reload_addr, session->reload_len);
  880. } else {
  881. session->reload_en = 0;
  882. }
  883. if (channel_type & AUDIO_CHANNEL_DAC) {
  884. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  885. ret = audio_out_enable_dac(dev, session, param);
  886. phy_audio_control(dac, AOUT_CMD_SET_FIFO_SRC, &def_dac_fifosrc);
  887. #else
  888. ret = -ENXIO;
  889. #endif
  890. } else if (channel_type & AUDIO_CHANNEL_I2STX) {
  891. #ifdef CONFIG_AUDIO_OUT_I2STX_SUPPORT
  892. ret = audio_out_enable_i2stx(dev, session, param);
  893. #else
  894. ret = -ENXIO;
  895. #endif
  896. } else if (channel_type & AUDIO_CHANNEL_SPDIFTX) {
  897. #ifdef CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT
  898. ret = audio_out_enable_spdiftx(dev, session, param);
  899. #else
  900. ret = -ENXIO;
  901. #endif
  902. } else if (channel_type & AUDIO_CHANNEL_PDMTX) {
  903. #ifdef CONFIG_AUDIO_OUT_PDMTX_SUPPORT
  904. ret = audio_out_enable_pdmtx(dev, session, param);
  905. #else
  906. ret = -ENXIO;
  907. #endif
  908. } else {
  909. LOG_ERR("Invalid channel type %d", channel_type);
  910. goto err;
  911. }
  912. if (ret) {
  913. LOG_ERR("Enable channel type %d error:%d", channel_type, ret);
  914. goto err;
  915. }
  916. LOG_INF("channel@%d sess:%p type:%d fifo:%d sr:%d opened",
  917. session->id, session, channel_type,
  918. param->outfifo_type, param->sample_rate);
  919. audio_out_unlock(dev);
  920. return (void *)session;
  921. err:
  922. audio_out_session_put(session);
  923. audio_out_unlock(dev);
  924. return NULL;
  925. }
  926. /* @brief Disable the DAC channel */
  927. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  928. static int audio_out_disable_dac(struct device *dev, aout_session_t *session)
  929. {
  930. struct aout_drv_data *data = dev->data;
  931. struct device *dac = data->dac0_dev;
  932. uint8_t fifo_idx = session->outfifo_type;
  933. if (!dac) {
  934. LOG_ERR("no dac device");
  935. return -EFAULT;
  936. }
  937. if (session->channel_type & AUDIO_CHANNEL_SPDIFTX)
  938. phy_audio_control(dac, PHY_CMD_CLAIM_WITHOUT_128FS, NULL);
  939. #if defined(CONFIG_BOARD_EXTERNAL_PA_ENABLE) && (CONFIG_AUDIO_DAC_POWER_PREFERRED == 1)
  940. acts_audio_close_external_pa(dev);
  941. #endif
  942. return phy_audio_disable(dac, &fifo_idx);
  943. }
  944. #endif
  945. /* @brief Disable the I2STX channel */
  946. #ifdef CONFIG_AUDIO_OUT_I2STX_SUPPORT
  947. static int audio_out_disable_i2stx(struct device *dev, aout_session_t *session)
  948. {
  949. struct aout_drv_data *data = dev->data;
  950. struct device *i2stx = data->i2stx0_dev;
  951. uint8_t fifo_idx = session->outfifo_type;
  952. if (!i2stx) {
  953. LOG_ERR("Physical I2STX device is not esixted");
  954. return -EFAULT;
  955. }
  956. if ((AOUT_FIFO_DAC0 == session->outfifo_type)
  957. || (AOUT_FIFO_DAC1 == session->outfifo_type)) {
  958. audio_out_fifo_release(data->dac0_dev, fifo_idx);
  959. --data->dac_fifo_ref_counter;
  960. }
  961. if (data->dac_fifo_ref_counter) {
  962. LOG_INF("Still remain %d DAC FIFO now is using", data->dac_fifo_ref_counter);
  963. return 0;
  964. }
  965. if (session->channel_type & AUDIO_CHANNEL_SPDIFTX)
  966. phy_audio_control(data->dac0_dev, PHY_CMD_CLAIM_WITHOUT_128FS, NULL);
  967. return phy_audio_disable(i2stx, NULL);
  968. }
  969. #endif
  970. /* @brief Disable the SPDIFTX channel */
  971. #ifdef CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT
  972. static int audio_out_disable_spdiftx(struct device *dev, aout_session_t *session)
  973. {
  974. struct aout_drv_data *data = dev->data;
  975. struct device *spdiftx = data->spdiftx0_dev;
  976. uint8_t fifo_idx = session->outfifo_type;
  977. if (!spdiftx) {
  978. LOG_ERR("Physical SPDIFTX device is not esixted");
  979. return -EFAULT;
  980. }
  981. if ((AOUT_FIFO_DAC0 == session->outfifo_type)
  982. || (AOUT_FIFO_DAC1 == session->outfifo_type)
  983. || (AOUT_FIFO_DAC1_ONLY_SPDIF == session->outfifo_type)) {
  984. audio_out_fifo_release(data->dac0_dev, fifo_idx);
  985. --data->dac_fifo_ref_counter;
  986. } else if (AOUT_FIFO_I2STX0 == session->outfifo_type) {
  987. audio_out_fifo_release(data->i2stx0_dev, fifo_idx);
  988. }
  989. if (data->dac_fifo_ref_counter) {
  990. LOG_INF("Still remain %d DAC FIFO now is using", data->dac_fifo_ref_counter);
  991. return 0;
  992. }
  993. phy_audio_control(data->dac0_dev, PHY_CMD_CLAIM_WITHOUT_128FS, NULL);
  994. return phy_audio_disable(spdiftx, NULL);
  995. }
  996. #endif
  997. #ifdef CONFIG_AUDIO_OUT_PDMTX_SUPPORT
  998. static int audio_out_disable_pdmtx(struct device *dev, aout_session_t *session)
  999. {
  1000. struct aout_drv_data *data = dev->data;
  1001. struct device *pdmtx = data->pdmtx0_dev;
  1002. if (!pdmtx) {
  1003. LOG_ERR("Physical PDMTX device is not esixted");
  1004. return -EFAULT;
  1005. }
  1006. return phy_audio_disable(pdmtx, NULL);
  1007. }
  1008. #endif
  1009. /* @brief Close audio out channel by specified session handler */
  1010. static int acts_audio_out_close(struct device *dev, void *handle)
  1011. {
  1012. struct aout_drv_data *data = dev->data;
  1013. uint8_t channel_type;
  1014. int ret;
  1015. aout_session_t *session = (aout_session_t *)handle;
  1016. if (!handle) {
  1017. LOG_ERR("Invalid handle");
  1018. return -EINVAL;
  1019. }
  1020. audio_out_lock(dev);
  1021. if (!AOUT_SESSION_CHECK_MAGIC(session->magic)) {
  1022. LOG_ERR("Session magic error:0x%x", session->magic);
  1023. ret = -EFAULT;
  1024. goto out;
  1025. }
  1026. channel_type = session->channel_type;
  1027. #ifdef CONFIG_AUDIO_PA_AW87390_SUPPORT
  1028. phy_audio_disable(data->pa_aw87390_dev,NULL);
  1029. #endif
  1030. if (channel_type & AUDIO_CHANNEL_DAC) {
  1031. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  1032. ret = audio_out_disable_dac(dev, session);
  1033. #else
  1034. ret = -ENXIO;
  1035. #endif
  1036. } else if (channel_type & AUDIO_CHANNEL_I2STX) {
  1037. #ifdef CONFIG_AUDIO_OUT_I2STX_SUPPORT
  1038. ret = audio_out_disable_i2stx(dev, session);
  1039. #else
  1040. ret = -ENXIO;
  1041. #endif
  1042. } else if (channel_type & AUDIO_CHANNEL_SPDIFTX) {
  1043. #ifdef CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT
  1044. ret = audio_out_disable_spdiftx(dev, session);
  1045. #else
  1046. ret = -ENXIO;
  1047. #endif
  1048. } else if (channel_type & AUDIO_CHANNEL_PDMTX) {
  1049. #ifdef CONFIG_AUDIO_OUT_PDMTX_SUPPORT
  1050. ret = audio_out_disable_pdmtx(dev, session);
  1051. #else
  1052. ret = -ENXIO;
  1053. #endif
  1054. } else {
  1055. LOG_ERR("Invalid channel type %d", channel_type);
  1056. ret = -EINVAL;
  1057. goto out;
  1058. }
  1059. if (ret) {
  1060. LOG_ERR("Disable channel type %d error:%d", channel_type, ret);
  1061. goto out;
  1062. }
  1063. /* stop and free dma channel resource */
  1064. if (data->dma_dev && (session->dma_chan >= 0)) {
  1065. dma_stop(data->dma_dev, session->dma_chan);
  1066. dma_free(data->dma_dev, session->dma_chan);
  1067. }
  1068. LOG_INF("session#%d@%p closed", session->id, session);
  1069. audio_out_session_put(session);
  1070. out:
  1071. audio_out_unlock(dev);
  1072. return ret;
  1073. }
  1074. static int acts_audio_out_control(struct device *dev, void *handle, int cmd, void *param)
  1075. {
  1076. #if defined(CONFIG_AUDIO_OUT_DAC_SUPPORT) \
  1077. || defined(CONFIG_AUDIO_OUT_I2STX_SUPPORT) \
  1078. || defined(CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT)
  1079. struct aout_drv_data *data = dev->data;
  1080. #endif
  1081. aout_session_t *session = (aout_session_t *)handle;
  1082. uint8_t channel_type = session->channel_type;
  1083. int ret;
  1084. LOG_DBG("session#0x%x cmd 0x%x", (uint32_t)handle, cmd);
  1085. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  1086. if (AOUT_CMD_OPEN_PA == cmd)
  1087. return acts_audio_open_pa(dev, true);
  1088. if (AOUT_CMD_CLOSE_PA == cmd)
  1089. return acts_audio_close_pa(dev);
  1090. if (AOUT_CMD_PA_CLASS_SEL == cmd)
  1091. return acts_audio_pa_class_select(dev, *(uint8_t *)param);
  1092. #endif
  1093. #ifdef CONFIG_AUDIO_POWERON_OPEN_I2STX
  1094. if (AOUT_CMD_OPEN_I2STX_DEVICE == cmd)
  1095. return acts_audio_open_i2stx_dev(dev);
  1096. if (AOUT_CMD_CLOSE_I2STX_DEVICE == cmd)
  1097. return acts_audio_close_i2stx_dev(dev);
  1098. #endif
  1099. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  1100. if (AOUT_CMD_DEBUG_PERFORMANCE_CTL_ALL == cmd)
  1101. return audio_out_debug_perf_all_sessions(*(uint8_t *)param);
  1102. if (AOUT_CMD_DEBUG_DUMP_LENGTH_ALL == cmd)
  1103. return audio_out_debug_dump_length(*(uint8_t *)param);
  1104. #endif
  1105. if (cmd == AOUT_CMD_ANC_CONTROL) {
  1106. audio_out_lock(dev);
  1107. ret = phy_audio_control(data->dac0_dev, AOUT_CMD_ANC_CONTROL, param);
  1108. audio_out_unlock(dev);
  1109. return ret;
  1110. }
  1111. if (!AOUT_SESSION_CHECK_MAGIC(session->magic)) {
  1112. LOG_ERR("Session magic error:0x%x", session->magic);
  1113. return -EFAULT;
  1114. }
  1115. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  1116. if (AOUT_CMD_DEBUG_PERFORMANCE_CTL == cmd) {
  1117. session->debug.performance = *(uint8_t *)param;
  1118. session->debug.per_second_size = 0;
  1119. session->debug.timestamp = 0;
  1120. session->debug.dump_len = 0;
  1121. return 0;
  1122. }
  1123. if (AOUT_CMD_DEBUG_DUMP_LENGTH == cmd) {
  1124. session->debug.dump_len = *(uint8_t *)param;
  1125. return 0;
  1126. }
  1127. #endif
  1128. if (AOUT_CMD_SET_SEPARATED_MODE == cmd) {
  1129. audio_out_dma_separated_enable(dev, session);
  1130. return 0;
  1131. }
  1132. if (AOUT_CMD_SET_FIFO_SRC == cmd) {
  1133. dac_fifosrc_setting_t *dac_fifosrc = (dac_fifosrc_setting_t*)param;
  1134. session->dsp_fifo_src = dac_fifosrc->fifo_from_dsp ? 1:0;
  1135. }
  1136. /* In the case of the commands according to the FIFO attribute */
  1137. if (AOUT_IS_FIFO_CMD(cmd)) {
  1138. if ((AOUT_FIFO_DAC0 == session->outfifo_type)
  1139. || (AOUT_FIFO_DAC1 == session->outfifo_type)
  1140. || (AOUT_FIFO_DAC1_ONLY_SPDIF == session->outfifo_type)) {
  1141. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  1142. uint32_t val = session->outfifo_type;
  1143. if (val == AOUT_FIFO_DAC1_ONLY_SPDIF)
  1144. val = AOUT_FIFO_DAC1;
  1145. if (AOUT_CMD_GET_SAMPLE_CNT == cmd) {
  1146. ret = phy_audio_control(data->dac0_dev,
  1147. PHY_CMD_DAC_FIFO_GET_SAMPLE_CNT, &val);
  1148. if (!ret)
  1149. *(uint32_t *)param = val;
  1150. else
  1151. *(uint32_t *)param = 0;
  1152. } else if (AOUT_CMD_RESET_SAMPLE_CNT == cmd) {
  1153. ret = phy_audio_control(data->dac0_dev,
  1154. PHY_CMD_DAC_FIFO_RESET_SAMPLE_CNT, &val);
  1155. } else if (AOUT_CMD_ENABLE_SAMPLE_CNT == cmd) {
  1156. ret = phy_audio_control(data->dac0_dev,
  1157. PHY_CMD_DAC_FIFO_ENABLE_SAMPLE_CNT, &val);
  1158. } else if (AOUT_CMD_DISABLE_SAMPLE_CNT == cmd) {
  1159. ret = phy_audio_control(data->dac0_dev,
  1160. PHY_CMD_DAC_FIFO_DISABLE_SAMPLE_CNT, &val);
  1161. } else if (AOUT_CMD_GET_CHANNEL_STATUS == cmd) {
  1162. ret = phy_audio_control(data->dac0_dev,
  1163. AOUT_CMD_GET_CHANNEL_STATUS, &val);
  1164. if (!ret)
  1165. *(uint8_t *)param = val;
  1166. } else if (PHY_CMD_FIFO_PUT == cmd) {
  1167. ret = phy_audio_control(data->dac0_dev,
  1168. PHY_CMD_FIFO_PUT, &val);
  1169. } else if (AOUT_CMD_GET_DAC_FIFO_DRQ_LEVEL == cmd) {
  1170. uint32_t fifo_cmd = PHY_FIFO_CMD(val, 0);
  1171. ret = phy_audio_control(data->dac0_dev,
  1172. PHY_CMD_FIFO_DRQ_LEVEL_GET, &fifo_cmd);
  1173. if (!ret)
  1174. *(uint8_t *)param = PHY_GET_FIFO_CMD_VAL(fifo_cmd);
  1175. } else if (AOUT_CMD_SET_DAC_FIFO_DRQ_LEVEL == cmd) {
  1176. uint8_t level = *(uint8_t *)param;
  1177. uint32_t fifo_cmd = PHY_FIFO_CMD(val, level);
  1178. ret = phy_audio_control(data->dac0_dev,
  1179. PHY_CMD_FIFO_DRQ_LEVEL_SET, &fifo_cmd);
  1180. } else if (AOUT_CMD_GET_DAC_FIFO_VOLUME == cmd) {
  1181. uint32_t fifo_cmd = PHY_FIFO_CMD(val, 0);
  1182. ret = phy_audio_control(data->dac0_dev,
  1183. PHY_CMD_DAC_FIFO_VOLUME_GET, &fifo_cmd);
  1184. if (!ret)
  1185. *(uint8_t *)param = PHY_GET_FIFO_CMD_VAL(fifo_cmd);
  1186. } else if (AOUT_CMD_SET_DAC_FIFO_VOLUME == cmd) {
  1187. uint8_t volume = *(uint8_t *)param;
  1188. uint32_t fifo_cmd = PHY_FIFO_CMD(val, volume);
  1189. ret = phy_audio_control(data->dac0_dev,
  1190. PHY_CMD_DAC_FIFO_VOLUME_SET, &fifo_cmd);
  1191. } else {
  1192. ret = phy_audio_control(data->dac0_dev, cmd, param);
  1193. }
  1194. #else
  1195. ret = -ENXIO;
  1196. #endif
  1197. } else if (AOUT_FIFO_I2STX0 == session->outfifo_type) {
  1198. #ifdef CONFIG_AUDIO_OUT_I2STX_SUPPORT
  1199. ret = phy_audio_control(data->i2stx0_dev, cmd, param);
  1200. LOG_INF("i2stx0_dev+++cmd %d", cmd);
  1201. #else
  1202. ret = -ENXIO;
  1203. #endif
  1204. } else {
  1205. ret = -ENXIO;
  1206. }
  1207. goto out;
  1208. }
  1209. if (channel_type & AUDIO_CHANNEL_DAC) {
  1210. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  1211. ret = phy_audio_control(data->dac0_dev, cmd, param);
  1212. #else
  1213. ret = -ENXIO;
  1214. #endif
  1215. } else if (channel_type & AUDIO_CHANNEL_I2STX) {
  1216. #ifdef CONFIG_AUDIO_OUT_I2STX_SUPPORT
  1217. ret = phy_audio_control(data->i2stx0_dev, cmd, param);
  1218. #else
  1219. ret = -ENXIO;
  1220. #endif
  1221. } else if (channel_type & AUDIO_CHANNEL_SPDIFTX) {
  1222. #ifdef CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT
  1223. ret = phy_audio_control(data->spdiftx0_dev, cmd, param);
  1224. #else
  1225. ret = -ENXIO;
  1226. #endif
  1227. } else if (channel_type & AUDIO_CHANNEL_PDMTX) {
  1228. #ifdef CONFIG_AUDIO_OUT_PDMTX_SUPPORT
  1229. ret = phy_audio_control(data->pdmtx0_dev, cmd, param);
  1230. #else
  1231. ret = -ENXIO;
  1232. #endif
  1233. } else {
  1234. LOG_ERR("Invalid channel type %d", channel_type);
  1235. ret = -EINVAL;
  1236. }
  1237. out:
  1238. return ret;
  1239. }
  1240. static int acts_audio_out_start(struct device *dev, void *handle)
  1241. {
  1242. struct aout_drv_data *data = dev->data;
  1243. aout_session_t *session = (aout_session_t *)handle;
  1244. if (!handle) {
  1245. LOG_ERR("Invalid handle");
  1246. return -EINVAL;
  1247. }
  1248. if (!AOUT_SESSION_CHECK_MAGIC(session->magic)) {
  1249. LOG_ERR("Session magic error:0x%x", session->magic);
  1250. return -EFAULT;
  1251. }
  1252. if(!session->dsp_fifo_src) {
  1253. if (audio_out_dma_prepare(dev, session)) {
  1254. LOG_ERR("prepare session dma error");
  1255. return -ENXIO;
  1256. }
  1257. }
  1258. #ifdef CONFIG_BOARD_EXTERNAL_PA_ENABLE
  1259. acts_audio_open_external_pa(dev, false);
  1260. #endif
  1261. /* In DMA reload mode only start one time is enough */
  1262. if (session->reload_en
  1263. && (session->flags & AOUT_SESSION_START)) {
  1264. return 0;
  1265. }
  1266. if (!(session->flags & AOUT_SESSION_START))
  1267. session->flags |= AOUT_SESSION_START;
  1268. if(session->dsp_fifo_src) {
  1269. return 0;
  1270. }
  1271. return dma_start(data->dma_dev, session->dma_chan);
  1272. }
  1273. #if defined(CONFIG_AUDIO_OUT_DAC_PCMBUF_SUPPORT) && (CONFIG_AUDIO_DAC_WAIT_WRITE_PCMBUF_FINISH == 1)
  1274. static bool __acts_audio_check_dma_busy(struct device *dma_dev, uint32_t dma_chan)
  1275. {
  1276. int ret;
  1277. struct dma_status stat = {0};
  1278. ret = dma_get_status(dma_dev, dma_chan, &stat);
  1279. if (ret) {
  1280. LOG_ERR("get dma(%d) status error %d\n", dma_chan, ret);
  1281. return -EFAULT;
  1282. }
  1283. /* DMA transfer finish */
  1284. if (!stat.pending_length)
  1285. return false;
  1286. return true;
  1287. }
  1288. static int acts_audio_dma_wait_timeout(struct device *dma_dev, uint32_t dma_chan, uint32_t timeout)
  1289. {
  1290. uint32_t start_time, curr_time;
  1291. LOG_DBG("audio wait write dma_chan:%d", dma_chan);
  1292. start_time = k_cycle_get_32();
  1293. while (1) {
  1294. if (!__acts_audio_check_dma_busy(dma_dev, dma_chan))
  1295. break;
  1296. curr_time = k_cycle_get_32();
  1297. if (k_cyc_to_us_floor32(curr_time - start_time) >= timeout) {
  1298. LOG_ERR("wait dma(%d) finish timeout", dma_chan);
  1299. return -ETIMEDOUT;
  1300. }
  1301. if ((!k_is_in_isr()) && (CONFIG_AUDIO_DAC_WAIT_WRITE_PCMBUF_SLEEP_MS)
  1302. && (!z_is_idle_thread_object(_current)))
  1303. k_sleep(K_MSEC(CONFIG_AUDIO_DAC_WAIT_WRITE_PCMBUF_SLEEP_MS));
  1304. }
  1305. return 0;
  1306. }
  1307. /* @brief wait dac FIFO empty */
  1308. static int wait_dacfifo_empty(struct device *dev, aout_session_t *session)
  1309. {
  1310. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  1311. struct aout_drv_data *data = dev->data;
  1312. int ret;
  1313. uint8_t fifo_idx = session->outfifo_type;
  1314. ret = phy_audio_control(data->dac0_dev, PHY_CMD_DAC_WAIT_EMPTY, &fifo_idx);
  1315. if (ret) {
  1316. LOG_ERR("wait empty error");
  1317. }
  1318. return ret;
  1319. #else
  1320. return -ENXIO;
  1321. #endif
  1322. }
  1323. /* @brief Wait writing data to audio DAC channel finishly */
  1324. static int acts_audio_out_wait_write_finish(struct device *dev, aout_session_t *session)
  1325. {
  1326. struct aout_drv_data *data = dev->data;
  1327. int ret;
  1328. if ((AOUT_FIFO_DAC0 == session->outfifo_type)
  1329. || (AOUT_FIFO_DAC1 == session->outfifo_type)) {
  1330. #if (CONFIG_AUDIO_DAC_WAIT_WRITE_PCMBUF_NEXT_TIME == 1)
  1331. if (session->flags & AOUT_SESSION_START)
  1332. #endif
  1333. {
  1334. ret = acts_audio_dma_wait_timeout(data->dma_dev,
  1335. session->dma_chan, CONFIG_AUDIO_DAC_WAIT_WRITE_PCMBUF_TIMEOUT_US);
  1336. if (ret) {
  1337. LOG_ERR("wait dma error %d", ret);
  1338. return -EIO;
  1339. }
  1340. wait_dacfifo_empty(dev, session);
  1341. }
  1342. }
  1343. return 0;
  1344. }
  1345. #endif
  1346. /* @brief Write the data to the audio output channel */
  1347. static int acts_audio_out_write(struct device *dev, void *handle, uint8_t *buffer, uint32_t length)
  1348. {
  1349. struct aout_drv_data *data = dev->data;
  1350. aout_session_t *session = (aout_session_t *)handle;
  1351. int ret;
  1352. if (!handle || !buffer || !length) {
  1353. LOG_ERR("Invalid parameters (%p, %p, %d)", handle, buffer, length);
  1354. return -EINVAL;
  1355. }
  1356. if (!AOUT_SESSION_CHECK_MAGIC(session->magic)) {
  1357. LOG_ERR("Session magic error:0x%x", session->magic);
  1358. return -EFAULT;
  1359. }
  1360. if (session->reload_en) {
  1361. LOG_INF("Reload mode can start directly");
  1362. return 0;
  1363. }
  1364. if (!(session->flags & AOUT_SESSION_OPEN)) {
  1365. LOG_ERR("session not opened");
  1366. return -EPERM;
  1367. }
  1368. if(!session->dsp_fifo_src){
  1369. #if defined(CONFIG_AUDIO_OUT_DAC_PCMBUF_SUPPORT) \
  1370. && (CONFIG_AUDIO_DAC_WAIT_WRITE_PCMBUF_FINISH == 1) \
  1371. && (CONFIG_AUDIO_DAC_WAIT_WRITE_PCMBUF_NEXT_TIME == 1)
  1372. ret = acts_audio_out_wait_write_finish(dev, session);
  1373. if (ret)
  1374. return ret;
  1375. #endif
  1376. if (audio_out_dma_prepare(dev, session)) {
  1377. LOG_ERR("prepare session dma error");
  1378. return -ENXIO;
  1379. }
  1380. LOG_DBG("DMA channel:0x%x, buffer:%p len:%d", session->dma_chan, buffer, length);
  1381. if (session->dma_separated_en) {
  1382. ret = dma_reload(data->dma_dev, session->dma_chan, (uint32_t)buffer,
  1383. (uint32_t)buffer, length * 2);
  1384. } else {
  1385. ret = dma_reload(data->dma_dev, session->dma_chan, (uint32_t)buffer, 0, length);
  1386. }
  1387. if (ret) {
  1388. LOG_ERR("dma reload error %d", ret);
  1389. return ret;
  1390. }
  1391. }
  1392. ret = audio_out_start(dev, handle);
  1393. if (ret)
  1394. LOG_ERR("dma start error %d", ret);
  1395. if(!session->dsp_fifo_src){
  1396. #if defined(CONFIG_AUDIO_OUT_DAC_PCMBUF_SUPPORT) \
  1397. && (CONFIG_AUDIO_DAC_WAIT_WRITE_PCMBUF_FINISH == 1) \
  1398. && (CONFIG_AUDIO_DAC_WAIT_WRITE_PCMBUF_NEXT_TIME == 0)
  1399. ret = acts_audio_out_wait_write_finish(dev, session);
  1400. if (ret)
  1401. return ret;
  1402. #endif
  1403. }
  1404. #ifdef CONFIG_AUDIO_DYNAMIC_DEBUG
  1405. if (!session->reload_en)
  1406. audio_out_debug_perf(session, buffer, length);
  1407. #endif
  1408. return ret;
  1409. }
  1410. static int acts_audio_out_stop(struct device *dev, void *handle)
  1411. {
  1412. struct aout_drv_data *data = dev->data;
  1413. aout_session_t *session = (aout_session_t *)handle;
  1414. int ret = 0;
  1415. if (session && AOUT_SESSION_CHECK_MAGIC(session->magic)) {
  1416. LOG_INF("session#%p, audio out stop", session);
  1417. if (data->dma_dev && session->dma_chan) {
  1418. ret = dma_stop(data->dma_dev, session->dma_chan);
  1419. if (!ret)
  1420. session->flags &= ~AOUT_SESSION_START;
  1421. }
  1422. }
  1423. return ret;
  1424. }
  1425. const struct aout_driver_api aout_drv_api = {
  1426. .aout_open = acts_audio_out_open,
  1427. .aout_close = acts_audio_out_close,
  1428. .aout_control = acts_audio_out_control,
  1429. .aout_start = acts_audio_out_start,
  1430. .aout_write = acts_audio_out_write,
  1431. .aout_stop = acts_audio_out_stop
  1432. };
  1433. /* @brief audio-out channles initialization */
  1434. static int audio_out_init(const struct device *dev)
  1435. {
  1436. const struct aout_config_data *cfg = dev->config;
  1437. struct aout_drv_data *data = dev->data;
  1438. memset(data, 0, sizeof(struct aout_drv_data));
  1439. k_sem_init(&data->lock, 1, 1);
  1440. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  1441. data->dac0_dev = (struct device *)device_get_binding(cfg->dac0_name);
  1442. if (!data->dac0_dev) {
  1443. LOG_ERR("no DAC device(%s)", cfg->dac0_name);
  1444. }
  1445. #endif
  1446. #ifdef CONFIG_AUDIO_OUT_I2STX_SUPPORT
  1447. data->i2stx0_dev = (struct device *)device_get_binding(cfg->i2stx0_name);
  1448. if (!data->i2stx0_dev) {
  1449. LOG_ERR("no I2STX device(%s)", cfg->i2stx0_name);
  1450. }
  1451. #endif
  1452. #ifdef CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT
  1453. data->spdiftx0_dev = (struct device *)device_get_binding(cfg->spdiftx0_name);
  1454. if (!data->spdiftx0_dev) {
  1455. LOG_ERR("no SPDIFTX device(%s)", cfg->spdiftx0_name);
  1456. }
  1457. #endif
  1458. #ifdef CONFIG_AUDIO_OUT_PDMTX_SUPPORT
  1459. data->pdmtx0_dev = (struct device *)device_get_binding(cfg->pdmtx0_name);
  1460. if (!data->pdmtx0_dev) {
  1461. LOG_ERR("no PDMTX device(%s)", cfg->pdmtx0_name);
  1462. }
  1463. #endif
  1464. #ifdef CONFIG_AUDIO_PA_AW87390_SUPPORT
  1465. data->pa_aw87390_dev = (struct device *)device_get_binding(cfg->pa_aw87390_name);
  1466. if (!data->pa_aw87390_dev) {
  1467. LOG_ERR("no pa_aw87390_dev device(%s)", cfg->pa_aw87390_name);
  1468. }
  1469. #endif
  1470. /* clear pa session indicator */
  1471. data->pa_session_indicator = 0;
  1472. /* clear DAC fifo reference counter */
  1473. data->dac_fifo_ref_counter = 0;
  1474. /* disable AVDD pulldown */
  1475. sys_write32(sys_read32(AUDIOLDO_CTL) & ~(1 << 4), AUDIOLDO_CTL);
  1476. /* open internal and external pa */
  1477. #ifdef CONFIG_AUDIO_POWERON_OPEN_PA
  1478. #ifdef CONFIG_AUDIO_PA_AW87390_SUPPORT
  1479. phy_audio_disable(data->pa_aw87390_dev,NULL);
  1480. #endif
  1481. acts_audio_open_pa((struct device *)dev, CONFIG_POWERON_OPEN_EXTERNAL_PA);
  1482. #ifdef CONFIG_AUDIO_PA_AW87390_SUPPORT
  1483. phy_audio_enable(data->pa_aw87390_dev,NULL);
  1484. #endif
  1485. #endif
  1486. #ifdef CONFIG_AUDIO_POWERON_OPEN_I2STX
  1487. acts_audio_open_i2stx_dev(dev);
  1488. #endif
  1489. printk("ACTS-AUDIO OUT initialized\n");
  1490. return 0;
  1491. }
  1492. static struct aout_drv_data audio_out_drv_data;
  1493. static const struct aout_config_data audio_out_config_data = {
  1494. #ifdef CONFIG_AUDIO_OUT_DAC_SUPPORT
  1495. .dac0_name = CONFIG_AUDIO_DAC_0_NAME,
  1496. #endif
  1497. #ifdef CONFIG_AUDIO_OUT_I2STX_SUPPORT
  1498. .i2stx0_name = CONFIG_AUDIO_I2STX_0_NAME,
  1499. #endif
  1500. #ifdef CONFIG_AUDIO_OUT_SPDIFTX_SUPPORT
  1501. .spdiftx0_name = CONFIG_AUDIO_SPDIFTX_0_NAME,
  1502. #endif
  1503. #ifdef CONFIG_AUDIO_OUT_PDMTX_SUPPORT
  1504. .pdmtx0_name = CONFIG_AUDIO_PDMTX_0_NAME,
  1505. #endif
  1506. #ifdef CONFIG_AUDIO_PA_AW87390_SUPPORT
  1507. .pa_aw87390_name = "aw87390_out",
  1508. #endif
  1509. };
  1510. DEVICE_DEFINE(audio_out, CONFIG_AUDIO_OUT_ACTS_DEV_NAME, audio_out_init,
  1511. NULL,
  1512. &audio_out_drv_data, &audio_out_config_data,
  1513. POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &aout_drv_api);