phy_audio_i2srx.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. /*
  2. * Copyright (c) 2020 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief Audio I2SRX physical implementation
  9. */
  10. /*
  11. * Features
  12. * - Support master and slave mode
  13. * - Support I2S 2ch format
  14. * - I2SRXFIFO(32 x 24bits level)
  15. * - Support 3 format: left-justified format, right-justified format, I2S format
  16. * - Support 16/20/24 effective data width; BCLK support 32/64fs, and MCLK=4BCLK
  17. * - Support sample rate auto detect in slave mode
  18. * - Sample rate support 8k/12k/11.025k/16k/22.05k/24k/32k/44.1k/48k/88.2k/96k/192k
  19. */
  20. #include <kernel.h>
  21. #include <device.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include <soc.h>
  25. #include <board_cfg.h>
  26. #include "../phy_audio_common.h"
  27. #include "../audio_acts_utils.h"
  28. #include <drivers/audio/audio_in.h>
  29. #include <logging/log.h>
  30. LOG_MODULE_REGISTER(i2srx0, CONFIG_LOG_DEFAULT_LEVEL);
  31. /***************************************************************************************************
  32. * I2SRX_CTL
  33. */
  34. #define I2SR0_CTL_TDMRX_CHAN BIT(16) /* 4 channel or 8 channel */
  35. #define I2SR0_CTL_TDMRX_MODE BIT(15) /* I2S format or left-justified format */
  36. #define I2SR0_CTL_TDMRX_SYNC_SHIFT (13) /* at the beginning of the data frame, the type of LRCLK setting */
  37. #define I2SR0_CTL_TDMRX_SYNC_MASK (0x3 << I2SR0_CTL_TDMRX_SYNC_SHIFT)
  38. #define I2SR0_CTL_TDMRX_SYNC(x) ((x) << I2SR0_CTL_TDMRX_SYNC_SHIFT)
  39. #define I2SR0_CTL_RXWIDTH_SHIFT (4) /* effective width */
  40. #define I2SR0_CTL_RXWIDTH_MASK (0x3 << I2SR0_CTL_RXWIDTH_SHIFT)
  41. #define I2SR0_CTL_RXWIDTH(x) ((x) << I2SR0_CTL_RXWIDTH_SHIFT)
  42. #define I2SR0_CTL_RXBCLKSET BIT(3) /* rate of BCLK with LRCLK */
  43. #define I2SR0_CTL_RXMODELSEL_SHIFT (1) /* I2S transfer format select */
  44. #define I2SR0_CTL_RXMODELSEL_MASK (0x3 << I2SR0_CTL_RXMODELSEL_SHIFT)
  45. #define I2SR0_CTL_RXMODELSEL(x) ((x) << I2SR0_CTL_RXMODELSEL_SHIFT)
  46. #define I2SR0_CTL_RXEN BIT(0) /* I2S RX enable */
  47. /***************************************************************************************************
  48. * I2SRX_FIFOCTL
  49. */
  50. #define I2SR0_FIFOCTL_RXFIFO_DMAWIDTH BIT(7) /* DMA transfer width */
  51. #define I2SR0_FIFOCTL_RXFOS_SHIFT (4) /* RX FIFO output select */
  52. #define I2SR0_FIFOCTL_RXFOS_MASK (0x3 << I2SR0_FIFOCTL_RXFOS_SHIFT)
  53. #define I2SR0_FIFOCTL_RXFOS(x) ((x) << I2SR0_FIFOCTL_RXFOS_SHIFT)
  54. #define I2SR0_FIFOCTL_RXFFIE BIT(2) /* RX FIFO half filled irq enable */
  55. #define I2SR0_FIFOCTL_RXFFDE BIT(1) /* RX FIFO half filed drq enable */
  56. #define I2SR0_FIFOCTL_RXFRT BIT(0) /* RX FIFO reset */
  57. /***************************************************************************************************
  58. * I2SRX_STAT
  59. */
  60. #define I2SR0_FIFOSTA_FIFO_ER BIT(8) /* FIFO error */
  61. #define I2SR0_FIFOSTA_RXFEF BIT(7) /* RX FIFO empty flag */
  62. #define I2SR0_FIFOSTA_RXFIP BIT(6) /* RX FIFO half filled irq pending */
  63. #define I2SR0_FIFOSTA_RXFS_SHIFT (0) /* RX FIFO status */
  64. #define I2SR0_FIFOSTA_RXFS_MASK (0x3F << I2SR0_FIFOSTA_RXFS_SHIFT)
  65. /***************************************************************************************************
  66. * I2SRX_DAT
  67. */
  68. #define I2SR0_DAT_RXDAT_SHIFT (8) /* I2S RX FIFO data */
  69. #define I2SR0_DAT_RXDAT_MASK (0xFFFFFF << I2SR0_DAT_RXDAT_SHIFT)
  70. /***************************************************************************************************
  71. * I2SRX_CTL
  72. */
  73. #define I2SR0_SRDCTL_MUTE_EN BIT(12) /* If detect sample rate or channel width changing, mute output */
  74. #define I2SR0_SRDCTL_SRD_IE BIT(8) /* sample rate detect result change interrupt enable */
  75. #define I2SR0_SRDCTL_CNT_TIM_SHIFT (4) /* slave mode rample rate detect counter period select */
  76. #define I2SR0_SRDCTL_CNT_TIM_MASK (0x3 << I2SR0_SRDCTL_CNT_TIM_SHIFT)
  77. #define I2SR0_SRDCTL_SRD_TH_SHIFT (1) /* the sampling sensitivity */
  78. #define I2SR0_SRDCTL_SRD_TH_MASK (0x7 << I2SR0_SRDCTL_SRD_TH_SHIFT)
  79. #define I2SR0_SRDCTL_SRD_TH(x) ((x) << I2SR0_SRDCTL_SRD_TH_SHIFT)
  80. #define I2SR0_SRDCTL_SRD_EN BIT(0) /* slave mode sample rate detect enable */
  81. /***************************************************************************************************
  82. * I2SRX_SRDSTA
  83. */
  84. #define I2SR0_SRDSTA_CNT_SHIFT (12) /* CNT of LRCLK which sampling by SRC_CLK */
  85. #define I2SR0_SRDSTA_CNT_MASK (0x1FFF << I2SR0_SRDSTA_CNT_SHIFT)
  86. #define I2SR0_SRDSTA_TO_PD BIT(11) /* sample rate changing detection timeout interrupt pending */
  87. #define I2SR0_SRDSTA_SRC_PD BIT(10) /* sample rate changing detection interrupt pending */
  88. #define I2SR0_SRDSTA_CHW_PD BIT(8) /* channel width change interrupt pending */
  89. #define I2SR0_SRDSTA_WL_SHIFT (0) /* channel word length */
  90. #define I2SR0_SRDSTA_WL_MASK (0x7 << I2SR0_SRDSTA_WL_SHIFT)
  91. /***************************************************************************************************
  92. * i2SRX FEATURES CONGIURATION
  93. */
  94. /* The sensitivity of the SRD */
  95. #define I2SRX_SRD_TH_DEFAULT (7)
  96. #define I2SRX_BCLK_DIV_DEFAULT (0) /* BCLK divisor */
  97. #define I2SRX_SRD_CONFIG_TIMEOUT_US (500000)
  98. /*
  99. * enum a_i2srx_mclk_clksrc_e
  100. * @brief The MCLK clock source of i2srx selection
  101. */
  102. typedef enum {
  103. CLK_SRCRX_I2SRX = 0, /* I2SRX clock source from I2SRX clk */
  104. CLK_SRCRX_I2STX, /* I2SRX clock source from I2STX MCLK */
  105. CLK_SRCRX_I2SRX_EXT = 3, /* I2SRX clock source from I2SRX extern MCLK */
  106. } a_i2srx_mclk_clksrc_e;
  107. /*
  108. * @struct acts_audio_i2srx
  109. * @brief I2SRX controller hardware register
  110. */
  111. struct acts_audio_i2srx {
  112. volatile uint32_t rx_ctl; /* I2SRX control */
  113. volatile uint32_t fifoctl; /* I2SRX FIFO control */
  114. volatile uint32_t fifostat; /* I2SRX FIFO state */
  115. volatile uint32_t dat; /* I2SRX FIFO data */
  116. volatile uint32_t srdctl; /* I2S slave mode RX sample rate detect control */
  117. volatile uint32_t srdstat; /* I2S slave mode RX sample rate detect state */
  118. };
  119. /*
  120. * struct phy_i2srx_drv_data
  121. * @brief The software related data that used by physical i2srx driver.
  122. */
  123. struct phy_i2srx_drv_data {
  124. uint8_t mclksrc; /* MCLK clock source selection refer to #a_i2srx_mclk_clksrc_e */
  125. int (*srd_callback)(void *cb_data, uint32_t cmd, void *param);
  126. void *cb_data;
  127. uint8_t srd_wl; /* The width length detected by SRD */
  128. uint8_t sample_rate; /* sample rate */
  129. uint8_t channel_opened : 1; /* flag of channel opened */
  130. };
  131. /**
  132. * union phy_i2srx_features
  133. * @brief The infomation from DTS to control the I2SRX features to enable or nor.
  134. */
  135. typedef union {
  136. uint32_t raw;
  137. struct {
  138. uint32_t srd_en : 1; /* SRD function enable or not */
  139. uint32_t mode: 1; /* master mode or slaver mode; 0: master 1: slaver */
  140. uint32_t channel_num : 4; /* channel number and only support 2/4/8 channels */
  141. uint32_t slave_internal_clk : 1; /* slave mode MCLK to use internal clock */
  142. uint32_t lrclk_proc : 1; /* LRCLK process */
  143. uint32_t mclk_reverse : 1; /* mclk reverse */
  144. uint32_t format : 2; /* I2S transfer format */
  145. uint32_t clk_from_i2stx : 1; /* clock from I2STX(I2SG0) clock */
  146. uint32_t tdm_format : 1; /* TDM format */
  147. uint32_t tdm_frame : 2; /* TDM frame start position */
  148. uint32_t bclk_width : 1; /* bclk width */
  149. } v;
  150. } phy_i2srx_features;
  151. /**
  152. * struct phy_i2srx_config_data
  153. * @brief The hardware related data that used by physical i2srx driver.
  154. */
  155. struct phy_i2srx_config_data {
  156. uint32_t reg_base; /* I2STX controller register base address */
  157. uint8_t clk_id; /* I2STX devclk id */
  158. uint8_t srd_clk_id; /* I2S SRD clock id */
  159. uint8_t hclk_clk_id; /* I2S HCLK clock id */
  160. uint8_t rst_id; /* I2STX reset id */
  161. struct audio_dma_dt dma_fifo0; /* DMA resource for SPDIFRX */
  162. void (*irq_config)(void); /* IRQ configuration function */
  163. phy_i2srx_features features; /* I2STX features */
  164. };
  165. /* @brief Get the I2SRX controller base address */
  166. static inline struct acts_audio_i2srx *get_i2srx_reg_base(struct device *dev)
  167. {
  168. const struct phy_i2srx_config_data *cfg = dev->config;
  169. return (struct acts_audio_i2srx *)cfg->reg_base;
  170. }
  171. /* @brief Dump the I2SRX relative registers */
  172. static void i2srx_dump_register(struct device *dev)
  173. {
  174. struct acts_audio_i2srx *i2srx_reg = get_i2srx_reg_base(dev);
  175. LOG_INF("** i2srx contoller regster **");
  176. LOG_INF(" BASE: %08x", (uint32_t)i2srx_reg);
  177. LOG_INF(" I2SRX_CTL: %08x", i2srx_reg->rx_ctl);
  178. LOG_INF(" I2SRX_FIFOCTL: %08x", i2srx_reg->fifoctl);
  179. LOG_INF(" I2SRX_FIFOSTA: %08x", i2srx_reg->fifostat);
  180. LOG_INF(" I2SRX_DAT: %08x", i2srx_reg->dat);
  181. LOG_INF(" I2SRX_SRDCTL: %08x", i2srx_reg->srdctl);
  182. LOG_INF(" I2SRX_SRDSTA: %08x", i2srx_reg->srdstat);
  183. LOG_INF(" AUDIOPLL0_CTL: %08x", sys_read32(AUDIO_PLL0_CTL));
  184. LOG_INF(" AUDIOPLL1_CTL: %08x", sys_read32(AUDIO_PLL1_CTL));
  185. LOG_INF(" CMU_I2STXCLK: %08x", sys_read32(CMU_I2STXCLK));
  186. LOG_INF(" CMU_I2SRXCLK: %08x", sys_read32(CMU_I2SRXCLK));
  187. }
  188. /* @brief I2SRX sample rate config */
  189. static int i2srx_sample_rate_set(struct device *dev, uint16_t sr_khz,
  190. a_i2srx_mclk_clksrc_e mclk_src)
  191. {
  192. const struct phy_i2srx_config_data *cfg = dev->config;
  193. int ret;
  194. uint8_t clk_div, series, pll_index;
  195. uint32_t reg = 0;
  196. uint32_t lrclk_div;
  197. a_mclk_type_e mclk;
  198. if (!PHY_DEV_FEATURE(bclk_width))
  199. mclk = MCLK_256FS;
  200. else
  201. mclk = MCLK_128FS;
  202. if (CLK_SRCRX_I2STX == mclk_src) {
  203. struct device *i2stx_dev = (struct device *)device_get_binding(CONFIG_AUDIO_I2STX_0_NAME);
  204. if (!i2stx_dev) {
  205. LOG_ERR("failed to get i2stx dev %s", CONFIG_AUDIO_I2STX_0_NAME);
  206. return -ENODEV;
  207. }
  208. sys_write32(sys_read32(CMU_I2SRXCLK) | CMU_I2SRXCLK_I2SRX0CLKSRC, CMU_I2SRXCLK);
  209. return phy_audio_control(i2stx_dev, PHY_CMD_I2STX_CLK_SET, &sr_khz);
  210. } else if (CLK_SRCRX_I2SRX == mclk_src) {
  211. /* make external MCLK clock phase reverse */
  212. if (PHY_DEV_FEATURE(mclk_reverse))
  213. reg |= CMU_I2SRXCLK_I2SG1MCLKEXTREV;
  214. /* I2S master mode to enable MCLK output to PAD */
  215. if (!PHY_DEV_FEATURE(mode)) {
  216. reg |= CMU_I2SRXCLK_I2SRXMCLKOEN;
  217. } else {
  218. if (PHY_DEV_FEATURE(slave_internal_clk))
  219. sr_khz *= 2; /* slave mode use internal clk condition: MCLK > 6BCLK */
  220. /* BCLK/LRCLK source from external PAD */
  221. reg |= CMU_I2SRXCLK_I2SG1BLRCLKSRC;
  222. }
  223. if (PHY_DEV_FEATURE(lrclk_proc))
  224. reg |= CMU_I2SRXCLK_I2SG1LRCLKPROC;
  225. /* BCLK = FS x channel number x channel bit width */
  226. if (!PHY_DEV_FEATURE(bclk_width))
  227. lrclk_div = PHY_DEV_FEATURE(channel_num) * 32;
  228. else
  229. lrclk_div = PHY_DEV_FEATURE(channel_num) * 16;
  230. /* LRCLK divisor 0:32; 1:64; 2: 128; 3:256 */
  231. if (32 == lrclk_div) {
  232. lrclk_div = 0;
  233. } else if (64 == lrclk_div) {
  234. lrclk_div = 1;
  235. } else if (128 == lrclk_div) {
  236. lrclk_div = 2;
  237. } else if (256 == lrclk_div) {
  238. lrclk_div = 3;
  239. } else {
  240. LOG_ERR("invalid lrclk divisor:%d", lrclk_div);
  241. return -EINVAL;
  242. }
  243. reg |= CMU_I2SRXCLK_I2SG1LRCLKDIV(lrclk_div);
  244. /* MCLK = 4 x BCLK */
  245. reg |= CMU_I2SRXCLK_I2SG1BCLKDIV(I2SRX_BCLK_DIV_DEFAULT);
  246. sr_khz = PHY_DEV_FEATURE(channel_num) / 2 * sr_khz;
  247. /* Get audio PLL setting */
  248. ret = audio_get_pll_setting_i2s(sr_khz, mclk, &clk_div, &series);
  249. if (ret) {
  250. LOG_DBG("get pll setting error:%d", ret);
  251. return ret;
  252. }
  253. ret = audio_pll_check_config(series, &pll_index);
  254. if (ret) {
  255. LOG_DBG("check pll config error:%d", ret);
  256. return ret;
  257. }
  258. /* Select pll0 or pll1 */
  259. reg |= (pll_index & 0x1) << CMU_I2SRXCLK_I2SG1CLKSRC;
  260. reg |= clk_div << CMU_I2SRXCLK_I2SG1CLKDIV_SHIFT;
  261. } else if (CLK_SRCRX_I2SRX_EXT == mclk_src) {
  262. LOG_INF("I2SRX clock source from external");
  263. /* BCLK/LRCLK source from external PAD */
  264. reg |= CMU_I2SRXCLK_I2SG1BLRCLKSRC;
  265. } else {
  266. LOG_ERR("Invalid i2srx clk source %d", mclk_src);
  267. return -EINVAL;
  268. }
  269. /* Select the i2srx mclk source */
  270. reg |= CMU_I2SRXCLK_I2SG1MCLKSRC(mclk_src & 0x3);
  271. sys_write32(reg, CMU_I2SRXCLK);
  272. return 0;
  273. }
  274. /* @brief Get the sample rate from the I2SRX config */
  275. static int i2srx_sample_rate_get(struct device *dev)
  276. {
  277. const struct phy_i2srx_config_data *cfg = dev->config;
  278. uint8_t clk_div, pll_index, mclk_src;
  279. uint32_t reg;
  280. int ret = -1;
  281. a_mclk_type_e mclk;
  282. if (!PHY_DEV_FEATURE(bclk_width))
  283. mclk = MCLK_256FS;
  284. else
  285. mclk = MCLK_128FS;
  286. reg = sys_read32(CMU_I2SRXCLK);
  287. mclk_src = (reg & CMU_I2SRXCLK_I2SG1MCLKSRC_MASK) >> CMU_I2SRXCLK_I2SG1MCLKSRC_SHIFT;
  288. if (CLK_SRCRX_I2SRX == mclk_src) {
  289. clk_div = reg & 0xF;
  290. pll_index = (reg >> CMU_I2SRXCLK_I2SG1CLKSRC) & 0x1;
  291. ret = audio_get_pll_sample_rate_i2s(MCLK_256FS, clk_div, pll_index);
  292. } else if (CLK_SRCRX_I2STX == mclk_src) {
  293. reg = sys_read32(CMU_I2STXCLK);
  294. clk_div = reg & 0xF;
  295. pll_index = (reg >> CMU_I2STXCLK_I2SG0CLKSRC) & 0x1;
  296. ret = audio_get_pll_sample_rate_i2s(mclk, clk_div, pll_index);
  297. } else if (CLK_SRCRX_I2SRX_EXT == mclk_src) {
  298. LOG_INF("I2SRX is using the external clock");
  299. ret = -ENOENT;
  300. }
  301. return ret;
  302. }
  303. /* @brief Get the AUDIO_PLL APS used by I2SRX */
  304. static int i2srx_get_pll_aps(struct device *dev)
  305. {
  306. uint32_t reg;
  307. uint8_t pll_index, mclk_src;
  308. int ret = -1;
  309. reg = sys_read32(CMU_I2SRXCLK);
  310. mclk_src = (reg & CMU_I2SRXCLK_I2SG1MCLKSRC_MASK) >> CMU_I2SRXCLK_I2SG1MCLKSRC_SHIFT;
  311. if (CLK_SRCRX_I2SRX == mclk_src) {
  312. pll_index = (reg & (1 << CMU_I2SRXCLK_I2SG1CLKSRC)) >> CMU_I2SRXCLK_I2SG1CLKSRC;
  313. ret = audio_pll_get_aps((a_pll_type_e)pll_index);
  314. } else if (CLK_SRCRX_I2STX == mclk_src) {
  315. reg = sys_read32(CMU_I2STXCLK);
  316. pll_index = (reg & (1 << CMU_I2STXCLK_I2SG0CLKSRC)) >> CMU_I2STXCLK_I2SG0CLKSRC;
  317. ret = audio_pll_get_aps((a_pll_type_e)pll_index);
  318. }if (CLK_SRCRX_I2SRX_EXT == mclk_src) {
  319. LOG_INF("I2SRX is using the external clock source");
  320. return -ENOENT;
  321. }
  322. return ret;
  323. }
  324. /* @brief Set the AUDIO_PLL APS used by I2SRX */
  325. static int i2srx_set_pll_aps(struct device *dev, audio_aps_level_e level)
  326. {
  327. uint32_t reg;
  328. uint8_t pll_index, mclk_src;
  329. int ret = -1;
  330. reg = sys_read32(CMU_I2SRXCLK);
  331. mclk_src = (reg & CMU_I2SRXCLK_I2SG1MCLKSRC_MASK) >> CMU_I2SRXCLK_I2SG1MCLKSRC_SHIFT;
  332. if (CLK_SRCRX_I2SRX == mclk_src) {
  333. pll_index = (reg & (1 << CMU_I2SRXCLK_I2SG1CLKSRC)) >> CMU_I2SRXCLK_I2SG1CLKSRC;
  334. ret = audio_pll_set_aps((a_pll_type_e)pll_index, level);
  335. } else if (CLK_SRCRX_I2STX == mclk_src) {
  336. reg = sys_read32(CMU_I2STXCLK);
  337. pll_index = (reg & (1 << CMU_I2STXCLK_I2SG0CLKSRC)) >> CMU_I2STXCLK_I2SG0CLKSRC;
  338. ret = audio_pll_set_aps((a_pll_type_e)pll_index, level);
  339. } else if (CLK_SRCRX_I2SRX_EXT == mclk_src) {
  340. LOG_INF("I2SRX is using the external clock source");
  341. ret = -ENOENT;
  342. }
  343. return ret;
  344. }
  345. /* @brief Disable the I2SRX FIFO */
  346. static void i2srx_fifo_disable(struct device *dev)
  347. {
  348. struct acts_audio_i2srx *i2srx_reg = get_i2srx_reg_base(dev);
  349. i2srx_reg->fifoctl &= ~I2SR0_CTL_RXEN;
  350. }
  351. /* @brief Reset the I2SRX FIFO */
  352. static void i2srx_fifo_reset(struct device *dev)
  353. {
  354. struct acts_audio_i2srx *i2srx_reg = get_i2srx_reg_base(dev);
  355. i2srx_reg->fifoctl &= ~I2SR0_CTL_RXEN;
  356. i2srx_reg->fifoctl |= I2SR0_CTL_RXEN;
  357. }
  358. /* @brief Enable the I2SRX FIFO */
  359. static void i2srx_fifo_enable(struct device *dev, audio_fifouse_sel_e sel, audio_dma_width_e width)
  360. {
  361. struct acts_audio_i2srx *i2srx_reg = get_i2srx_reg_base(dev);
  362. uint32_t reg = 0;
  363. if (DMA_WIDTH_16BITS == width)
  364. reg |= I2SR0_FIFOCTL_RXFIFO_DMAWIDTH;
  365. if (FIFO_SEL_CPU == sel) {
  366. reg |= (I2SR0_FIFOCTL_RXFFIE | I2SR0_FIFOCTL_RXFRT);
  367. } else if (FIFO_SEL_DMA == sel) {
  368. reg |= (I2SR0_FIFOCTL_RXFFDE | I2SR0_FIFOCTL_RXFRT
  369. | I2SR0_FIFOCTL_RXFOS(1));
  370. } else if (FIFO_SEL_DSP == sel) {
  371. reg |= I2SR0_FIFOCTL_RXFOS(3) | I2SR0_FIFOCTL_RXFRT;
  372. } else {
  373. LOG_ERR("invalid fifo sel %d", sel);
  374. }
  375. i2srx_reg->fifoctl = reg;
  376. }
  377. /* @brief I2SRX digital function control */
  378. static void i2srx_digital_enable(struct device *dev, audio_ch_width_e width)
  379. {
  380. const struct phy_i2srx_config_data *cfg = dev->config;
  381. struct acts_audio_i2srx *i2srx_reg = get_i2srx_reg_base(dev);
  382. uint32_t reg = 0;
  383. uint8_t rx_width, fmt = PHY_DEV_FEATURE(format);
  384. if (CHANNEL_WIDTH_16BITS == width)
  385. rx_width = 0;
  386. else if (CHANNEL_WIDTH_20BITS == width)
  387. rx_width = 1;
  388. else
  389. rx_width = 2;
  390. if (PHY_DEV_FEATURE(channel_num) != 2) {
  391. fmt = 3; /* TDM mode */
  392. reg &= ~ (0xF << I2SR0_CTL_TDMRX_SYNC_SHIFT);
  393. if (PHY_DEV_FEATURE(channel_num) == 8)
  394. reg |= I2SR0_CTL_TDMRX_CHAN;
  395. if (PHY_DEV_FEATURE(tdm_format))
  396. reg |= I2SR0_CTL_TDMRX_MODE;
  397. reg |= I2SR0_CTL_TDMRX_SYNC(PHY_DEV_FEATURE(tdm_frame));
  398. }
  399. reg |= (I2SR0_CTL_RXMODELSEL(fmt) | I2SR0_CTL_RXWIDTH(rx_width));
  400. if (PHY_DEV_FEATURE(bclk_width))
  401. reg |= I2SR0_CTL_RXBCLKSET;
  402. i2srx_reg->rx_ctl = reg;
  403. /* I2S RX enable */
  404. i2srx_reg->rx_ctl |= I2SR0_CTL_RXEN;
  405. }
  406. /* @brief Disable I2SRX digital function */
  407. static void i2srx_digital_disable(struct device *dev)
  408. {
  409. struct acts_audio_i2srx *i2srx_reg = get_i2srx_reg_base(dev);
  410. i2srx_reg->rx_ctl = 0;
  411. }
  412. /* @brief get the I2SRX sample rate detect counter */
  413. static uint32_t read_i2srx_srd_count(struct device *dev)
  414. {
  415. struct acts_audio_i2srx *i2srx_reg = get_i2srx_reg_base(dev);
  416. /* CNT of LRCLK which sampling by SRC_CLK */
  417. return ((i2srx_reg->srdstat & I2SR0_SRDSTA_CNT_MASK) >> I2SR0_SRDSTA_CNT_SHIFT);
  418. }
  419. /* @brief I2SRX in slave mode handle sample rate detect change */
  420. static void i2srx_srd_fs_change(struct device *dev)
  421. {
  422. const struct phy_i2srx_config_data *cfg = dev->config;
  423. struct phy_i2srx_drv_data *data = dev->data;
  424. uint32_t cnt, fs;
  425. audio_sr_sel_e sr;
  426. cnt = read_i2srx_srd_count(dev);
  427. /* CNT = SRD_CLK / LRCLK and SRD_CLK uses HOSC which is a 32MHz clock source*/
  428. fs = MHZ(CONFIG_HOSC_CLK_MHZ) / cnt;
  429. /* Allow a 1% deviation */
  430. if ((fs > 7920) && (fs < 8080)) { /* 8kfs */
  431. sr = SAMPLE_RATE_8KHZ;
  432. } else if ((fs > 10915) && (fs < 11135)) { /* 11.025kfs */
  433. sr = SAMPLE_RATE_11KHZ;
  434. } else if ((fs > 11880) && (fs < 12120)) { /* 12kfs */
  435. sr = SAMPLE_RATE_12KHZ;
  436. } else if ((fs > 15840) && (fs < 16160)) { /* 16kfs */
  437. sr = SAMPLE_RATE_16KHZ;
  438. } else if ((fs > 21830) && (fs < 22270)) { /* 22.05kfs */
  439. sr = SAMPLE_RATE_22KHZ;
  440. } else if ((fs > 23760) && (fs < 24240)) { /* 24kfs */
  441. sr = SAMPLE_RATE_24KHZ;
  442. } else if ((fs > 31680) && (fs < 32320)) { /* 32kfs */
  443. sr = SAMPLE_RATE_32KHZ;
  444. } else if ((fs > 43659) && (fs < 44541)) { /* 44.1kfs */
  445. sr = SAMPLE_RATE_44KHZ;
  446. } else if ((fs > 47520) && (fs < 48480)) { /* 48kfs */
  447. sr = SAMPLE_RATE_48KHZ;
  448. } else if ((fs > 63360) && (fs < 64640)) { /* 64kfs */
  449. sr = SAMPLE_RATE_64KHZ;
  450. } else if ((fs > 87318) && (fs < 89082)) { /* 88.2kfs */
  451. sr = SAMPLE_RATE_88KHZ;
  452. } else if ((fs > 95040) && (fs < 96960)) { /* 96kfs */
  453. sr = SAMPLE_RATE_96KHZ;
  454. } else if ((fs > 174636) && (fs < 178164)) { /* 176.4kfs */
  455. sr = SAMPLE_RATE_176KHZ;
  456. } else if((fs > 190080) && (fs < 193920)) { /* 192kfs */
  457. sr = SAMPLE_RATE_192KHZ;
  458. } else {
  459. LOG_ERR("Invalid sample rate %d", fs);
  460. return ;
  461. }
  462. LOG_INF("Detect new sample rate %d -> %d", fs, sr);
  463. /* FIXME: If not do the fifo reset, the left and right channel will exchange probably. */
  464. i2srx_fifo_reset(dev);
  465. if (data->sample_rate != sr && PHY_DEV_FEATURE(slave_internal_clk)) {
  466. i2srx_sample_rate_set(dev, sr, data->mclksrc);
  467. data->sample_rate = sr;
  468. }
  469. if (data->srd_callback)
  470. data->srd_callback(data->cb_data, I2SRX_SRD_FS_CHANGE, (void *)&sr);
  471. }
  472. /* @brief I2SRX SRD width length change operation */
  473. void i2srx_srd_wl_change(struct device *dev)
  474. {
  475. struct phy_i2srx_drv_data *data = dev->data;
  476. struct acts_audio_i2srx *i2srx_reg = get_i2srx_reg_base(dev);
  477. uint8_t width;
  478. width = i2srx_reg->srdstat & I2SR0_SRDSTA_WL_MASK;
  479. LOG_DBG("Detect new width length: %d", width);
  480. if (((data->srd_wl == SRDSTA_WL_64RATE) && (width == SRDSTA_WL_32RATE))
  481. || ((data->srd_wl == SRDSTA_WL_32RATE) && (width == SRDSTA_WL_64RATE))) {
  482. data->srd_wl = width;
  483. if (data->srd_callback)
  484. data->srd_callback(data->cb_data, I2SRX_SRD_WL_CHANGE, (void *)&data->srd_wl);
  485. }
  486. }
  487. /* @brief I2SRX sample rate detect function configuration */
  488. static int i2srx_srd_cfg(struct device *dev, uint8_t srd_th, audio_i2s_srd_period_e period, bool irq_en, bool mute)
  489. {
  490. const struct phy_i2srx_config_data *cfg = dev->config;
  491. struct acts_audio_i2srx *i2srx_reg = get_i2srx_reg_base(dev);
  492. uint32_t reg;
  493. uint8_t _wl, wl;
  494. uint32_t start_time, curr_time;
  495. reg = (I2SR0_SRDCTL_SRD_TH(srd_th & 0x7) | I2SR0_SRDCTL_SRD_TH(period));
  496. if (irq_en)
  497. reg |= I2SR0_SRDCTL_SRD_IE;
  498. if (mute)
  499. reg |= I2SR0_SRDCTL_MUTE_EN;
  500. i2srx_reg->srdctl = reg;
  501. /* enable slave mode sample rate detect */
  502. i2srx_reg->srdctl |= I2SR0_SRDCTL_SRD_EN;
  503. if (!PHY_DEV_FEATURE(bclk_width))
  504. wl = SRDSTA_WL_64RATE;
  505. else
  506. wl = SRDSTA_WL_32RATE;
  507. start_time = k_cycle_get_32();
  508. _wl = i2srx_reg->srdstat & I2SR0_SRDSTA_WL_MASK;
  509. while (_wl != wl) {
  510. curr_time = k_cycle_get_32();
  511. if (k_cyc_to_us_floor32(curr_time - start_time) > I2SRX_SRD_CONFIG_TIMEOUT_US) {
  512. LOG_ERR("Wait SRD WL status timeout");
  513. return -ETIMEDOUT;
  514. }
  515. _wl = i2srx_reg->srdstat & I2SR0_SRDSTA_WL_MASK;
  516. k_sleep(K_MSEC(2));
  517. }
  518. i2srx_reg->srdstat |= I2SR0_SRDSTA_CHW_PD;
  519. i2srx_srd_fs_change(dev);
  520. return 0;
  521. }
  522. /* @brief physical I2SRX device enable */
  523. static int phy_i2srx_enable(struct device *dev, void *param)
  524. {
  525. const struct phy_i2srx_config_data *cfg = dev->config;
  526. struct phy_i2srx_drv_data *data = dev->data;
  527. ain_param_t *in_param = (ain_param_t *)param;
  528. i2srx_setting_t *i2srx_setting = in_param->i2srx_setting;
  529. if ((!in_param) || (!i2srx_setting)
  530. || (!in_param->sample_rate)) {
  531. LOG_ERR("Invalid parameters");
  532. return -EINVAL;
  533. }
  534. if (in_param->channel_type != AUDIO_CHANNEL_I2SRX) {
  535. LOG_ERR("Invalid channel type %d", in_param->channel_type);
  536. return -EINVAL;
  537. }
  538. /* enable adc clock */
  539. acts_clock_peripheral_enable(cfg->clk_id);
  540. acts_clock_peripheral_enable(cfg->hclk_clk_id);
  541. if (PHY_DEV_FEATURE(srd_en))
  542. acts_clock_peripheral_enable(cfg->srd_clk_id);
  543. /* slave mode and clock from external source */
  544. if (PHY_DEV_FEATURE(mode)
  545. && !PHY_DEV_FEATURE(slave_internal_clk)) {
  546. data->mclksrc = CLK_SRCRX_I2SRX_EXT;
  547. } else if (PHY_DEV_FEATURE(clk_from_i2stx)) {
  548. if (PHY_DEV_FEATURE(mode)) {
  549. LOG_ERR("clock source form I2STX shall work in master mode");
  550. return -EPERM;
  551. }
  552. data->mclksrc = CLK_SRCRX_I2STX;
  553. } else {
  554. data->mclksrc = CLK_SRCRX_I2SRX;
  555. }
  556. /* I2SRX sample rate set */
  557. if (i2srx_sample_rate_set(dev, in_param->sample_rate, data->mclksrc)) {
  558. LOG_ERR("Failed to config sample rate %d",
  559. in_param->sample_rate);
  560. return -ESRCH;
  561. }
  562. i2srx_fifo_enable(dev, FIFO_SEL_DMA, (in_param->channel_width == CHANNEL_WIDTH_16BITS)
  563. ? DMA_WIDTH_16BITS : DMA_WIDTH_32BITS);
  564. i2srx_digital_enable(dev, in_param->channel_width);
  565. if (PHY_DEV_FEATURE(mode) && PHY_DEV_FEATURE(srd_en)) {
  566. LOG_INF("I2SRX SRD enable");
  567. i2srx_srd_cfg(dev, I2SRX_SRD_TH_DEFAULT, I2S_SRD_2LRCLK, true, false);
  568. data->srd_callback = i2srx_setting->srd_callback;
  569. data->cb_data = i2srx_setting->cb_data;
  570. if (!PHY_DEV_FEATURE(bclk_width))
  571. data->srd_wl = SRDSTA_WL_64RATE;
  572. else
  573. data->srd_wl = SRDSTA_WL_32RATE;
  574. }
  575. data->channel_opened = 1;
  576. return 0;
  577. }
  578. /* @brief physical I2SRX device disable */
  579. static int phy_i2srx_disable(struct device *dev, void *param)
  580. {
  581. const struct phy_i2srx_config_data *cfg = dev->config;
  582. struct phy_i2srx_drv_data *data = dev->data;
  583. i2srx_fifo_disable(dev);
  584. i2srx_digital_disable(dev);
  585. if (PHY_DEV_FEATURE(srd_en))
  586. acts_clock_peripheral_disable(cfg->srd_clk_id);
  587. data->srd_callback = NULL;
  588. data->cb_data = NULL;
  589. if (!PHY_DEV_FEATURE(bclk_width))
  590. data->srd_wl = SRDSTA_WL_64RATE;
  591. else
  592. data->srd_wl = SRDSTA_WL_32RATE;
  593. data->sample_rate = 0;
  594. data->channel_opened = 0;
  595. acts_clock_peripheral_disable(cfg->clk_id);
  596. return 0;
  597. }
  598. /* @brief physical I2SRX IO commands */
  599. static int phy_i2srx_ioctl(struct device *dev, uint32_t cmd, void *param)
  600. {
  601. const struct phy_i2srx_config_data *cfg = dev->config;
  602. struct phy_i2srx_drv_data *data = dev->data;
  603. int ret = 0;
  604. switch (cmd) {
  605. case PHY_CMD_DUMP_REGS:
  606. {
  607. i2srx_dump_register(dev);
  608. break;
  609. }
  610. case AIN_CMD_I2SRX_QUERY_SAMPLE_RATE:
  611. {
  612. *(audio_sr_sel_e *)param = data->sample_rate;
  613. break;
  614. }
  615. case PHY_CMD_I2SRX_IS_OPENED:
  616. {
  617. *(uint8_t *)param = data->channel_opened;
  618. break;
  619. }
  620. case AIN_CMD_GET_SAMPLERATE:
  621. {
  622. ret = i2srx_sample_rate_get(dev);
  623. if (ret < 0) {
  624. LOG_ERR("Failed to get I2SRX sample rate err=%d", ret);
  625. return ret;
  626. }
  627. *(audio_sr_sel_e *)param = (audio_sr_sel_e)ret;
  628. ret = 0;
  629. break;
  630. }
  631. case AIN_CMD_SET_SAMPLERATE:
  632. {
  633. audio_sr_sel_e val = *(audio_sr_sel_e *)param;
  634. ret = i2srx_sample_rate_set(dev, val, data->mclksrc);
  635. if (ret) {
  636. LOG_ERR("Failed to set I2SRX sample rate err=%d", ret);
  637. return ret;
  638. }
  639. break;
  640. }
  641. case AIN_CMD_GET_APS:
  642. {
  643. ret = i2srx_get_pll_aps(dev);
  644. if (ret < 0) {
  645. LOG_ERR("Failed to get audio pll APS err=%d", ret);
  646. return ret;
  647. }
  648. *(audio_aps_level_e *)param = (audio_aps_level_e)ret;
  649. ret = 0;
  650. break;
  651. }
  652. case AIN_CMD_SET_APS:
  653. {
  654. audio_aps_level_e level = *(audio_aps_level_e *)param;
  655. ret = i2srx_set_pll_aps(dev, level);
  656. if (ret) {
  657. LOG_ERR("Failed to set audio pll APS err=%d", ret);
  658. return ret;
  659. }
  660. LOG_DBG("set new aps level %d", level);
  661. break;
  662. }
  663. case PHY_CMD_GET_AIN_DMA_INFO:
  664. {
  665. struct audio_out_dma_info *info = (struct audio_out_dma_info *)param;
  666. info->dma_info.dma_chan = cfg->dma_fifo0.dma_chan;
  667. info->dma_info.dma_dev_name = cfg->dma_fifo0.dma_dev_name;
  668. info->dma_info.dma_id = cfg->dma_fifo0.dma_id;
  669. break;
  670. }
  671. default:
  672. LOG_ERR("Unsupport command %d", cmd);
  673. return -ENOTSUP;
  674. }
  675. return ret;
  676. }
  677. const struct phy_audio_driver_api phy_i2srx_drv_api = {
  678. .audio_enable = phy_i2srx_enable,
  679. .audio_disable = phy_i2srx_disable,
  680. .audio_ioctl = phy_i2srx_ioctl,
  681. };
  682. /* dump i2srx device tree infomation */
  683. static void __i2srx_dt_dump_info(const struct phy_i2srx_config_data *cfg)
  684. {
  685. #if (PHY_DEV_SHOW_DT_INFO == 1)
  686. LOG_INF("** I2SRX BASIC INFO **");
  687. LOG_INF(" BASE: %08x", cfg->reg_base);
  688. LOG_INF(" CLK-ID: %08x", cfg->clk_id);
  689. LOG_INF("SRDCLK-ID: %08x", cfg->srd_clk_id);
  690. LOG_INF(" RST-ID: %08x", cfg->rst_id);
  691. LOG_INF("DMA0-NAME: %s", cfg->dma_fifo0.dma_dev_name);
  692. LOG_INF(" DMA0-ID: %08x", cfg->dma_fifo0.dma_id);
  693. LOG_INF(" DMA0-CH: %08x", cfg->dma_fifo0.dma_chan);
  694. LOG_INF("** I2SRX FEATURES **");
  695. LOG_INF(" SRD-EN: %d", PHY_DEV_FEATURE(srd_en));
  696. LOG_INF(" MODE: %d", PHY_DEV_FEATURE(mode));
  697. LOG_INF(" BCLK-WIDTH: %d", PHY_DEV_FEATURE(bclk_width));
  698. LOG_INF(" CH-NUM: %d", PHY_DEV_FEATURE(channel_num));
  699. LOG_INF(" EXTERNAL-CLK: %d", PHY_DEV_FEATURE(slave_internal_clk));
  700. LOG_INF(" LRCLK-PROC: %d", PHY_DEV_FEATURE(lrclk_proc));
  701. LOG_INF(" TDM-FORMAT: %d", PHY_DEV_FEATURE(tdm_format));
  702. LOG_INF(" TDM-FRAME: %d", PHY_DEV_FEATURE(tdm_frame));
  703. LOG_INF(" MCLK-REVERSE: %d", PHY_DEV_FEATURE(mclk_reverse));
  704. LOG_INF("CLK-FROM-I2STX: %d", PHY_DEV_FEATURE(clk_from_i2stx));
  705. #endif
  706. }
  707. static int phy_i2srx_init(const struct device *dev)
  708. {
  709. const struct phy_i2srx_config_data *cfg = dev->config;
  710. struct phy_i2srx_drv_data *data = dev->data;
  711. /* clear driver data */
  712. memset(data, 0, sizeof(struct phy_i2srx_drv_data));
  713. __i2srx_dt_dump_info(cfg);
  714. /* reset I2SRX controller */
  715. acts_reset_peripheral(cfg->rst_id);
  716. if (cfg->irq_config)
  717. cfg->irq_config();
  718. printk("I2SRX init successfully\n");
  719. return 0;
  720. }
  721. void phy_i2srx_isr(const void *arg)
  722. {
  723. struct device *dev = (struct device *)arg;
  724. struct acts_audio_i2srx *i2srx_reg = get_i2srx_reg_base(dev);
  725. struct phy_i2srx_drv_data *data = dev->data;
  726. LOG_DBG("srdstat: 0x%x", i2srx_reg->srdstat);
  727. /* Sample rate detection timeout irq pending */
  728. if (i2srx_reg->srdstat & I2SR0_SRDSTA_TO_PD) {
  729. i2srx_reg->srdstat |= I2SR0_SRDSTA_TO_PD;
  730. if (data->srd_callback)
  731. data->srd_callback(data->cb_data, I2SRX_SRD_TIMEOUT, NULL);
  732. }
  733. /* Sample rate changed detection irq pending */
  734. if (i2srx_reg->srdstat & I2SR0_SRDSTA_SRC_PD) {
  735. i2srx_reg->srdstat |= I2SR0_SRDSTA_SRC_PD;
  736. i2srx_srd_fs_change(dev);
  737. }
  738. /* Channel width change irq pending */
  739. if (i2srx_reg->srdstat & I2SR0_SRDSTA_CHW_PD) {
  740. i2srx_reg->srdstat |= I2SR0_SRDSTA_CHW_PD;
  741. i2srx_srd_wl_change(dev);
  742. }
  743. }
  744. static void phy_i2srx_irq_config(void);
  745. /* physical i2stx driver data */
  746. static struct phy_i2srx_drv_data phy_i2srx_drv_data0;
  747. /* physical i2stx config data */
  748. static const struct phy_i2srx_config_data phy_i2srx_config_data0 = {
  749. .reg_base = AUDIO_I2SRX0_REG_BASE,
  750. .clk_id = CLOCK_ID_I2SRX,
  751. .srd_clk_id = CLOCK_ID_I2SSRDCLK,
  752. .hclk_clk_id = CLOCK_ID_I2SHCLKEN,
  753. .rst_id = RESET_ID_I2SRX,
  754. AUDIO_DMA_FIFO_DEF(I2SRX, 0),
  755. .irq_config = phy_i2srx_irq_config,
  756. PHY_DEV_FEATURE_DEF(srd_en) = CONFIG_AUDIO_I2SRX_0_SRD_EN,
  757. PHY_DEV_FEATURE_DEF(mode) = CONFIG_AUDIO_I2SRX_0_MODE,
  758. PHY_DEV_FEATURE_DEF(bclk_width) = CONFIG_AUDIO_I2SRX_0_BCLK_WIDTH,
  759. PHY_DEV_FEATURE_DEF(channel_num) = CONFIG_AUDIO_I2SRX_0_CHANNEL_NUM,
  760. PHY_DEV_FEATURE_DEF(slave_internal_clk) = CONFIG_AUDIO_I2SRX_0_SLAVE_INTERNAL_CLK,
  761. PHY_DEV_FEATURE_DEF(lrclk_proc) = CONFIG_AUDIO_I2SRX_0_LRCLK_PROC,
  762. PHY_DEV_FEATURE_DEF(tdm_format) = CONFIG_AUDIO_I2SRX_0_TDM_FORMAT,
  763. PHY_DEV_FEATURE_DEF(tdm_frame) = CONFIG_AUDIO_I2SRX_0_TDM_FRAME,
  764. PHY_DEV_FEATURE_DEF(mclk_reverse) = CONFIG_AUDIO_I2SRX_0_MCLK_REVERSE,
  765. PHY_DEV_FEATURE_DEF(clk_from_i2stx) = CONFIG_AUDIO_I2SRX_0_CLK_FROM_I2STX,
  766. };
  767. #if IS_ENABLED(CONFIG_AUDIO_I2SRX_0)
  768. DEVICE_DEFINE(i2srx0, CONFIG_AUDIO_I2SRX_0_NAME, phy_i2srx_init, NULL,
  769. &phy_i2srx_drv_data0, &phy_i2srx_config_data0,
  770. POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS, &phy_i2srx_drv_api);
  771. #endif
  772. /*
  773. * @brief Enable I2SRX IRQ
  774. * @note I2STX IRQ source as shown below:
  775. * - I2STX FIFO Half Filled IRQ
  776. * - I2STX SRDTO IRQ
  777. * - I2STX SRDSR IRQ
  778. * - I2STX SRDCHW IRQ
  779. */
  780. static void phy_i2srx_irq_config(void)
  781. {
  782. IRQ_CONNECT(IRQ_ID_I2S1, CONFIG_AUDIO_I2SRX_0_IRQ_PRI,
  783. phy_i2srx_isr,
  784. DEVICE_GET(i2srx0), 0);
  785. irq_enable(IRQ_ID_I2S1);
  786. }