drv_aic_i2s.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. /*
  2. * File : drv_i2s.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2015-11-19 Urey the first version
  23. */
  24. #include <rthw.h>
  25. #include <rtthread.h>
  26. #include <rtdevice.h>
  27. #include <drivers/audio.h>
  28. #include "dma.h"
  29. #ifdef RT_USING_FINSH
  30. #include <finsh.h>
  31. #endif
  32. #include "board.h"
  33. #include "drv_clock.h"
  34. #include "drv_dma.h"
  35. #include "drv_gpio.h"
  36. #include "drv_aic.h"
  37. #include "drv_aic_i2s.h"
  38. #define AIC_DEBUG 0
  39. #if AIC_DEBUG
  40. #define AIC_DBG(...) rt_kprintf("[AIC]"),rt_kprintf(__VA_ARGS__)
  41. #else
  42. #define AIC_DBG(...)
  43. #endif
  44. static struct jz_aic _g_jz_aic;
  45. int aic_set_rate(struct jz_aic *aic, uint32_t freq)
  46. {
  47. int ret;
  48. // clk_disable(aic->clk);
  49. if (aic->clk_rate != freq)
  50. {
  51. ret = clk_set_rate(aic->clk, freq);
  52. if (!ret)
  53. aic->clk_rate = clk_get_rate(aic->clk);
  54. }
  55. // clk_enable(aic->clk);
  56. AIC_DBG("aic clock = %d\n",clk_get_rate(aic->clk));
  57. return aic->clk_rate;
  58. }
  59. static void aic_irq_handler(int vector, void *param)
  60. {
  61. struct jz_aic *aic = (struct jz_aic *)param;
  62. aic->mask = __aic_get_irq_enmask(aic);
  63. if (aic->mask && (aic->mask & __aic_get_irq_flag(aic)))
  64. {
  65. /*Disable all aic interrupt*/
  66. __aic_set_irq_enmask(aic, 0);
  67. if ((aic->mask & 0x8) && __aic_test_ror(aic))
  68. {
  69. aic->ror++;
  70. AIC_DBG("recieve fifo [overrun] interrupt time [%d]\n",
  71. aic->ror);
  72. }
  73. if ((aic->mask & 0x4) && __aic_test_tur(aic))
  74. {
  75. aic->tur++;
  76. AIC_DBG("transmit fifo [underrun] interrupt time [%d]\n",
  77. aic->tur);
  78. }
  79. if ((aic->mask & 0x2) && __aic_test_rfs(aic))
  80. {
  81. AIC_DBG("[recieve] fifo at or above threshold interrupt time\n");
  82. }
  83. if ((aic->mask & 0x1) && __aic_test_tfs(aic))
  84. {
  85. AIC_DBG("[transmit] fifo at or blow threshold interrupt time\n");
  86. }
  87. /*sleep, avoid frequently interrupt*/
  88. __aic_clear_all_irq_flag(aic);
  89. __aic_set_irq_enmask(aic, aic->mask);
  90. }
  91. }
  92. struct jz_aic* _aic_init(void)
  93. {
  94. struct jz_aic *aic = &_g_jz_aic;
  95. struct rt_device *device;
  96. aic->base = AIC_BASE;
  97. aic->clk_gate = clk_get("aic");
  98. aic->clk = clk_get("cgu_i2s");
  99. if((aic->clk_gate == RT_NULL) || (aic->clk == RT_NULL))
  100. {
  101. AIC_DBG("aic or i2s clk error\n");
  102. goto aic_init_error;
  103. }
  104. /* set system clock */
  105. clk_set_rate(aic->clk, 24000000);
  106. aic->clk_rate = 24000000;
  107. clk_enable(aic->clk_gate);
  108. clk_enable(aic->clk);
  109. aic->irqno = IRQ_AIC0;
  110. aic->irqflags = 0;
  111. rt_hw_interrupt_install(IRQ_AIC0,aic_irq_handler,aic,"irq_aic");
  112. rt_hw_interrupt_umask(IRQ_AIC0);
  113. return aic;
  114. aic_init_error:
  115. clk_put(aic->clk);
  116. clk_put(aic->clk_gate);
  117. return RT_NULL;
  118. }
  119. #define I2S_DEBUG 0
  120. #if I2S_DEBUG
  121. #define I2S_DBG(...) rt_kprintf("[I2S]"),rt_kprintf(__VA_ARGS__)
  122. #else
  123. #define I2S_DBG(...)
  124. #endif
  125. #define I2S_TFIFO_DEPTH 64
  126. #define I2S_RFIFO_DEPTH 32
  127. #define I2S_OSS_FMT 16
  128. #define I2S_ISS_FMT 16
  129. #define I2S_PALY_CHANEL 2
  130. struct jz_i2s _g_jz_i2s =
  131. {
  132. .aic = 0,
  133. .i2s_init = 0,
  134. .i2s_mode = 0,
  135. .tx_dr_base = ((AIC_BASE + AICDR) & 0x1FFFFFFF),
  136. .channels = 2,
  137. .fmt_width = 16,
  138. .tx_dmac = RT_NULL,
  139. .rx_dmac = RT_NULL,
  140. };
  141. #define I2S_DMA_TX_CHAN 2
  142. #define I2S_DMA_RX_CHAN 3
  143. static void aic_i2s_trans_complete(struct rt_dma_channel *dmac, struct dma_message *msg);
  144. static void dump_registers(struct jz_aic *aic)
  145. {
  146. rt_kprintf("AIC_FR 0x%08x : 0x%08x\n", (aic->base+AICFR), jz_aic_read_reg(aic, AICFR));
  147. rt_kprintf("AIC_CR 0x%08x : 0x%08x\n", (aic->base+AICCR), jz_aic_read_reg(aic, AICCR));
  148. rt_kprintf("AIC_I2SCR 0x%08x : 0x%08x\n", (aic->base+I2SCR), jz_aic_read_reg(aic, I2SCR));
  149. rt_kprintf("AIC_SR 0x%08x : 0x%08x\n", (aic->base+AICSR), jz_aic_read_reg(aic, AICSR));
  150. rt_kprintf("AIC_I2SSR 0x%08x : 0x%08x\n", (aic->base+I2SSR), jz_aic_read_reg(aic, I2SSR));
  151. rt_kprintf("AIC_I2SDIV 0x%08x : 0x%08x\n", (aic->base+I2SDIV), jz_aic_read_reg(aic, I2SDIV));
  152. rt_kprintf("AIC_DR 0x%08x : 0x%08x\n", (aic->base+AICDR), jz_aic_read_reg(aic, AICDR));
  153. rt_kprintf("AIC_I2SCDR\t 0x%08x\n",*(volatile unsigned int*)0xb0000060);
  154. rt_kprintf("AIC_I2SCDR1\t 0x%08x\n",*(volatile unsigned int*)0xb0000070);
  155. rt_kprintf("AICSR\t 0x%08x\n",*(volatile unsigned int*)0xb0020014);
  156. return;
  157. }
  158. int dump_aic_i2s(void)
  159. {
  160. dump_registers(_g_jz_i2s.aic);
  161. return 0;
  162. }
  163. MSH_CMD_EXPORT(dump_aic_i2s,dump i2s registers...);
  164. #if 0
  165. int i2scdr_extclk(void)
  166. {
  167. rt_uint32_t regValue;
  168. regValue = readl(0xb0000060);
  169. regValue &= ~(0x01 << 30);
  170. writel(regValue,0xb0000060);
  171. rt_kprintf("AIC_I2SCDR\t 0x%08x\n",*(volatile unsigned int*)0xb0000060);
  172. }
  173. MSH_CMD_EXPORT(i2scdr_extclk,set i2s cdr ext clk...);
  174. int i2scdr_pllclk(void)
  175. {
  176. rt_uint32_t regValue;
  177. regValue = readl(0xb0000060);
  178. regValue |= (0x01 << 30);
  179. writel(regValue,0xb0000060);
  180. rt_kprintf("AIC_I2SCDR\t 0x%08x\n",*(volatile unsigned int*)0xb0000060);
  181. }
  182. MSH_CMD_EXPORT(i2scdr_pllclk,set i2s cdr pll clk...);
  183. #endif
  184. static void aic_i2s_start_substream(struct jz_i2s *i2s,int stream)
  185. {
  186. struct jz_aic *aic = i2s->aic;
  187. if(stream == AUDIO_STREAM_REPLAY)
  188. {
  189. int i = 4;
  190. I2S_DBG("codec fifo level0 %x\n", jz_aic_read_reg(aic, AICSR));
  191. for (i= 0; i < I2S_TFIFO_DEPTH ; i++)
  192. {
  193. __aic_write_txfifo(aic, 0x0);
  194. __aic_write_txfifo(aic, 0x0);
  195. }
  196. __aic_clear_tur(aic);
  197. I2S_DBG("codec fifo level1 %x\n", jz_aic_read_reg(aic, AICSR));
  198. __i2s_enable_replay(aic);
  199. while (!__aic_test_tur(aic)) ;
  200. __i2s_enable_transmit_dma(aic);
  201. __aic_clear_tur(aic);
  202. #if I2S_DEBUG
  203. __aic_en_tur_int(aic);
  204. #endif
  205. }
  206. else
  207. {
  208. __aic_flush_rxfifo(aic);
  209. rt_thread_delay(1);
  210. __i2s_enable_record(aic);
  211. __i2s_enable_receive_dma(aic);
  212. #if I2S_DEBUG
  213. __aic_en_ror_int(aic);
  214. #endif
  215. }
  216. I2S_DBG("strtup sub stream ok!\n");
  217. }
  218. static void aic_i2s_stop_substream(struct jz_i2s *i2s,int stream)
  219. {
  220. struct jz_aic *aic = i2s->aic;
  221. if(stream == AUDIO_STREAM_REPLAY)
  222. {
  223. #if I2S_DEBUG
  224. __aic_dis_tur_int(aic);
  225. #endif
  226. if (__i2s_transmit_dma_is_enable(aic))
  227. {
  228. //wait all dma queue is complete
  229. while(i2s->tx_dmac->get_index != i2s->tx_dmac->put_index)
  230. rt_thread_delay(1);
  231. __i2s_disable_transmit_dma(aic);
  232. __aic_clear_tur(aic);
  233. /*hrtime mode: stop will be happen in any where, make sure there is
  234. * no data transfer on ahb bus before stop dma
  235. */
  236. while(!__aic_test_tur(aic));
  237. }
  238. __i2s_disable_replay(aic);
  239. __aic_clear_tur(aic);
  240. }
  241. else
  242. {
  243. // if (jz_i2s_debug) __aic_dis_ror_int(aic);
  244. if (__i2s_receive_dma_is_enable(aic))
  245. {
  246. __i2s_disable_receive_dma(aic);
  247. __aic_clear_ror(aic);
  248. while(!__aic_test_ror(aic));
  249. }
  250. __i2s_disable_record(aic);
  251. __aic_clear_ror(aic);
  252. }
  253. }
  254. int aic_i2s_set_clkdiv(struct jz_i2s *i2s,int div_id, int div)
  255. {
  256. struct jz_aic *aic = i2s->aic;
  257. I2S_DBG("enter %s div_id %d div %d\n", __func__, div_id , div);
  258. /*BIT CLK fix 64FS*/
  259. /*SYS_CLK is 256, 384, 512, 768*/
  260. if (div != 256 && div != 384 && div != 512 && div != 768)
  261. return -RT_EIO;
  262. __i2s_set_dv(aic, (div/64) - 1);
  263. __i2s_set_idv(aic, (div/64) - 1);
  264. return RT_EOK;
  265. }
  266. /*
  267. * stream = CODEC_STREAM_PLAYBACK or CODEC_STREAM_CAPTURE
  268. */
  269. int aic_i2s_startup(struct jz_i2s *i2s,int stream)
  270. {
  271. struct jz_aic *aic = i2s->aic;
  272. if(!i2s->i2s_mode)
  273. {
  274. I2S_DBG("start set AIC register....\n");
  275. __aic_disable(aic);
  276. __aic_select_i2s(aic);
  277. __i2s_select_i2s_fmt(aic);
  278. #ifndef CODEC_AS_MASTER
  279. __i2s_bclk_output(aic);
  280. __i2s_sync_output(aic);
  281. #else
  282. __i2s_bclk_input(aic);
  283. __i2s_sync_input(aic);
  284. #endif
  285. aic_i2s_set_sysclk(i2s,CODEC_DEF_RATE);
  286. __i2s_play_lastsample(aic);
  287. __i2s_set_transmit_trigger(aic, I2S_TFIFO_DEPTH/4);
  288. __i2s_set_receive_trigger(aic, (I2S_RFIFO_DEPTH/4 - 1));
  289. __aic_enable(aic);
  290. }
  291. /* Set playback or record mode */
  292. if(stream == AUDIO_STREAM_REPLAY)
  293. {
  294. __i2s_send_rfirst(aic);
  295. __i2s_disable_transmit_dma(aic);
  296. __i2s_disable_replay(aic);
  297. __aic_clear_tur(aic);
  298. i2s->i2s_mode |= I2S_WRITE;
  299. }
  300. else
  301. {
  302. __i2s_disable_receive_dma(aic);
  303. __i2s_disable_record(aic);
  304. __aic_clear_ror(aic);
  305. i2s->i2s_mode |= I2S_READ;
  306. }
  307. return 0;
  308. }
  309. int aic_i2s_trigger(struct jz_i2s* i2s,int cmd,int stream)
  310. {
  311. switch (cmd)
  312. {
  313. case I2S_TRIGGER_START:
  314. case I2S_TRIGGER_RESUME:
  315. case I2S_TRIGGER_PAUSE_RELEASE:
  316. aic_i2s_start_substream(i2s,stream);
  317. break;
  318. case I2S_TRIGGER_STOP:
  319. case I2S_TRIGGER_SUSPEND:
  320. case I2S_TRIGGER_PAUSE_PUSH:
  321. default:
  322. aic_i2s_stop_substream(i2s,stream);
  323. break;
  324. }
  325. return 0;
  326. }
  327. int aic_i2s_hw_params(struct jz_i2s* i2s,int stream)
  328. {
  329. struct jz_aic *aic = i2s->aic;
  330. struct dma_config config;
  331. int trigger;
  332. int bus_width;
  333. I2S_DBG("upgrade hw params...\n");
  334. if(stream == AUDIO_STREAM_REPLAY)
  335. {
  336. /* channel */
  337. __i2s_channel(aic, i2s->channels);
  338. /* format */
  339. if(i2s->fmt_width == 8)
  340. bus_width = RT_DMA_BUSWIDTH_1_BYTE;
  341. else if(i2s->fmt_width == 16)
  342. bus_width = RT_DMA_BUSWIDTH_2_BYTES;
  343. else
  344. bus_width = RT_DMA_BUSWIDTH_4_BYTES;
  345. i2s->tx_dmac = rt_dma_get_channel(I2S_DMA_TX_CHAN);
  346. RT_ASSERT(i2s->tx_dmac != RT_NULL);
  347. if(i2s->tx_dmac != RT_NULL)
  348. {
  349. config.direction = RT_DMA_MEM_TO_DEV;
  350. config.src_addr_width = bus_width;
  351. config.src_maxburst = (64 * 1024);
  352. config.dst_addr_width = bus_width;
  353. config.dst_maxburst = (I2S_TFIFO_DEPTH * bus_width)/2;
  354. rt_dma_configture(i2s->tx_dmac,&config);
  355. i2s->tx_dmac->start = RT_NULL;
  356. i2s->tx_dmac->complete = aic_i2s_trans_complete;
  357. }
  358. __i2s_set_oss(aic, i2s->fmt_width);
  359. __i2s_set_transmit_trigger(aic, (I2S_TFIFO_DEPTH / 4));
  360. I2S_DBG("TX_DMAC config ok!\n");
  361. }
  362. else
  363. {
  364. /* format */
  365. if(i2s->fmt_width == 8)
  366. bus_width = RT_DMA_BUSWIDTH_1_BYTE;
  367. else if(i2s->fmt_width == 16)
  368. bus_width = RT_DMA_BUSWIDTH_2_BYTES;
  369. else
  370. bus_width = RT_DMA_BUSWIDTH_4_BYTES;
  371. i2s->rx_dmac = rt_dma_get_channel(I2S_DMA_RX_CHAN);
  372. if(i2s->rx_dmac != RT_NULL)
  373. {
  374. config.direction = RT_DMA_DEV_TO_MEM;
  375. config.src_addr_width = bus_width;
  376. config.src_maxburst = (I2S_RFIFO_DEPTH * bus_width)/2;
  377. config.dst_addr_width = bus_width;
  378. config.dst_maxburst = (64 * 1024);
  379. rt_dma_configture(i2s->rx_dmac,&config);
  380. i2s->rx_dmac->start = RT_NULL;
  381. i2s->rx_dmac->complete = aic_i2s_trans_complete;
  382. I2S_DBG("RX DMA config ok \n");
  383. }
  384. __i2s_set_iss(aic, i2s->fmt_width);
  385. __i2s_set_receive_trigger(aic, (I2S_RFIFO_DEPTH/4 - 1));
  386. }
  387. return 0;
  388. }
  389. void aic_i2s_shutdown(struct jz_i2s *i2s,int stream)
  390. {
  391. struct jz_aic *aic = i2s->aic;
  392. aic_i2s_stop_substream(i2s,stream);
  393. if(stream == AUDIO_STREAM_REPLAY)
  394. i2s->i2s_mode &= ~I2S_WRITE;
  395. else
  396. i2s->i2s_mode &= ~I2S_READ;
  397. if(!i2s->i2s_mode)
  398. __aic_disable(aic);
  399. }
  400. int aic_i2s_set_sysclk(struct jz_i2s *i2s,uint32_t freq)
  401. {
  402. struct jz_aic *aic = i2s->aic;
  403. #ifdef RT_USING_ICODEC
  404. __aic_select_internal_codec(aic);
  405. #else
  406. __aic_select_external_codec(aic);
  407. #endif
  408. __i2s_stop_bitclk(aic);
  409. aic_set_rate(aic, freq);
  410. __i2s_start_bitclk(aic);
  411. #ifdef CFG_AIC_SOC_CLKOUT
  412. /* Master clk output */
  413. __i2s_select_sysclk_output(aic);
  414. __i2s_enable_sysclk_output(aic);
  415. #else
  416. /* Master clk input */
  417. __i2s_select_sysclk_input(aic);
  418. __i2s_disable_sysclk_output(aic);
  419. #endif
  420. return 0;
  421. }
  422. static void aic_i2s_trans_complete(struct rt_dma_channel *dmac, struct dma_message *msg)
  423. {
  424. I2S_DBG("TAG,%d,%s\n",__LINE__,__func__);
  425. if(msg->complete_cb)
  426. {
  427. if(msg->t_mode == JZDMA_REQ_I2S0_TX)
  428. msg->complete_cb(msg->complete_arg,msg->src_addr);
  429. else
  430. msg->complete_cb(msg->complete_arg,msg->dst_addr);
  431. }
  432. }
  433. rt_size_t aic_i2s_send(struct jz_i2s *i2s, const void* buffer, rt_size_t size,void (*tx_callback)(void *,void *), void *tx_arg)
  434. {
  435. struct dma_message message;
  436. I2S_DBG("TAG,%d,%s\n",__LINE__,__func__);
  437. message.src_addr = (uint8_t *) (buffer);
  438. message.src_option = RT_DMA_ADDR_INC;
  439. message.dst_addr = (uint8_t *) (AIC_BASE + AICDR);
  440. message.dst_option = RT_DMA_ADDR_FIX;
  441. message.t_size = size;
  442. message.t_mode = JZDMA_REQ_I2S0_TX;
  443. message.complete_cb = (void *)tx_callback;
  444. message.complete_arg= tx_arg;
  445. I2S_DBG("i2s trans length = %d\n",size);
  446. if (rt_dma_trans_message(i2s->tx_dmac, &message) == RT_EOK)
  447. return size;
  448. return 0;
  449. }
  450. rt_size_t aic_i2s_recv(struct jz_i2s *i2s, void* buffer, rt_size_t size,void (*rx_callback)(void *,void *), void *rx_arg)
  451. {
  452. struct dma_message message;
  453. message.src_addr = (uint8_t *) (AIC_BASE + AICDR);
  454. message.src_option = RT_DMA_ADDR_FIX;
  455. message.dst_addr = (uint8_t *) (buffer);
  456. message.dst_option = RT_DMA_ADDR_INC;
  457. message.t_size = size;
  458. message.t_mode = JZDMA_REQ_I2S0_RX;
  459. message.complete_cb = (void *)rx_callback;
  460. message.complete_arg= rx_arg;
  461. if(rt_dma_trans_message(i2s->rx_dmac,&message) == RT_EOK)
  462. return size;
  463. return 0;
  464. }
  465. struct jz_i2s *rt_hw_aic_i2s_init(void)
  466. {
  467. struct jz_aic *aic;
  468. struct jz_i2s *i2s = &_g_jz_i2s;
  469. #ifndef RT_USING_ICODEC
  470. #ifdef CFG_AIC_SOC_CLKOUT
  471. gpio_set_func(GPIO_PORT_B, GPIO_Pin_0, GPIO_FUNC_1); // I2S_MCLK
  472. #endif
  473. gpio_set_func(GPIO_PORT_B, GPIO_Pin_1, GPIO_FUNC_1); // I2S_BCLK
  474. gpio_set_func(GPIO_PORT_B, GPIO_Pin_2, GPIO_FUNC_1); // I2S_LRCLK
  475. gpio_set_func(GPIO_PORT_B, GPIO_Pin_3, GPIO_FUNC_1); // I2S_DI
  476. gpio_set_func(GPIO_PORT_B, GPIO_Pin_4, GPIO_FUNC_1); // I2S_DO
  477. #endif
  478. I2S_DBG("TAG,%d,%s\n",__LINE__,__func__);
  479. aic = _aic_init();
  480. if(aic == RT_NULL)
  481. return RT_NULL;
  482. i2s->aic = aic;
  483. i2s->i2s_mode = 0;
  484. I2S_DBG("TAG,%d,%s\n",__LINE__,__func__);
  485. /* now ,we just support I2S playback */
  486. aic_i2s_startup(i2s,AUDIO_STREAM_REPLAY);
  487. aic_i2s_hw_params(i2s,AUDIO_STREAM_REPLAY);
  488. return i2s;
  489. }