phy_audio_i2stx.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388
  1. /*
  2. * Copyright (c) 2020 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief Audio I2STX physical implementation
  9. */
  10. /*
  11. * Features
  12. * - Support master and slave mode
  13. * - Support I2S 2ch format
  14. * - I2STX FIFO(32 x 24bits level) and DAC FIFO(8 x 24 bits 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_out.h>
  29. #include <board.h>
  30. #ifdef CONFIG_CFG_DRV
  31. #include <config.h>
  32. #include <drivers/cfg_drv/driver_config.h>
  33. #endif
  34. #include <logging/log.h>
  35. LOG_MODULE_REGISTER(i2stx0, CONFIG_LOG_DEFAULT_LEVEL);
  36. /***************************************************************************************************
  37. * I2STX_CTL
  38. */
  39. #define I2ST0_CTL_TXD_DELAY_SHIFT (21) /* tx data output delay 0: 2 mclk after bclk rising edge; 1: 3 mclk; 2: 4 mclk; 3" 5 mclk */
  40. #define I2ST0_CTL_TXD_DELAY_MASK (0x3 << I2ST0_CTL_TXD_DELAY_SHIFT)
  41. #define I2ST0_CTL_TXD_DELAY(x) ((x) << I2ST0_CTL_TXD_DELAY_SHIFT)
  42. #define I2ST0_CTL_TDMTX_CHAN BIT(20) /* 4 channel or 8 channel */
  43. #define I2ST0_CTL_TDMTX_MODE BIT(19) /* (TDM-A) I2S format or (TDM-B) left-justified format */
  44. #define I2ST0_CTL_TDMTX_SYNC_SHIFT (17) /* the type of LRCLK setting at the begining of the data frame */
  45. #define I2ST0_CTL_TDMTX_SYNC_MASK (0x3 << I2ST0_CTL_TDMTX_SYNC_SHIFT)
  46. #define I2ST0_CTL_TDMTX_SYNC(x) ((x) << I2ST0_CTL_TDMTX_SYNC_SHIFT)
  47. #define I2ST0_CTL_MULT_DEVICE BIT(16) /* multi device selection */
  48. #define I2ST0_CTL_LPEN0 BIT(8) /* I2STX and I2SRX data loopback enable */
  49. #define I2ST0_CTL_TXWIDTH_SHIFT (4) /* effective data width */
  50. #define I2ST0_CTL_TXWIDTH_MASK (0x3 << I2ST0_CTL_TXWIDTH_SHIFT)
  51. #define I2ST0_CTL_TXWIDTH(x) ((x) << I2ST0_CTL_TXWIDTH_SHIFT)
  52. #define I2ST0_CTL_TXBCLKSET BIT(3) /* bits of BCLK with LRCLK */
  53. #define I2ST0_CTL_TXMODELSEL_SHIFT (1) /* I2S transfer format select */
  54. #define I2ST0_CTL_TXMODELSEL_MASK (0x3 << I2ST0_CTL_TXMODELSEL_SHIFT)
  55. #define I2ST0_CTL_TXMODELSEL(x) ((x) << I2ST0_CTL_TXMODELSEL_SHIFT)
  56. #define I2ST0_CTL_TXEN BIT(0) /* I2S TX Enable */
  57. /***************************************************************************************************
  58. * I2STX_FIFOCTL
  59. */
  60. #define I2ST0_FIFOCTL_FIFO0_VOL_SHIFT (8) /* FIFO volume control */
  61. #define I2ST0_FIFOCTL_FIFO0_VOL_MASK (0xF << I2ST0_FIFOCTL_FIFO0_VOL_SHIFT)
  62. #define I2ST0_FIFOCTL_FIFO0_VOL(x) ((x) << I2ST0_FIFOCTL_FIFO0_VOL_SHIFT)
  63. #define I2ST0_FIFOCTL_TXFIFO_DMAWIDTH BIT(7) /* dma transfer width */
  64. #define I2ST0_FIFOCTL_FIFO_IN_SEL_SHIFT (4) /* I2STX FIFO input select */
  65. #define I2ST0_FIFOCTL_FIFO_IN_SEL_MASK (0x3 << I2ST0_FIFOCTL_FIFO_IN_SEL_SHIFT)
  66. #define I2ST0_FIFOCTL_FIFO_IN_SEL(x) ((x) << I2ST0_FIFOCTL_FIFO_IN_SEL_SHIFT)
  67. #define I2ST0_FIFOCTL_FIFO_SEL BIT(3) /* I2S/SPDIF module FIFO selection */
  68. #define I2ST0_FIFOCTL_FIFO_IEN BIT(2) /* I2STX FIFO half empty irq enable */
  69. #define I2ST0_FIFOCTL_FIFO_DEN BIT(1) /* I2STX FIFO half empty drq enable */
  70. #define I2ST0_FIFOCTL_FIFO_RST BIT(0) /* I2STX FIFO reset */
  71. /***************************************************************************************************
  72. * I2STX_FIFOSTAT
  73. */
  74. #define I2ST0_FIFOSTA_FIFO_ER BIT(8) /* FIFO error */
  75. #define I2ST0_FIFOSTA_IP BIT(7) /* half empty irq pending bit */
  76. #define I2ST0_FIFOSTA_TFFU BIT(6) /* fifo full flag */
  77. #define I2ST0_FIFOSTA_STA_SHIFT (0) /* fifo status */
  78. #define I2ST0_FIFOSTA_STA_MASK (0x3F << I2ST0_FIFOSTA_STA_SHIFT)
  79. /***************************************************************************************************
  80. * I2STX_DAT
  81. */
  82. #define I2ST0_DAT_DAT_SHIFT (8) /* I2STX FIFO is 24bits x 32 levels */
  83. #define I2ST0_DAT_DAT_MASK (0xFFFFFF << I2ST0_DAT_DAT_SHIFT)
  84. /***************************************************************************************************
  85. * I2STX_SRDCTL - I2STX Slave mode sample rate detect register
  86. */
  87. #define I2ST0_SRDCTL_MUTE_EN BIT(12) /* If detect sample rate or channel width changing, mute the TX output as 0 */
  88. #define I2ST0_SRDCTL_SRD_IE BIT(8) /* sample rate detect result change interrupt enable */
  89. #define I2ST0_SRDCTL_CNT_TIM_SHIFT (4) /* slave mode sample rate detect counter period select */
  90. #define I2ST0_SRDCTL_CNT_TIM_MASK (0x3 << I2ST0_SRDCTL_CNT_TIM_SHIFT)
  91. #define I2ST0_SRDCTL_CNT_TIM(x) ((x) << I2ST0_SRDCTL_CNT_TIM_SHIFT)
  92. #define I2ST0_SRDCTL_SRD_TH_SHIFT (1) /* sample rate detecting sensitivity setting */
  93. #define I2ST0_SRDCTL_SRD_TH_MASK (0x7 << I2ST0_SRDCTL_SRD_TH_SHIFT)
  94. #define I2ST0_SRDCTL_SRD_TH(x) ((x) << I2ST0_SRDCTL_SRD_TH_SHIFT)
  95. #define I2ST0_SRDCTL_SRD_EN BIT(0) /* slave mode sample rate detect enable */
  96. /***************************************************************************************************
  97. * I2STX_SRDSTA
  98. */
  99. #define I2ST0_SRDSTA_CNT_SHIFT (12) /* CNT of LRCLK which sampling by SRC_CLK */
  100. #define I2ST0_SRDSTA_CNT_MASK (0x1FFF << I2ST0_SRDSTA_CNT_SHIFT)
  101. #define I2ST0_SRDSTA_CNT(x) ((x) << I2ST0_SRDSTA_CNT_SHIFT)
  102. #define I2ST0_SRDSTA_TO_PD BIT(11) /* SRD timput irq pending */
  103. #define I2ST0_SRDSTA_SRC_PD BIT(10) /* sample rate changing detection interrupt pending */
  104. #define I2ST0_SRDSTA_CHW_PD BIT(8) /* channel width change irq pending */
  105. #define I2ST0_SRDSTA_WL_SHIFT (0) /* channel word lenght */
  106. #define I2ST0_SRDSTA_WL_MASK (0x7 << I2ST0_SRDSTA_WL_SHIFT)
  107. #define I2ST0_SRDSTA_WL(x) ((x) << I2ST0_SRDSTA_WL_SHIFT)
  108. /***************************************************************************************************
  109. * I2STX_FIFO_CNT
  110. */
  111. #define I2ST0_FIFO_CNT_IP BIT(18) /* I2STX FIFO counter overflow irq pending */
  112. #define I2ST0_FIFO_CNT_IE BIT(17) /* I2STX FIFO counter overflow irq enable */
  113. #define I2ST0_FIFO_CNT_EN BIT(16) /* I2STX FIFO counter enable */
  114. #define I2ST0_FIFO_CNT_CNT_SHIFT (0) /* I2STX FIFO counter */
  115. #define I2ST0_FIFO_CNT_CNT_MASK (0xFFFF << I2ST0_FIFO_CNT_CNT_SHIFT)
  116. /***************************************************************************************************
  117. * i2STX FEATURES CONGIURATION
  118. */
  119. /* The sensitivity of the SRD */
  120. #define I2STX_SRD_TH_DEFAULT (7)
  121. #define I2STX_BCLK_DIV_DEFAULT (0) /* MCLK = 4BCLK */
  122. #define I2STX_FIFO_LEVEL (32)
  123. #define I2STX_SRD_CONFIG_TIMEOUT_US (500000)
  124. #define I2STX_FIFO_MAX_VOL_LEVEL (0xF)
  125. #define I2STX_FIFO_VOL_LEVEL_DEFAULT (0x3) /* 0db */
  126. /*
  127. * enum a_i2s_mclk_clksrc_e
  128. * @brief The MCLK clock source of i2stx selection
  129. */
  130. typedef enum {
  131. CLK_SRCTX_I2STX = 0, /* I2STX clock source from I2STX MCLK */
  132. CLK_SRCTX_DAC_256FS, /* I2STX clock source from DAC 256FS */
  133. CLK_SRCTX_DAC_128FS, /* I2STX clock source from DAC 256FS */
  134. CLK_SRCTX_I2STX_EXT, /* I2STX clock source from I2STX extern MCLK */
  135. } a_i2stx_mclk_clksrc_e;
  136. /*
  137. * @struct acts_audio_i2stx0
  138. * @brief I2STX controller hardware register
  139. */
  140. struct acts_audio_i2stx {
  141. volatile uint32_t tx_ctl; /* I2STX control */
  142. volatile uint32_t fifoctl; /* I2STX FIFO control */
  143. volatile uint32_t fifostat; /* I2STX FIFO state */
  144. volatile uint32_t dat; /* I2STX FIFO data */
  145. volatile uint32_t srdctl; /* I2S slave mode TX sample rate detect control */
  146. volatile uint32_t srdstat; /* I2S slave mode TX sample rate detect state */
  147. volatile uint32_t reserved[2]; /* reserved space */
  148. volatile uint32_t fifocnt; /* I2STX out FIFO counter */
  149. };
  150. #ifdef CONFIG_CFG_DRV
  151. /**
  152. * struct phy_i2stx_external_config
  153. * @brief The I2STX external configuration which generated by configuration tool.
  154. */
  155. struct phy_i2stx_external_config {
  156. CFG_Type_I2S_Select_GPIO I2STX_Select_GPIO; /* I2STX PINs setting */
  157. };
  158. #endif
  159. /*
  160. * struct phy_i2stx_drv_data
  161. * @brief The software related data that used by physical i2stx driver.
  162. */
  163. struct phy_i2stx_drv_data {
  164. uint8_t mclksrc; /* MCLK clock source selection refer to #a_i2stx_mclk_clksrc_e */
  165. uint32_t fifo_cnt; /* I2STX FIFO hardware counter max value is 0xFFFF */
  166. int (*srd_callback)(void *cb_data, uint32_t cmd, void *param);
  167. void *cb_data;
  168. uint8_t srd_wl; /* The width length detected by SRD */
  169. uint8_t fifo_use; /* Record the used FIFO */
  170. #ifdef CONFIG_CFG_DRV
  171. struct phy_i2stx_external_config external_config; /* I2STX external configuration */
  172. #endif
  173. uint8_t link_with_dac : 1; /* The flag of linkage with dac */
  174. uint8_t channel_opened : 1; /* flag of channel opened */
  175. };
  176. /**
  177. * union phy_i2stx_features
  178. * @brief The infomation from DTS to control the I2STX features to enable or nor.
  179. */
  180. typedef union {
  181. uint32_t raw;
  182. struct {
  183. uint32_t srd_en : 1; /* SRD function enable or not */
  184. uint32_t mode : 1; /* master mode or slaver mode; 0: master 1: slaver */
  185. uint32_t channel_num : 4; /* channel number and only support 2/4/8 channels */
  186. uint32_t slave_internal_clk : 1; /* slave mode MCLK to use internal clock */
  187. uint32_t lrclk_proc : 1; /* LRCLK process 0: 50% DUTY; 1: 1 BCLK */
  188. uint32_t mclk_reverse : 1; /* mclk reverse */
  189. uint32_t always_open : 1; /* BCLK/LRCLK always existed */
  190. uint32_t format : 2; /* I2S transfer format */
  191. uint32_t tdm_format : 1; /* TDM format */
  192. uint32_t tdm_frame : 2; /* TDM frame start position */
  193. uint32_t bclk_width : 1; /* bclk width */
  194. uint32_t txd_delay : 2; /* I2STX data delay */
  195. } v;
  196. } phy_i2stx_features;
  197. /**
  198. * struct phy_i2stx_config_data
  199. * @brief The hardware related data that used by physical i2stx driver.
  200. */
  201. struct phy_i2stx_config_data {
  202. uint32_t reg_base; /* I2STX controller register base address */
  203. uint8_t clk_id; /* I2STX devclk id */
  204. uint8_t srd_clk_id; /* I2S SRD clock id */
  205. uint8_t hclk_clk_id; /* I2S HCLK clock id */
  206. uint8_t rst_id; /* I2STX reset id */
  207. struct audio_dma_dt dma_fifo0; /* DMA resource for SPDIFRX */
  208. void (*irq_config)(void); /* IRQ configuration function */
  209. phy_i2stx_features features; /* I2STX features */
  210. };
  211. /* @brief Get the I2STX controller base address */
  212. static inline struct acts_audio_i2stx *get_i2stx_reg_base(struct device *dev)
  213. {
  214. const struct phy_i2stx_config_data *cfg = dev->config;
  215. return (struct acts_audio_i2stx *)cfg->reg_base;
  216. }
  217. /* @brief Dump the I2STX relative registers */
  218. static void i2stx_dump_register(struct device *dev)
  219. {
  220. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  221. LOG_INF("** i2stx contoller regster **");
  222. LOG_INF(" BASE: %08x", (uint32_t)i2stx_reg);
  223. LOG_INF(" I2STX_CTL: %08x", i2stx_reg->tx_ctl);
  224. LOG_INF(" I2STX_FIFOCTL: %08x", i2stx_reg->fifoctl);
  225. LOG_INF(" I2STX_FIFOSTA: %08x", i2stx_reg->fifostat);
  226. LOG_INF(" I2STX_DAT: %08x", i2stx_reg->dat);
  227. LOG_INF(" I2STX_SRDCTL: %08x", i2stx_reg->srdctl);
  228. LOG_INF(" I2STX_SRDSTA: %08x", i2stx_reg->srdstat);
  229. LOG_INF(" I2STX_FIFOCNT: %08x", i2stx_reg->fifocnt);
  230. LOG_INF(" AUDIOPLL0_CTL: %08x", sys_read32(AUDIO_PLL0_CTL));
  231. LOG_INF(" AUDIOPLL1_CTL: %08x", sys_read32(AUDIO_PLL1_CTL));
  232. LOG_INF(" CMU_DACCLK: %08x", sys_read32(CMU_DACCLK));
  233. LOG_INF(" CMU_I2STXCLK: %08x", sys_read32(CMU_I2STXCLK));
  234. }
  235. /* @brief I2STX sample rate config */
  236. static int i2stx_sample_rate_set(struct device *dev, uint16_t sr_khz,
  237. a_i2stx_mclk_clksrc_e mclk_src, bool direct_set)
  238. {
  239. const struct phy_i2stx_config_data *cfg = dev->config;
  240. int ret;
  241. uint8_t pre_div, clk_div, series, pll_index;
  242. uint32_t reg = 0, reg1;
  243. uint32_t lrclk_div;
  244. a_mclk_type_e mclk;
  245. if (!PHY_DEV_FEATURE(bclk_width))
  246. mclk = MCLK_256FS;
  247. else
  248. mclk = MCLK_128FS;
  249. if (direct_set) {
  250. reg = sys_read32(CMU_I2STXCLK) & ~CMU_I2STXCLK_I2SG0MCLKSRC_MASK;
  251. goto out;
  252. }
  253. if (CLK_SRCTX_I2STX_EXT != mclk_src) {
  254. /* make external MCLK clock phase reverse */
  255. if (PHY_DEV_FEATURE(mclk_reverse))
  256. reg |= CMU_I2STXCLK_I2SG0MCLKEXTREV;
  257. /* I2S master mode to enable MCLK output to PAD */
  258. if (!PHY_DEV_FEATURE(mode)) {
  259. reg |= CMU_I2STXCLK_I2STXMCLKOEN;
  260. } else {
  261. if (PHY_DEV_FEATURE(slave_internal_clk))
  262. sr_khz *= 2; /* slave mode use internal clk condition: MCLK > 6BCLK */
  263. /* BCLK/LRCLK source from external PAD */
  264. reg |= CMU_I2STXCLK_I2SG0BLRCLKSRC;
  265. }
  266. if (PHY_DEV_FEATURE(lrclk_proc))
  267. reg |= CMU_I2STXCLK_I2SG0LRCLKPROC;
  268. /* BCLK = FS x channel number x channel bit width */
  269. if (!PHY_DEV_FEATURE(bclk_width))
  270. lrclk_div = PHY_DEV_FEATURE(channel_num) * 32;
  271. else
  272. lrclk_div = PHY_DEV_FEATURE(channel_num) * 16;
  273. /* LRCLK divisor 0:32; 1:64; 2: 128; 3:256 */
  274. if (32 == lrclk_div) {
  275. lrclk_div = 0;
  276. } else if (64 == lrclk_div) {
  277. lrclk_div = 1;
  278. } else if (128 == lrclk_div) {
  279. lrclk_div = 2;
  280. } else if (256 == lrclk_div) {
  281. lrclk_div = 3;
  282. } else {
  283. LOG_ERR("invalid lrclk divisor:%d", lrclk_div);
  284. return -EINVAL;
  285. }
  286. reg |= CMU_I2STXCLK_I2SG0LRCLKDIV(lrclk_div);
  287. /* MCLK = 4 x BCLK */
  288. reg |= CMU_I2STXCLK_I2SG0BCLKDIV(I2STX_BCLK_DIV_DEFAULT);
  289. sr_khz = PHY_DEV_FEATURE(channel_num) / 2 * sr_khz;
  290. }
  291. if ((CLK_SRCTX_DAC_256FS == mclk_src)
  292. || (CLK_SRCTX_DAC_128FS == mclk_src)) {
  293. /* Get audio PLL setting */
  294. ret = audio_get_pll_setting(sr_khz, MCLK_256FS, &pre_div, &clk_div, &series);
  295. if (ret) {
  296. LOG_DBG("get pll setting error:%d", ret);
  297. return ret;
  298. }
  299. ret = audio_pll_check_config(series, &pll_index);
  300. if (ret) {
  301. LOG_DBG("check pll config error:%d", ret);
  302. return ret;
  303. }
  304. reg1 = sys_read32(CMU_DACCLK) & ~0x1FF;
  305. reg1 |= (pll_index & 0x1) << CMU_DACCLK_DACCLKSRC;
  306. reg1 |= (pre_div << CMU_DACCLK_DACCLKPREDIV) | (clk_div << CMU_DACCLK_DACCLKDIV_SHIFT);
  307. sys_write32(reg1, CMU_DACCLK);
  308. } else if (CLK_SRCTX_I2STX == mclk_src) {
  309. /* Get audio PLL setting */
  310. ret = audio_get_pll_setting_i2s(sr_khz, mclk, &clk_div, &series);
  311. if (ret) {
  312. LOG_DBG("get pll setting error:%d", ret);
  313. return ret;
  314. }
  315. ret = audio_pll_check_config(series, &pll_index);
  316. if (ret) {
  317. LOG_DBG("check pll config error:%d", ret);
  318. return ret;
  319. }
  320. reg |= (pll_index & 0x1) << CMU_I2STXCLK_I2SG0CLKSRC;
  321. reg |= clk_div << CMU_I2STXCLK_I2SG0CLKDIV_SHIFT;
  322. } else if (CLK_SRCTX_I2STX_EXT == mclk_src) {
  323. /* BCLK/LRCLK source from external PAD */
  324. reg |= CMU_I2STXCLK_I2SG0BLRCLKSRC;
  325. LOG_INF("I2STX clock source from external");
  326. } else {
  327. LOG_ERR("Invalid i2stx clk source %d", mclk_src);
  328. return -EINVAL;
  329. }
  330. out:
  331. /* Select the i2stx mclk source */
  332. reg |= CMU_I2STXCLK_I2SG0MCLKSRC(mclk_src & 0x3);
  333. sys_write32(reg, CMU_I2STXCLK);
  334. return 0;
  335. }
  336. /* @brief Get the sample rate from the I2STX config */
  337. static int i2stx_sample_rate_get(struct device *dev)
  338. {
  339. const struct phy_i2stx_config_data *cfg = dev->config;
  340. uint8_t pre_div, clk_div, pll_index, mclk_src;
  341. uint32_t reg;
  342. int ret = -1;
  343. a_mclk_type_e mclk;
  344. if (!PHY_DEV_FEATURE(bclk_width))
  345. mclk = MCLK_256FS;
  346. else
  347. mclk = MCLK_128FS;
  348. reg = sys_read32(CMU_I2STXCLK);
  349. mclk_src = (reg & CMU_I2STXCLK_I2SG0MCLKSRC_MASK) >> CMU_I2STXCLK_I2SG0MCLKSRC_SHIFT;
  350. if ((CLK_SRCTX_DAC_256FS == mclk_src)
  351. || (CLK_SRCTX_DAC_128FS == mclk_src)) {
  352. reg = sys_read32(CMU_DACCLK);
  353. pll_index = (reg >> CMU_DACCLK_DACCLKSRC) & 0x1;
  354. pre_div = (reg & (1 << CMU_DACCLK_DACCLKPREDIV)) >> CMU_DACCLK_DACCLKPREDIV;
  355. clk_div = reg & CMU_DACCLK_DACCLKDIV_MASK;
  356. ret = audio_get_pll_sample_rate(MCLK_256FS, pre_div, clk_div, pll_index);
  357. } else if (CLK_SRCTX_I2STX == mclk_src) {
  358. reg = sys_read32(CMU_I2STXCLK);
  359. clk_div = reg & 0xF;
  360. pll_index = (reg >> CMU_I2STXCLK_I2SG0CLKSRC) & 0x1;
  361. ret = audio_get_pll_sample_rate_i2s(mclk, clk_div, pll_index);
  362. } else if (CLK_SRCTX_I2STX_EXT == mclk_src) {
  363. LOG_INF("I2STX is using the external clock");
  364. ret = -ENOENT;
  365. }
  366. return ret;
  367. }
  368. /* @brief Get the AUDIO_PLL APS used by I2STX */
  369. static int i2stx_get_pll_aps(struct device *dev)
  370. {
  371. uint32_t reg;
  372. uint8_t pll_index, mclk_src;
  373. int ret = -1;
  374. reg = sys_read32(CMU_I2STXCLK);
  375. mclk_src = (reg & CMU_I2STXCLK_I2SG0MCLKSRC_MASK) >> CMU_I2STXCLK_I2SG0MCLKSRC_SHIFT;
  376. /* If I2STX CLK from DAC_CLK, the APS regulation will be called at DAC APIs */
  377. if (CLK_SRCTX_I2STX == mclk_src) {
  378. pll_index = (reg & (1 << CMU_I2STXCLK_I2SG0CLKSRC)) >> CMU_I2STXCLK_I2SG0CLKSRC;
  379. ret = audio_pll_get_aps((a_pll_type_e)pll_index);
  380. } else if (CLK_SRCTX_I2STX_EXT == mclk_src) {
  381. LOG_INF("I2STX is using the external clock source");
  382. ret = -ENOENT;
  383. } else {
  384. ret = -EPERM;
  385. }
  386. return ret;
  387. }
  388. /* @brief Set the AUDIO_PLL APS used by I2STX */
  389. static int i2stx_set_pll_aps(struct device *dev, audio_aps_level_e level)
  390. {
  391. uint32_t reg;
  392. uint8_t pll_index, mclk_src;
  393. int ret = -1;
  394. reg = sys_read32(CMU_I2STXCLK);
  395. mclk_src = (reg & CMU_I2STXCLK_I2SG0MCLKSRC_MASK) >> CMU_I2STXCLK_I2SG0MCLKSRC_SHIFT;
  396. /* If I2STX CLK from DAC_CLK, the APS regulation will be called at DAC APIs */
  397. if (CLK_SRCTX_I2STX == mclk_src) {
  398. pll_index = (reg & (1 << CMU_I2STXCLK_I2SG0CLKSRC)) >> CMU_I2STXCLK_I2SG0CLKSRC;
  399. ret = audio_pll_set_aps((a_pll_type_e)pll_index, level);
  400. } else if (CLK_SRCTX_I2STX_EXT == mclk_src) {
  401. LOG_INF("I2STX is using the external clock");
  402. ret = -ENOENT;
  403. } else {
  404. ret = -EPERM;
  405. }
  406. return ret;
  407. }
  408. /* @brief Disable the I2STX FIFO */
  409. static void i2stx_fifo_disable(struct device *dev)
  410. {
  411. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  412. i2stx_reg->fifoctl = 0;
  413. }
  414. /* @brief Reset the I2STX FIFO */
  415. static void i2stx_fifo_reset(struct device *dev)
  416. {
  417. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  418. i2stx_reg->fifoctl &= ~I2ST0_FIFOCTL_FIFO_RST;
  419. i2stx_reg->fifoctl |= I2ST0_FIFOCTL_FIFO_RST;
  420. }
  421. /* @brief Check the I2STX FIFO is working or not */
  422. static bool is_i2stx_fifo_working(struct device *dev)
  423. {
  424. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  425. return !!(i2stx_reg->fifoctl & I2ST0_FIFOCTL_FIFO_RST);
  426. }
  427. /* @brief Check the I2STX FIFO is error */
  428. static bool check_i2stx_fifo_error(struct device *dev)
  429. {
  430. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  431. if (i2stx_reg->fifostat & I2ST0_FIFOSTA_FIFO_ER) {
  432. i2stx_reg->fifostat |= I2ST0_FIFOSTA_FIFO_ER;
  433. return true;
  434. }
  435. return false;
  436. }
  437. /* @brief Get the I2STX FIFO status which indicates how many samples not filled */
  438. static uint32_t i2stx_fifo_status(struct device *dev)
  439. {
  440. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  441. return (i2stx_reg->fifostat & I2ST0_FIFOSTA_STA_MASK) >> I2ST0_FIFOSTA_STA_SHIFT;
  442. }
  443. /* @brief Enable the I2STX FIFO */
  444. static void i2stx_fifo_enable(struct device *dev, audio_fifouse_sel_e sel, audio_dma_width_e width, bool this_use)
  445. {
  446. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  447. uint32_t reg = 0;
  448. LOG_DBG("I2STX sel:%d width:%d this_use:%d", sel, width, this_use);
  449. /* If the I2STX FIFO is used by SPDIFTX, the FIFO_SEL shall set to DAC FIFO source, otherwise will get no dma IRQ */
  450. if (!this_use)
  451. reg = I2ST0_FIFOCTL_FIFO_SEL; /* 0: I2STX FIFO; 1: DAC FIFO */
  452. /* set I2STX FIFO default volume*/
  453. reg &= ~I2ST0_FIFOCTL_FIFO0_VOL_MASK;
  454. reg |= I2ST0_FIFOCTL_FIFO0_VOL(I2STX_FIFO_VOL_LEVEL_DEFAULT);
  455. if (DMA_WIDTH_16BITS == width)
  456. reg |= I2ST0_FIFOCTL_TXFIFO_DMAWIDTH;
  457. if (FIFO_SEL_CPU == sel) {
  458. reg |= (I2ST0_FIFOCTL_FIFO_IEN | I2ST0_FIFOCTL_FIFO_RST);
  459. } else if (FIFO_SEL_DMA == sel) {
  460. reg |= (I2ST0_FIFOCTL_FIFO_DEN | I2ST0_FIFOCTL_FIFO_RST
  461. | I2ST0_FIFOCTL_FIFO_IN_SEL(1));
  462. } else if (FIFO_SEL_DSP == sel) {
  463. reg |= I2ST0_FIFOCTL_FIFO_IN_SEL(3) | I2ST0_FIFOCTL_FIFO_RST;
  464. } else {
  465. LOG_ERR("invalid fifo sel %d", sel);
  466. }
  467. i2stx_reg->fifoctl = reg;
  468. }
  469. /* @brief Enable the I2STX FIFO counter function */
  470. static void i2stx_fifocount_enable(struct device *dev)
  471. {
  472. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  473. uint32_t reg = 0;
  474. reg = I2ST0_FIFO_CNT_EN;
  475. reg |= I2ST0_FIFO_CNT_IE;
  476. reg |= I2ST0_FIFO_CNT_IP;
  477. i2stx_reg->fifocnt = reg;
  478. LOG_INF("I2STX sample counter enable");
  479. }
  480. /* @brief Disable the I2STX FIFO counter function */
  481. static void i2stx_fifocount_disable(struct device *dev)
  482. {
  483. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  484. i2stx_reg->fifocnt &= ~(I2ST0_FIFO_CNT_EN | I2ST0_FIFO_CNT_IE);
  485. }
  486. /* @brief Reset the I2STX FIFO counter function and by default to enable IRQ */
  487. static void i2stx_fifocount_reset(struct device *dev)
  488. {
  489. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  490. i2stx_reg->fifocnt &= ~(I2ST0_FIFO_CNT_EN | I2ST0_FIFO_CNT_IE);
  491. i2stx_reg->fifocnt |= I2ST0_FIFO_CNT_EN;
  492. i2stx_reg->fifocnt |= I2ST0_FIFO_CNT_IE;
  493. }
  494. /* @brief Enable the I2STX FIFO counter function */
  495. static uint32_t i2stx_read_fifocount(struct device *dev)
  496. {
  497. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  498. return i2stx_reg->fifocnt & I2ST0_FIFO_CNT_CNT_MASK;
  499. }
  500. /* @brief set the I2STX FIFO volume */
  501. static int i2stx_fifo_volume_set(struct device *dev, uint8_t vol)
  502. {
  503. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  504. uint32_t reg = i2stx_reg->fifoctl;
  505. /**
  506. * FIFO VOLUME LEVEL <=> db
  507. * - 0: 3db
  508. * - 1: 2db
  509. * - 2: 1db
  510. * ... ...
  511. * - 0xe: -11db
  512. * - 0xf: -12db
  513. */
  514. if (vol > I2STX_FIFO_MAX_VOL_LEVEL)
  515. vol = I2STX_FIFO_MAX_VOL_LEVEL;
  516. reg &= ~I2ST0_FIFOCTL_FIFO0_VOL_MASK;
  517. reg |= I2ST0_FIFOCTL_FIFO0_VOL(vol);
  518. i2stx_reg->fifoctl = reg;
  519. return 0;
  520. }
  521. /* @brief get the I2STX FIFO volume */
  522. static int i2stx_fifo_volume_get(struct device *dev)
  523. {
  524. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  525. uint32_t reg = i2stx_reg->fifoctl;
  526. int val;
  527. val = (reg & I2ST0_FIFOCTL_FIFO0_VOL_MASK) >> I2ST0_FIFOCTL_FIFO0_VOL_SHIFT;
  528. return val;
  529. }
  530. /* @brief I2STX digital function control enable */
  531. static void i2stx_digital_enable(struct device *dev, audio_ch_width_e width, bool en)
  532. {
  533. const struct phy_i2stx_config_data *cfg = dev->config;
  534. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  535. uint32_t reg = i2stx_reg->tx_ctl & ~(0x3E);
  536. uint8_t tx_width, fmt = PHY_DEV_FEATURE(format);
  537. /* By default TXD = 2MCLK */
  538. reg |= I2ST0_CTL_TXD_DELAY(PHY_DEV_FEATURE(txd_delay));
  539. if (CHANNEL_WIDTH_16BITS == width)
  540. tx_width = 0;
  541. else if (CHANNEL_WIDTH_20BITS == width)
  542. tx_width = 1;
  543. else
  544. tx_width = 2;
  545. if (PHY_DEV_FEATURE(channel_num) != 2) {
  546. fmt = 3; /* TDM mode */
  547. reg &= ~ (0xF << I2ST0_CTL_TDMTX_SYNC_SHIFT);
  548. if (PHY_DEV_FEATURE(channel_num) == 8)
  549. reg |= I2ST0_CTL_TDMTX_CHAN; /* 0: 4 channels; 1: 8 channels */
  550. if (PHY_DEV_FEATURE(tdm_format))
  551. reg |= I2ST0_CTL_TDMTX_MODE; /* 0: I2S format; 1: Left-justified format */
  552. reg |= I2ST0_CTL_TDMTX_SYNC(PHY_DEV_FEATURE(tdm_frame));
  553. }
  554. reg |= (I2ST0_CTL_TXMODELSEL(fmt) | I2ST0_CTL_TXWIDTH(tx_width));
  555. if (PHY_DEV_FEATURE(bclk_width))
  556. reg |= I2ST0_CTL_TXBCLKSET;
  557. i2stx_reg->tx_ctl = reg;
  558. /* I2S TX enable */
  559. if (en)
  560. i2stx_reg->tx_ctl |= I2ST0_CTL_TXEN;
  561. }
  562. /* @brief I2STX digital function control disable */
  563. static void i2stx_digital_disable(struct device *dev)
  564. {
  565. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  566. i2stx_reg->tx_ctl = 0;
  567. }
  568. /* @brief I2STX sample rate detect function configuration */
  569. static int i2stx_srd_cfg(struct device *dev, uint8_t srd_th, audio_i2s_srd_period_e period, bool irq_en, bool mute)
  570. {
  571. const struct phy_i2stx_config_data *cfg = dev->config;
  572. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  573. uint32_t reg;
  574. uint8_t _wl, wl;
  575. uint32_t start_time, curr_time;
  576. reg = (I2ST0_SRDCTL_SRD_TH(srd_th & 0x7) | I2ST0_SRDCTL_CNT_TIM(period));
  577. if (irq_en)
  578. reg |= I2ST0_SRDCTL_SRD_IE;
  579. if (mute)
  580. reg |= I2ST0_SRDCTL_MUTE_EN;
  581. i2stx_reg->srdctl = reg;
  582. /* enable slave mode sample rate detect */
  583. i2stx_reg->srdctl |= I2ST0_SRDCTL_SRD_EN;
  584. if (!PHY_DEV_FEATURE(bclk_width))
  585. wl = SRDSTA_WL_64RATE;
  586. else
  587. wl = SRDSTA_WL_32RATE;
  588. start_time = k_cycle_get_32();
  589. _wl = i2stx_reg->srdstat & I2ST0_SRDSTA_WL_MASK;
  590. while (_wl != wl) {
  591. curr_time = k_cycle_get_32();
  592. if (k_cyc_to_us_floor32(curr_time - start_time) > I2STX_SRD_CONFIG_TIMEOUT_US) {
  593. LOG_ERR("Wait SRD WL status timeout");
  594. return -ETIMEDOUT;
  595. }
  596. _wl = i2stx_reg->srdstat & I2ST0_SRDSTA_WL_MASK;
  597. k_sleep(K_MSEC(2));
  598. }
  599. return 0;
  600. }
  601. /* @brief get the I2STX sample rate detect counter */
  602. static uint32_t read_i2stx_srd_count(struct device *dev)
  603. {
  604. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  605. /* CNT of LRCLK which sampling by SRC_CLK */
  606. return ((i2stx_reg->srdstat & I2ST0_SRDSTA_CNT_MASK) >> I2ST0_SRDSTA_CNT_SHIFT);
  607. }
  608. /* @brief I2STX in slave mode handle sample rate detect change */
  609. void i2stx_srd_fs_change(struct device *dev)
  610. {
  611. const struct phy_i2stx_config_data *cfg = dev->config;
  612. struct phy_i2stx_drv_data *data = dev->data;
  613. uint32_t cnt, fs;
  614. audio_sr_sel_e sr;
  615. cnt = read_i2stx_srd_count(dev);
  616. /* CNT = SRD_CLK / LRCLK and SRD_CLK uses HOSC which is a 32MHz clock source*/
  617. fs = 32000000 / cnt;
  618. /* Allow a 1% deviation */
  619. if ((fs > 7920) && (fs < 8080)) { /* 8kfs */
  620. sr = SAMPLE_RATE_8KHZ;
  621. } else if ((fs > 10915) && (fs < 11135)) { /* 11.025kfs */
  622. sr = SAMPLE_RATE_11KHZ;
  623. } else if ((fs > 11880) && (fs < 12120)) { /* 12kfs */
  624. sr = SAMPLE_RATE_12KHZ;
  625. } else if ((fs > 15840) && (fs < 16160)) { /* 16kfs */
  626. sr = SAMPLE_RATE_16KHZ;
  627. } else if ((fs > 21830) && (fs < 22270)) { /* 22.05kfs */
  628. sr = SAMPLE_RATE_22KHZ;
  629. } else if ((fs > 23760) && (fs < 24240)) { /* 24kfs */
  630. sr = SAMPLE_RATE_24KHZ;
  631. } else if ((fs > 31680) && (fs < 32320)) { /* 32kfs */
  632. sr = SAMPLE_RATE_32KHZ;
  633. } else if ((fs > 43659) && (fs < 44541)) { /* 44.1kfs */
  634. sr = SAMPLE_RATE_44KHZ;
  635. } else if ((fs > 47520) && (fs < 48480)) { /* 48kfs */
  636. sr = SAMPLE_RATE_48KHZ;
  637. } else if ((fs > 63360) && (fs < 64640)) { /* 64kfs */
  638. sr = SAMPLE_RATE_64KHZ;
  639. } else if ((fs > 87318) && (fs < 89082)) { /* 88.2kfs */
  640. sr = SAMPLE_RATE_88KHZ;
  641. } else if ((fs > 95040) && (fs < 96960)) { /* 96kfs */
  642. sr = SAMPLE_RATE_96KHZ;
  643. } else if ((fs > 174636) && (fs < 178164)) { /* 176.4kfs */
  644. sr = SAMPLE_RATE_176KHZ;
  645. } else if((fs > 190080) && (fs < 193920)) { /* 192kfs */
  646. sr = SAMPLE_RATE_192KHZ;
  647. } else {
  648. LOG_ERR("Invalid sample rate %d", fs);
  649. return ;
  650. }
  651. LOG_INF("Detect new sample rate %d -> %d", fs, sr);
  652. /* FIXME: If not do the fifo reset, the left and right channel will exchange probably. */
  653. if (data->fifo_use == AOUT_FIFO_I2STX0)
  654. i2stx_fifo_reset(dev);
  655. if (PHY_DEV_FEATURE(slave_internal_clk))
  656. i2stx_sample_rate_set(dev, sr, data->mclksrc, false);
  657. if (data->srd_callback)
  658. data->srd_callback(data->cb_data, I2STX_SRD_FS_CHANGE, (void *)&sr);
  659. }
  660. /* @brief I2STX SRD width length change operation */
  661. void i2stx_srd_wl_change(struct device *dev)
  662. {
  663. struct phy_i2stx_drv_data *data = dev->data;
  664. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  665. uint8_t width;
  666. width = i2stx_reg->srdstat & I2ST0_SRDSTA_WL_MASK;
  667. LOG_INF("Detect new width length: %d", width);
  668. if (((data->srd_wl == SRDSTA_WL_64RATE) && (width == SRDSTA_WL_32RATE))
  669. || ((data->srd_wl == SRDSTA_WL_32RATE) && (width == SRDSTA_WL_64RATE))) {
  670. data->srd_wl = width;
  671. if (data->srd_callback)
  672. data->srd_callback(data->cb_data, I2STX_SRD_WL_CHANGE, (void *)&data->srd_wl);
  673. }
  674. }
  675. static int phy_i2stx_prepare_enable(struct device *dev, aout_param_t *out_param)
  676. {
  677. const struct phy_i2stx_config_data *cfg = dev->config;
  678. if ((!out_param) || (!out_param->i2stx_setting)
  679. || (!out_param->sample_rate)) {
  680. LOG_ERR("Invalid parameters");
  681. return -EINVAL;
  682. }
  683. if (!(out_param->channel_type & AUDIO_CHANNEL_I2STX)) {
  684. LOG_ERR("Invalid channel type %d", out_param->channel_type);
  685. return -EINVAL;
  686. }
  687. if ((PHY_DEV_FEATURE(channel_num) != 2)
  688. && (PHY_DEV_FEATURE(channel_num) != 4)
  689. && (PHY_DEV_FEATURE(channel_num) != 8)) {
  690. LOG_ERR("Invalid channel num %d", PHY_DEV_FEATURE(channel_num));
  691. return -EINVAL;
  692. }
  693. #ifndef CONFIG_CFG_DRV
  694. {
  695. struct board_pinmux_info pinmux_info;
  696. board_get_i2stx0_pinmux_info(&pinmux_info);
  697. /* Config the i2stx pin state */
  698. acts_pinmux_setup_pins(pinmux_info.pins_config, pinmux_info.pins_num);
  699. }
  700. #endif
  701. acts_clock_peripheral_enable(cfg->clk_id);
  702. acts_clock_peripheral_enable(cfg->hclk_clk_id);
  703. if (PHY_DEV_FEATURE(srd_en))
  704. acts_clock_peripheral_enable(cfg->srd_clk_id);
  705. return 0;
  706. }
  707. /* @brief physical I2STX device enable */
  708. static int phy_i2stx_enable(struct device *dev, void *param)
  709. {
  710. const struct phy_i2stx_config_data *cfg = dev->config;
  711. aout_param_t *out_param = (aout_param_t *)param;
  712. i2stx_setting_t *i2stx_setting = out_param->i2stx_setting;
  713. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  714. struct phy_i2stx_drv_data *data = dev->data;
  715. int ret;
  716. bool link_dac = false, link_spdif = false;
  717. ret = phy_i2stx_prepare_enable(dev, out_param);
  718. if (ret) {
  719. LOG_ERR("Failed to prepare enable i2stx err=%d", ret);
  720. return ret;
  721. }
  722. if (out_param->channel_type & AUDIO_CHANNEL_DAC) {
  723. link_dac = true;
  724. data->link_with_dac = 1;
  725. data->mclksrc = CLK_SRCTX_DAC_256FS;
  726. } else if (out_param->channel_type & AUDIO_CHANNEL_SPDIFTX) {
  727. link_spdif = true;
  728. if ((AOUT_FIFO_DAC0 == out_param->outfifo_type)
  729. || (AOUT_FIFO_DAC1 == out_param->outfifo_type)) {
  730. data->mclksrc = CLK_SRCTX_DAC_256FS;
  731. /* I2STX use DAC FIFO shall set FIFO_SET to 1 */
  732. i2stx_reg->fifoctl |= I2ST0_FIFOCTL_FIFO_SEL;
  733. } else {
  734. data->mclksrc = CLK_SRCTX_I2STX;
  735. }
  736. } else {
  737. if ((AOUT_FIFO_DAC0 == out_param->outfifo_type)
  738. || (AOUT_FIFO_DAC1 == out_param->outfifo_type)) {
  739. data->mclksrc = CLK_SRCTX_DAC_256FS;
  740. data->fifo_use = out_param->outfifo_type;
  741. /* I2STX use DAC FIFO shall set FIFO_SET to 1 */
  742. i2stx_reg->fifoctl |= I2ST0_FIFOCTL_FIFO_SEL;
  743. } else {
  744. data->mclksrc = CLK_SRCTX_I2STX;
  745. }
  746. /* slave mode */
  747. if (PHY_DEV_FEATURE(mode)) {
  748. /* MCLK use external clock */
  749. if (!PHY_DEV_FEATURE(slave_internal_clk))
  750. data->mclksrc = CLK_SRCTX_I2STX_EXT;
  751. }
  752. }
  753. /* I2STX sample rate set */
  754. if (i2stx_sample_rate_set(dev, out_param->sample_rate,
  755. data->mclksrc, link_dac ? true : false)) {
  756. LOG_ERR("Failed to config sample rate %d",
  757. out_param->sample_rate);
  758. return -ESRCH;
  759. }
  760. /* Linkage with DAC will force the I2STX use the DAC FIFO */
  761. if ((!link_dac) && (AOUT_FIFO_I2STX0 == out_param->outfifo_type)) {
  762. if (is_i2stx_fifo_working(dev)) {
  763. LOG_ERR("I2STX FIFO now is using ...");
  764. return -EACCES;
  765. }
  766. i2stx_fifo_enable(dev, FIFO_SEL_DMA, (out_param->channel_width == CHANNEL_WIDTH_16BITS)
  767. ? DMA_WIDTH_16BITS : DMA_WIDTH_32BITS, true);
  768. data->fifo_use = AOUT_FIFO_I2STX0;
  769. }
  770. /* I2STX linkage with SPDIFTX */
  771. if (link_spdif)
  772. i2stx_reg->tx_ctl |= I2ST0_CTL_MULT_DEVICE;
  773. if (!link_dac) {
  774. i2stx_digital_enable(dev, out_param->channel_width, true);
  775. } else {
  776. /* linkage with DAC shall set FIFO_SET to 1 */
  777. i2stx_reg->fifoctl |= I2ST0_FIFOCTL_FIFO_SEL;
  778. i2stx_digital_enable(dev, out_param->channel_width, false);
  779. }
  780. if (PHY_DEV_FEATURE(srd_en)) {
  781. if ((!link_dac) && (PHY_DEV_FEATURE(mode))) {
  782. LOG_INF("I2STX SRD enable");
  783. i2stx_srd_cfg(dev, I2STX_SRD_TH_DEFAULT, I2S_SRD_2LRCLK, true, false);
  784. data->srd_callback = i2stx_setting->srd_callback;
  785. data->cb_data = i2stx_setting->cb_data;
  786. if (!PHY_DEV_FEATURE(bclk_width))
  787. data->srd_wl = SRDSTA_WL_64RATE;
  788. else
  789. data->srd_wl = SRDSTA_WL_32RATE;
  790. }
  791. }
  792. if (AOUT_FIFO_I2STX0 == data->fifo_use) {
  793. /* Clear FIFO ERROR */
  794. if (i2stx_reg->fifostat & I2ST0_FIFOSTA_FIFO_ER)
  795. i2stx_reg->fifostat |= I2ST0_FIFOSTA_FIFO_ER;
  796. }
  797. /* set flag of channel opened */
  798. data->channel_opened = 1;
  799. return 0;
  800. }
  801. /* @brief physical I2STX device disable */
  802. static int phy_i2stx_disable(struct device *dev, void *param)
  803. {
  804. const struct phy_i2stx_config_data *cfg = dev->config;
  805. struct phy_i2stx_drv_data *data = dev->data;
  806. if (data->fifo_use == AOUT_FIFO_I2STX0)
  807. i2stx_fifo_disable(dev);
  808. /* Don't disable I2STX until the user call iotcl #PHY_CMD_I2STX_DISABLE_DEVICE */
  809. if (!PHY_DEV_FEATURE(always_open) && !PHY_DEV_FEATURE(mode)) {
  810. i2stx_digital_disable(dev);
  811. acts_clock_peripheral_disable(cfg->clk_id);
  812. }
  813. if (PHY_DEV_FEATURE(srd_en))
  814. acts_clock_peripheral_disable(cfg->srd_clk_id);
  815. data->srd_callback = NULL;
  816. data->cb_data = NULL;
  817. if (!PHY_DEV_FEATURE(bclk_width))
  818. data->srd_wl = SRDSTA_WL_64RATE;
  819. else
  820. data->srd_wl = SRDSTA_WL_32RATE;
  821. data->fifo_use = AUDIO_FIFO_INVALID_TYPE;
  822. data->fifo_cnt = 0;
  823. data->link_with_dac = 0;
  824. data->channel_opened = 0;
  825. return 0;
  826. }
  827. static int phy_i2stx_ioctl(struct device *dev, uint32_t cmd, void *param)
  828. {
  829. const struct phy_i2stx_config_data *cfg = dev->config;
  830. struct phy_i2stx_drv_data *data = dev->data;
  831. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  832. int ret = 0;
  833. switch (cmd) {
  834. case PHY_CMD_DUMP_REGS:
  835. {
  836. i2stx_dump_register(dev);
  837. break;
  838. }
  839. case AOUT_CMD_GET_SAMPLERATE:
  840. {
  841. ret = i2stx_sample_rate_get(dev);
  842. if (ret < 0) {
  843. LOG_ERR("Failed to get I2STX sample rate err=%d", ret);
  844. return ret;
  845. }
  846. *(audio_sr_sel_e *)param = (audio_sr_sel_e)ret;
  847. ret = 0;
  848. break;
  849. }
  850. case AOUT_CMD_SET_SAMPLERATE:
  851. {
  852. audio_sr_sel_e val = *(audio_sr_sel_e *)param;
  853. ret = i2stx_sample_rate_set(dev, val, data->mclksrc,
  854. data->link_with_dac ? true : false);
  855. if (ret) {
  856. LOG_ERR("Failed to set I2STX sample rate err=%d", ret);
  857. return ret;
  858. }
  859. break;
  860. }
  861. case AOUT_CMD_GET_SAMPLE_CNT:
  862. {
  863. uint32_t val;
  864. val = i2stx_read_fifocount(dev);
  865. *(uint32_t *)param = val + data->fifo_cnt;
  866. LOG_DBG("I2STX FIFO counter: %d", *(uint32_t *)param);
  867. break;
  868. }
  869. case AOUT_CMD_RESET_SAMPLE_CNT:
  870. {
  871. data->fifo_cnt = 0;
  872. i2stx_fifocount_reset(dev);
  873. break;
  874. }
  875. case AOUT_CMD_ENABLE_SAMPLE_CNT:
  876. {
  877. i2stx_fifocount_enable(dev);
  878. break;
  879. }
  880. case AOUT_CMD_DISABLE_SAMPLE_CNT:
  881. {
  882. i2stx_fifocount_disable(dev);
  883. break;
  884. }
  885. case AOUT_CMD_GET_CHANNEL_STATUS:
  886. {
  887. uint8_t status = 0;
  888. if (check_i2stx_fifo_error(dev)) {
  889. status = AUDIO_CHANNEL_STATUS_ERROR;
  890. LOG_DBG("I2STX FIFO ERROR");
  891. }
  892. if (i2stx_fifo_status(dev) < (I2STX_FIFO_LEVEL - 1))
  893. status |= AUDIO_CHANNEL_STATUS_BUSY;
  894. *(uint8_t *)param = status;
  895. break;
  896. }
  897. case AOUT_CMD_GET_FIFO_LEN:
  898. {
  899. *(uint32_t *)param = I2STX_FIFO_LEVEL;
  900. break;
  901. }
  902. case AOUT_CMD_GET_FIFO_AVAILABLE_LEN:
  903. {
  904. *(uint32_t *)param = i2stx_fifo_status(dev);
  905. break;
  906. }
  907. case AOUT_CMD_GET_APS:
  908. {
  909. ret = i2stx_get_pll_aps(dev);
  910. if (ret < 0) {
  911. LOG_ERR("Failed to get audio pll APS err=%d", ret);
  912. return ret;
  913. }
  914. *(audio_aps_level_e *)param = (audio_aps_level_e)ret;
  915. ret = 0;
  916. break;
  917. }
  918. case AOUT_CMD_SET_APS:
  919. {
  920. audio_aps_level_e level = *(audio_aps_level_e *)param;
  921. ret = i2stx_set_pll_aps(dev, level);
  922. if (ret) {
  923. LOG_ERR("Failed to set audio pll APS err=%d", ret);
  924. return ret;
  925. }
  926. break;
  927. }
  928. case PHY_CMD_FIFO_GET:
  929. {
  930. aout_param_t *out_param = (aout_param_t *)param;
  931. if (!out_param)
  932. return -EINVAL;
  933. /* enable i2stx clock */
  934. acts_clock_peripheral_enable(cfg->clk_id);
  935. acts_clock_peripheral_enable(cfg->hclk_clk_id);
  936. if (is_i2stx_fifo_working(dev)) {
  937. LOG_ERR("I2STX FIFO is using");
  938. return -EBUSY;
  939. }
  940. /* SPDIFTX use I2STX FIFO shall set FIFO_SET to 1 */
  941. i2stx_reg->fifoctl |= I2ST0_FIFOCTL_FIFO_SEL;
  942. i2stx_fifo_enable(dev, FIFO_SEL_DMA,
  943. (out_param->channel_width == CHANNEL_WIDTH_16BITS)
  944. ? DMA_WIDTH_16BITS : DMA_WIDTH_32BITS, false);
  945. break;
  946. }
  947. case PHY_CMD_FIFO_PUT:
  948. {
  949. if (is_i2stx_fifo_working(dev))
  950. i2stx_fifo_disable(dev);
  951. data->fifo_cnt = 0;
  952. break;
  953. }
  954. case PHY_CMD_I2STX_IS_OPENED:
  955. {
  956. *(uint8_t *)param = data->channel_opened;
  957. break;
  958. }
  959. case PHY_CMD_I2STX_DISABLE_DEVICE:
  960. {
  961. i2stx_digital_disable(dev);
  962. acts_clock_peripheral_disable(cfg->clk_id);
  963. acts_clock_peripheral_disable(cfg->hclk_clk_id);
  964. acts_clock_peripheral_disable(cfg->srd_clk_id);
  965. break;
  966. }
  967. case PHY_CMD_I2STX_CLK_SET:
  968. {
  969. uint8_t sr = *(uint8_t *)param;
  970. struct board_pinmux_info pinmux_info;
  971. acts_clock_peripheral_enable(cfg->clk_id);
  972. board_get_i2stx0_pinmux_info(&pinmux_info);
  973. acts_pinmux_setup_pins(pinmux_info.pins_config, pinmux_info.pins_num);
  974. ret = i2stx_sample_rate_set(dev, sr, CLK_SRCTX_I2STX, false);
  975. break;
  976. }
  977. case PHY_CMD_GET_AOUT_DMA_INFO:
  978. {
  979. struct audio_out_dma_info *info = (struct audio_out_dma_info *)param;
  980. info->dma_info.dma_chan = cfg->dma_fifo0.dma_chan;
  981. info->dma_info.dma_dev_name = cfg->dma_fifo0.dma_dev_name;
  982. info->dma_info.dma_id = cfg->dma_fifo0.dma_id;
  983. break;
  984. }
  985. case PHY_CMD_I2STX_IS_MCLK_128FS:
  986. {
  987. if (PHY_DEV_FEATURE(bclk_width))
  988. *(uint8_t *)param = 1;
  989. else
  990. *(uint8_t *)param = 0;
  991. break;
  992. }
  993. case PHY_CMD_DAC_FIFO_VOLUME_SET:
  994. {
  995. uint8_t volume = *(uint8_t *)param;
  996. ret = i2stx_fifo_volume_set(dev, volume);
  997. break;
  998. }
  999. case PHY_CMD_DAC_FIFO_VOLUME_GET:
  1000. {
  1001. ret = i2stx_fifo_volume_get(dev);
  1002. if (ret < 0) {
  1003. LOG_ERR("Get I2STX FIFO volume error=%d", ret);
  1004. return ret;
  1005. }
  1006. *(uint8_t *)param = ret;
  1007. ret = 0;
  1008. break;
  1009. }
  1010. default:
  1011. LOG_ERR("Unsupport command %d", cmd);
  1012. return -ENOTSUP;
  1013. }
  1014. return ret;
  1015. }
  1016. const struct phy_audio_driver_api phy_i2stx_drv_api = {
  1017. .audio_enable = phy_i2stx_enable,
  1018. .audio_disable = phy_i2stx_disable,
  1019. .audio_ioctl = phy_i2stx_ioctl,
  1020. };
  1021. /* dump i2stx device tree infomation */
  1022. static void __i2stx_dt_dump_info(const struct phy_i2stx_config_data *cfg)
  1023. {
  1024. #if (PHY_DEV_SHOW_DT_INFO == 1)
  1025. LOG_INF("** I2STX BASIC INFO **");
  1026. LOG_INF(" BASE: %08x", cfg->reg_base);
  1027. LOG_INF(" CLK-ID: %08x", cfg->clk_id);
  1028. LOG_INF("SRDCLK-ID: %08x", cfg->srd_clk_id);
  1029. LOG_INF(" RST-ID: %08x", cfg->rst_id);
  1030. LOG_INF("DMA0-NAME: %s", cfg->dma_fifo0.dma_dev_name);
  1031. LOG_INF(" DMA0-ID: %08x", cfg->dma_fifo0.dma_id);
  1032. LOG_INF(" DMA0-CH: %08x", cfg->dma_fifo0.dma_chan);
  1033. LOG_INF("** I2STX FEATURES **");
  1034. LOG_INF(" SRD-EN: %d", PHY_DEV_FEATURE(srd_en));
  1035. LOG_INF(" MODE: %d", PHY_DEV_FEATURE(mode));
  1036. LOG_INF(" BCLK-WIDTH: %d", PHY_DEV_FEATURE(bclk_width));
  1037. LOG_INF(" CH-NUM: %d", PHY_DEV_FEATURE(channel_num));
  1038. LOG_INF("INTERNAL-CLK: %d", PHY_DEV_FEATURE(slave_internal_clk));
  1039. LOG_INF(" LRCLK-PROC: %d", PHY_DEV_FEATURE(lrclk_proc));
  1040. LOG_INF("MCLK-REVERSE: %d", PHY_DEV_FEATURE(mclk_reverse));
  1041. LOG_INF(" ALWAYS-OPEN: %d", PHY_DEV_FEATURE(always_open));
  1042. LOG_INF(" TDM-FORMAT: %d", PHY_DEV_FEATURE(tdm_format));
  1043. LOG_INF(" TDM-FRAME: %d", PHY_DEV_FEATURE(tdm_frame));
  1044. LOG_INF(" TDM-FRAME: %d", PHY_DEV_FEATURE(txd_delay));
  1045. #endif
  1046. }
  1047. static void phy_i2stx_isr(const void *arg)
  1048. {
  1049. struct device *dev = (struct device *)arg;
  1050. struct acts_audio_i2stx *i2stx_reg = get_i2stx_reg_base(dev);
  1051. struct phy_i2stx_drv_data *data = dev->data;
  1052. LOG_DBG("fifocnt 0x%x srdstat 0x%x", i2stx_reg->fifocnt, i2stx_reg->srdstat);
  1053. if (i2stx_reg->fifocnt & I2ST0_FIFO_CNT_IP) {
  1054. data->fifo_cnt += (AOUT_FIFO_CNT_MAX + 1);
  1055. /* Here we need to wait 100us for the synchronization of audio clock fields */
  1056. k_busy_wait(100);
  1057. i2stx_reg->fifocnt |= I2ST0_FIFO_CNT_IP;
  1058. }
  1059. /* Sample rate detection timeout irq pending */
  1060. if (i2stx_reg->srdstat & I2ST0_SRDSTA_TO_PD) {
  1061. i2stx_reg->srdstat |= I2ST0_SRDSTA_TO_PD;
  1062. if (data->srd_callback)
  1063. data->srd_callback(data->cb_data, I2STX_SRD_TIMEOUT, NULL);
  1064. }
  1065. /* Sample rate changed detection irq pending */
  1066. if (i2stx_reg->srdstat & I2ST0_SRDSTA_SRC_PD) {
  1067. i2stx_reg->srdstat |= I2ST0_SRDSTA_SRC_PD;
  1068. i2stx_srd_fs_change(dev);
  1069. }
  1070. /* Channel width change irq pending */
  1071. if (i2stx_reg->srdstat & I2ST0_SRDSTA_CHW_PD) {
  1072. i2stx_reg->srdstat |= I2ST0_SRDSTA_CHW_PD;
  1073. i2stx_srd_wl_change(dev);
  1074. }
  1075. }
  1076. #ifdef CONFIG_CFG_DRV
  1077. /* @brief initialize I2STX external configuration */
  1078. static int phy_i2stx_config_init(const struct device *dev)
  1079. {
  1080. struct phy_i2stx_drv_data *data = dev->data;
  1081. struct acts_pin_config i2stx_pins_state[4] = {0};
  1082. int ret;
  1083. ret = cfg_get_by_key(ITEM_AUDIO_I2STX_SELECT_GPIO,
  1084. &data->external_config.I2STX_Select_GPIO, sizeof(data->external_config.I2STX_Select_GPIO));
  1085. if (ret) {
  1086. LOG_INF("** I2STX PINMUX **");
  1087. LOG_INF("I2S_MCLK:%d", data->external_config.I2STX_Select_GPIO.I2S_MCLK);
  1088. LOG_INF("I2S_LRCLK:%d", data->external_config.I2STX_Select_GPIO.I2S_LRCLK);
  1089. LOG_INF("I2S_BCLK:%d", data->external_config.I2STX_Select_GPIO.I2S_BCLK);
  1090. LOG_INF("I2S_DOUT:%d", data->external_config.I2STX_Select_GPIO.I2S_DOUT);
  1091. }
  1092. if ((data->external_config.I2STX_Select_GPIO.I2S_MCLK != GPIO_NONE)
  1093. && (data->external_config.I2STX_Select_GPIO.I2S_LRCLK != GPIO_NONE)
  1094. && (data->external_config.I2STX_Select_GPIO.I2S_BCLK != GPIO_NONE)
  1095. && (data->external_config.I2STX_Select_GPIO.I2S_DOUT != GPIO_NONE)) {
  1096. i2stx_pins_state[0].pin_num = data->external_config.I2STX_Select_GPIO.I2S_MCLK;
  1097. i2stx_pins_state[0].mode = 12;
  1098. i2stx_pins_state[1].pin_num = data->external_config.I2STX_Select_GPIO.I2S_LRCLK;
  1099. i2stx_pins_state[1].mode = 12;
  1100. i2stx_pins_state[2].pin_num = data->external_config.I2STX_Select_GPIO.I2S_BCLK;
  1101. i2stx_pins_state[2].mode = 12;
  1102. i2stx_pins_state[3].pin_num = data->external_config.I2STX_Select_GPIO.I2S_DOUT;
  1103. i2stx_pins_state[3].mode = 12;
  1104. acts_pinmux_setup_pins(i2stx_pins_state, ARRAY_SIZE(i2stx_pins_state));
  1105. }
  1106. return 0;
  1107. }
  1108. #endif
  1109. static int phy_i2stx_init(const struct device *dev)
  1110. {
  1111. const struct phy_i2stx_config_data *cfg = dev->config;
  1112. struct phy_i2stx_drv_data *data = dev->data;
  1113. /* clear driver data */
  1114. memset(data, 0, sizeof(struct phy_i2stx_drv_data));
  1115. __i2stx_dt_dump_info(cfg);
  1116. #ifdef CONFIG_CFG_DRV
  1117. phy_i2stx_config_init(dev);
  1118. #endif
  1119. /* reset I2STX controller */
  1120. acts_reset_peripheral(cfg->rst_id);
  1121. if (cfg->irq_config)
  1122. cfg->irq_config();
  1123. data->fifo_use = AUDIO_FIFO_INVALID_TYPE;
  1124. printk("I2STX init successfully\n");
  1125. return 0;
  1126. }
  1127. static void phy_i2stx_irq_config(void);
  1128. /* physical i2stx driver data */
  1129. static struct phy_i2stx_drv_data phy_i2stx_drv_data0;
  1130. /* physical i2stx config data */
  1131. static const struct phy_i2stx_config_data phy_i2stx_config_data0 = {
  1132. .reg_base = AUDIO_I2STX0_REG_BASE,
  1133. .clk_id = CLOCK_ID_I2STX,
  1134. .srd_clk_id = CLOCK_ID_I2SSRDCLK,
  1135. .hclk_clk_id = CLOCK_ID_I2SHCLKEN,
  1136. .rst_id = RESET_ID_I2STX,
  1137. AUDIO_DMA_FIFO_DEF(I2STX, 0),
  1138. .irq_config = phy_i2stx_irq_config,
  1139. PHY_DEV_FEATURE_DEF(format) = CONFIG_AUDIO_I2STX_0_FORMAT,
  1140. PHY_DEV_FEATURE_DEF(srd_en) = CONFIG_AUDIO_I2STX_0_SRD_EN,
  1141. PHY_DEV_FEATURE_DEF(mode) = CONFIG_AUDIO_I2STX_0_MODE,
  1142. PHY_DEV_FEATURE_DEF(bclk_width) = CONFIG_AUDIO_I2STX_0_BCLK_WIDTH,
  1143. PHY_DEV_FEATURE_DEF(channel_num) = CONFIG_AUDIO_I2STX_0_CHANNEL_NUM,
  1144. PHY_DEV_FEATURE_DEF(slave_internal_clk) = CONFIG_AUDIO_I2STX_0_SLAVE_INTERNAL_CLK,
  1145. PHY_DEV_FEATURE_DEF(lrclk_proc) = CONFIG_AUDIO_I2STX_0_LRCLK_PROC,
  1146. PHY_DEV_FEATURE_DEF(mclk_reverse) = CONFIG_AUDIO_I2STX_0_MCLK_REVERSE,
  1147. PHY_DEV_FEATURE_DEF(always_open) = CONFIG_AUDIO_I2STX_0_ALWAYS_OPEN,
  1148. PHY_DEV_FEATURE_DEF(tdm_format) = CONFIG_AUDIO_I2STX_0_TDM_FORMAT,
  1149. PHY_DEV_FEATURE_DEF(tdm_frame) = CONFIG_AUDIO_I2STX_0_TDM_FRAME,
  1150. PHY_DEV_FEATURE_DEF(txd_delay) = CONFIG_AUDIO_I2STX_0_TX_DELAY,
  1151. };
  1152. #if IS_ENABLED(CONFIG_AUDIO_I2STX_0)
  1153. DEVICE_DEFINE(i2stx0, CONFIG_AUDIO_I2STX_0_NAME, phy_i2stx_init, NULL,
  1154. &phy_i2stx_drv_data0, &phy_i2stx_config_data0,
  1155. POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS, &phy_i2stx_drv_api);
  1156. #endif
  1157. /*
  1158. * @brief Enable I2STX IRQ
  1159. * @note I2STX IRQ source as shown below:
  1160. * - I2STX FIFO Half Empty IRQ
  1161. * - I2STX FIFO CNT IRQ
  1162. * - I2STX SRDTO IRQ
  1163. * - I2STX SRDSR IRQ
  1164. * - I2STX SRDCHW IRQ
  1165. */
  1166. static void phy_i2stx_irq_config(void)
  1167. {
  1168. IRQ_CONNECT(IRQ_ID_I2S0, CONFIG_AUDIO_I2STX_0_IRQ_PRI,
  1169. phy_i2stx_isr,
  1170. DEVICE_GET(i2stx0), 0);
  1171. irq_enable(IRQ_ID_I2S0);
  1172. }