s3c2416-i2s.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. /*
  2. * s3c-i2s.c -- ALSA Soc Audio Layer
  3. *
  4. * (c) 2006 Wolfson Microelectronics PLC.
  5. * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
  6. *
  7. * (c) 2004-2005 Simtec Electronics
  8. * http://armlinux.simtec.co.uk/
  9. * Ben Dooks <ben@simtec.co.uk>
  10. * Ryu Euiyoul <ryu.real@gmail.com>
  11. *
  12. * This program is free software; you can redistribute it and/or modify it
  13. * under the terms of the GNU General Public License as published by the
  14. * Free Software Foundation; either version 2 of the License, or (at your
  15. * option) any later version.
  16. *
  17. *
  18. * Revision history
  19. * 11th Dec 2006 Merged with Simtec driver
  20. * 10th Nov 2006 Initial version.
  21. */
  22. #include <linux/init.h>
  23. #include <linux/module.h>
  24. #include <linux/device.h>
  25. #include <linux/delay.h>
  26. #include <linux/clk.h>
  27. #include <sound/driver.h>
  28. #include <sound/core.h>
  29. #include <sound/pcm.h>
  30. #include <sound/pcm_params.h>
  31. #include <sound/initval.h>
  32. #include <sound/soc.h>
  33. #include <asm/hardware.h>
  34. #include <asm/io.h>
  35. #include <asm/dma.h>
  36. #include <asm/arch/regs-iis.h>
  37. #include <asm/arch/regs-gpio.h>
  38. #include <asm/arch/regs-gpioj.h>
  39. #include <asm/arch/audio.h>
  40. #include <asm/arch/dma.h>
  41. #include <asm/arch/regs-s3c2450-clock.h>
  42. #include "s3c-pcm.h"
  43. #include "s3c-i2s.h"
  44. #ifdef CONFIG_SND_DEBUG
  45. #define s3cdbg(x...) printk(x)
  46. #else
  47. #define s3cdbg(x...)
  48. #endif
  49. /* used to disable sysclk if external crystal is used */
  50. static int extclk = 0;
  51. module_param(extclk, int, 0);
  52. MODULE_PARM_DESC(extclk, "set to 1 to disable s3c24XX i2s sysclk");
  53. static struct s3c2410_dma_client s3c24xx_dma_client_out = {
  54. .name = "I2S PCM Stereo out"
  55. };
  56. static struct s3c2410_dma_client s3c24xx_dma_client_in = {
  57. .name = "I2S PCM Stereo in"
  58. };
  59. static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_out = {
  60. .client = &s3c24xx_dma_client_out,
  61. .channel = DMACH_I2S_OUT,
  62. .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO,
  63. //HIKO DEBUG: I2S issue
  64. // .dma_size = 2,
  65. .dma_size = 4,
  66. // .dma_size = 1,
  67. };
  68. static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_in = {
  69. .client = &s3c24xx_dma_client_in,
  70. .channel = DMACH_I2S_IN,
  71. .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFORX,
  72. //HIKO DEBUG: I2S issue
  73. // .dma_size = 2,
  74. .dma_size = 4,
  75. // .dma_size = 1,
  76. };
  77. struct s3c24xx_i2s_info {
  78. void __iomem *regs;
  79. struct clk *iis_clk;
  80. int master;
  81. };
  82. static struct s3c24xx_i2s_info s3c24xx_i2s;
  83. static void s3c24xx_snd_txctrl(int on)
  84. {
  85. u32 iiscon;
  86. s3cdbg("Entered %s : on = %d \n", __FUNCTION__, on);
  87. iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
  88. if (on) {
  89. iiscon |= S3C_IIS0CON_I2SACTIVE;
  90. writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
  91. } else {
  92. /* note, we have to disable the FIFOs otherwise bad things
  93. * seem to happen when the DMA stops. According to the
  94. * Samsung supplied kernel, this should allow the DMA
  95. * engine and FIFOs to reset. If this isn't allowed, the
  96. * DMA engine will simply freeze randomly.
  97. */
  98. iiscon &= ~S3C_IIS0CON_I2SACTIVE;
  99. writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
  100. }
  101. }
  102. static void s3c24xx_snd_rxctrl(int on)
  103. {
  104. u32 iiscon;
  105. s3cdbg("Entered %s: on = %d\n", __FUNCTION__, on);
  106. iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
  107. if (on) {
  108. iiscon |= S3C_IIS0CON_I2SACTIVE;
  109. writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
  110. } else {
  111. /* note, we have to disable the FIFOs otherwise bad things
  112. * seem to happen when the DMA stops. According to the
  113. * Samsung supplied kernel, this should allow the DMA
  114. * engine and FIFOs to reset. If this isn't allowed, the
  115. * DMA engine will simply freeze randomly.
  116. */
  117. iiscon &= ~S3C_IIS0CON_I2SACTIVE;
  118. writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
  119. }
  120. }
  121. /*
  122. * Wait for the LR signal to allow synchronisation to the L/R clock
  123. * from the codec. May only be needed for slave mode.
  124. */
  125. static int s3c24xx_snd_lrsync(void)
  126. {
  127. u32 iiscon;
  128. unsigned long timeout = jiffies + msecs_to_jiffies(5);
  129. s3cdbg("Entered %s\n", __FUNCTION__);
  130. while (1) {
  131. iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
  132. if (iiscon & S3C_IISCON_LRINDEX)
  133. break;
  134. if (timeout < jiffies)
  135. return -ETIMEDOUT;
  136. }
  137. return 0;
  138. }
  139. /*
  140. * Check whether CPU is the master or slave
  141. */
  142. static inline int s3c24xx_snd_is_clkmaster(void)
  143. {
  144. s3cdbg("Entered %s\n", __FUNCTION__);
  145. return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C_IIS0MOD_IMS_SLAVE) ? 0:1;
  146. }
  147. /*
  148. * Set S3C24xx I2S DAI format
  149. */
  150. static int s3c_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai,
  151. unsigned int fmt)
  152. {
  153. u32 iismod;
  154. iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
  155. iismod &= ~S3C_IIS0MOD_FS_MASK;
  156. //HIKO DEBUG:
  157. // iismod |= S3C_IIS0MOD_384FS;
  158. // iismod |= S3C_IIS0MOD_768FS;
  159. iismod |= S3C_IIS0MOD_512FS;
  160. writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
  161. return 0;
  162. }
  163. static int s3c_i2s_hw_params(struct snd_pcm_substream *substream,
  164. struct snd_pcm_hw_params *params)
  165. {
  166. struct snd_soc_pcm_runtime *rtd = substream->private_data;
  167. unsigned long iiscon;
  168. unsigned long iismod;
  169. unsigned long iisfcon;
  170. s3cdbg("Entered %s\n", __FUNCTION__);
  171. #if 0 /* To mesure mpll clock */
  172. s3c2410_gpio_cfgpin(S3C2443_GPH13, S3C2443_GPH13_CLKOUT0);
  173. s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_CLKOUT1);
  174. #endif
  175. writel((readl(S3C2410_MISCCR) & ~(7<<8))|(1<<8), S3C2410_MISCCR);
  176. //[HIKO] Original (Master)
  177. #if 1
  178. s3c24xx_i2s.master = 1;
  179. //[HIKO] Realtek Charles suggestion for CPU Slave mode
  180. #else
  181. s3c24xx_i2s.master = 0;
  182. #endif //0
  183. /* Configure the I2S pins in correct mode */
  184. writel(0x0, S3C2450_GPESEL);
  185. // rt5624_power(true);
  186. // rt5624_i2s_init();
  187. // rt5624_i2c_init();
  188. writel(readl(S3C2410_GPEUP)| 0x3ff, S3C2410_GPEUP);
  189. //writel(readl(S3C2450_GPBSEL)|(0x3<<3), S3C2450_GPBSEL);
  190. writel(readl(S3C2450_GPBSEL)|(0x1<<3), S3C2450_GPBSEL);
  191. writel(readl(S3C2410_GPBUP)|(0xF<<18), S3C2410_GPBUP);
  192. if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
  193. rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out;
  194. } else {
  195. rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_in;
  196. }
  197. /* Working copies of registers */
  198. iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
  199. iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
  200. iisfcon = readl(s3c24xx_i2s.regs + S3C2443_IISFIC);
  201. iiscon |= S3C_IIS0CON_TXDMACTIVE;
  202. iiscon |= S3C_IIS0CON_RXDMACTIVE;
  203. iismod &= ~S3C_IIS0MOD_CLK_MASK;
  204. //[HIKO] Original (Master)
  205. #if 1
  206. //Original
  207. iismod |= S3C_IIS0MOD_IMS_EXTERNAL_MASTER| S3C_IIS0MOD_INTERNAL_CLK;
  208. //HIKO DEBUG
  209. // iismod &= S3C_IIS0MOD_FM_MASK;
  210. // iismod |= S3C_IIS0MOD_LSB;
  211. //[HIKO] Realtek Charles suggestion for CPU Slave mode
  212. #else
  213. // iismod |= S3C_IIS0MOD_IMS_SLAVE| S3C_IIS0MOD_INTERNAL_CLK;
  214. // iismod |= S3C_IIS0MOD_IMS_SLAVE| S3C_IIS0MOD_INTERNAL_CLK;
  215. iismod |= (0x3<<10)| S3C_IIS0MOD_INTERNAL_CLK;
  216. #endif //0
  217. iismod &= ~S3C_IIS0MOD_MODE_MASK;
  218. iismod |= S3C_IIS0MOD_TXRXMODE;
  219. //HIKO: the Multichannel setting would cause the CPU reboot continuously
  220. #if 0
  221. /* Multi channel enable */
  222. iismod &= ~S3C_IIS0MOD_DCE_MASK;
  223. switch (params_channels(params)) {
  224. case 6:
  225. printk("s3c i2s: 5.1channel\n");
  226. iismod |= S3C_IIS0MOD_DCE_SD1;
  227. iismod |= S3C_IIS0MOD_DCE_SD2;
  228. break;
  229. case 4:
  230. printk("s3c i2s: 4 channel\n");
  231. iismod |= S3C_IIS0MOD_DCE_SD1;
  232. break;
  233. case 2:
  234. printk("s3c i2s: 2 channel\n");
  235. break;
  236. default:
  237. printk(KERN_ERR "s3c-i2s-v40: %d channels unsupported\n",
  238. params_channels(params));
  239. return -EINVAL;
  240. }
  241. #endif //0
  242. #if 1
  243. // iismod &= ~0x6000;
  244. iismod &= ~S3C_IIS0MOD_BFS_MASK;
  245. //HIKO DEBUG
  246. iismod |= S3C_IIS0MOD_32FS;
  247. // iismod |= S3C_IIS0MOD_48FS;
  248. iismod &= ~S3C_IIS0MOD_FS_MASK;
  249. //HIKO DEBUG
  250. // iismod |= S3C_IIS0MOD_384FS;
  251. // iismod |= S3C_IIS0MOD_768FS;
  252. iismod |= S3C_IIS0MOD_512FS;
  253. #else
  254. switch (params_format(params)) {
  255. case SNDRV_PCM_FORMAT_S8:
  256. // iismod |= S3C_IIS0MOD_8BIT;
  257. iismod |= S3C_IIS0MOD_16BIT;
  258. iismod &= ~S3C_IIS0MOD_BFS_MASK;
  259. iismod |= S3C_IIS0MOD_32FS;
  260. iismod &= ~S3C_IIS0MOD_FS_MASK;
  261. iismod |= S3C_IIS0MOD_384FS;
  262. break;
  263. case SNDRV_PCM_FORMAT_S16_LE:
  264. iismod &= ~S3C_IIS0MOD_FS_MASK;
  265. iismod &= ~S3C_IIS0MOD_BFS_MASK;
  266. iismod |= S3C_IIS0MOD_384FS | S3C_IIS0MOD_32FS;
  267. iismod &= ~S3C_IIS0MOD_BLC_MASK;
  268. iismod |= S3C_IIS0MOD_16BIT;
  269. break;
  270. case SNDRV_PCM_FORMAT_S24_LE:
  271. iismod &= ~S3C_IIS0MOD_FS_MASK;
  272. iismod &= ~S3C_IIS0MOD_BFS_MASK;
  273. iismod |= S3C_IIS0MOD_384FS | S3C_IIS0MOD_48FS;
  274. iismod &= ~S3C_IIS0MOD_BLC_MASK;
  275. // iismod |= S3C_IIS0MOD_24BIT;
  276. iismod |= S3C_IIS0MOD_16BIT;
  277. break;
  278. default:
  279. return -EINVAL;
  280. }
  281. #endif
  282. iisfcon |= S3C_IIS_TX_FLUSH;
  283. iisfcon |= S3C_IIS_RX_FLUSH;
  284. writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
  285. writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
  286. writel(iisfcon, s3c24xx_i2s.regs + S3C2443_IISFIC);
  287. /* Tx, Rx fifo flush bit clear */
  288. iisfcon &= ~(S3C_IIS_TX_FLUSH | S3C_IIS_RX_FLUSH);
  289. writel(iisfcon, s3c24xx_i2s.regs + S3C2443_IISFIC);
  290. printk("s3c iis mode: 0x%08x\n", readl(s3c24xx_i2s.regs + S3C2410_IISMOD));
  291. printk("s3c: params_channels %d\n", params_channels(params));
  292. printk("s3c: params_format %d\n", params_format(params));
  293. printk("s3c: params_subformat %d\n", params_subformat(params));
  294. printk("s3c: params_period_size %d\n", params_period_size(params));
  295. printk("s3c: params_period_bytes %d\n", params_period_bytes(params));
  296. printk("s3c: params_periods %d\n", params_periods(params));
  297. printk("s3c: params_buffer_size %d\n", params_buffer_size(params));
  298. printk("s3c: params_buffer_bytes %d\n", params_buffer_bytes(params));
  299. printk("s3c: params_tick_time %d\n", params_tick_time(params));
  300. return 0;
  301. }
  302. static int s3c_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
  303. {
  304. int ret = 0;
  305. s3cdbg("Entered %s: cmd = %d\n", __FUNCTION__, cmd);
  306. switch (cmd) {
  307. case SNDRV_PCM_TRIGGER_START:
  308. case SNDRV_PCM_TRIGGER_RESUME:
  309. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  310. if (!s3c24xx_snd_is_clkmaster()) {
  311. ret = s3c24xx_snd_lrsync();
  312. if (ret)
  313. goto exit_err;
  314. }
  315. if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  316. s3c24xx_snd_rxctrl(1);
  317. else
  318. s3c24xx_snd_txctrl(1);
  319. break;
  320. case SNDRV_PCM_TRIGGER_STOP:
  321. case SNDRV_PCM_TRIGGER_SUSPEND:
  322. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  323. if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
  324. s3c24xx_snd_rxctrl(0);
  325. else
  326. s3c24xx_snd_txctrl(0);
  327. break;
  328. default:
  329. ret = -EINVAL;
  330. break;
  331. }
  332. exit_err:
  333. return ret;
  334. }
  335. static void s3c64xx_i2s_shutdown(struct snd_pcm_substream *substream)
  336. {
  337. unsigned long iiscon;
  338. iiscon=readl(s3c24xx_i2s.regs + S3C2410_IISCON);
  339. iiscon &= ~S3C_IIS0CON_I2SACTIVE;
  340. writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
  341. }
  342. /*
  343. * Set S3C24xx Clock source
  344. */
  345. static int s3c_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
  346. int clk_id, unsigned int freq, int dir)
  347. {
  348. u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
  349. switch (clk_id) {
  350. case S3C24XX_CLKSRC_PCLK:
  351. break;
  352. case S3C24XX_CLKSRC_MPLL:
  353. break;
  354. default:
  355. return -EINVAL;
  356. }
  357. writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
  358. return 0;
  359. }
  360. /*
  361. * Set S3C24xx Clock dividers
  362. */
  363. static int s3c_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
  364. int div_id, int div)
  365. {
  366. u32 reg;
  367. s3cdbg("Entered %s : div_id = %d, div = %d\n", __FUNCTION__, div_id, div);
  368. switch (div_id) {
  369. case S3C24XX_DIV_MCLK:
  370. reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_BFS_MASK;
  371. writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD);
  372. break;
  373. case S3C24XX_DIV_BCLK:
  374. reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~(S3C_IIS0MOD_FS_MASK);
  375. writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD);
  376. break;
  377. case S3C24XX_DIV_PRESCALER:
  378. reg = readl(s3c24xx_i2s.regs + S3C2443_IISPSR);
  379. reg &= ~(S3C_IISPSR_PS_MASK|S3C_IISPSR_PSRAEN);
  380. writel(reg , s3c24xx_i2s.regs + S3C2443_IISPSR);
  381. reg |= (div|S3C_IISPSR_PSRAEN);
  382. writel(reg, s3c24xx_i2s.regs + S3C2443_IISPSR);
  383. break;
  384. default:
  385. return -EINVAL;
  386. }
  387. return 0;
  388. }
  389. /*
  390. * To avoid duplicating clock code, allow machine driver to
  391. * get the clockrate from here.
  392. */
  393. u32 s3c_i2s_get_clockrate(void)
  394. {
  395. return clk_get_rate(s3c24xx_i2s.iis_clk);
  396. }
  397. EXPORT_SYMBOL_GPL(s3c_i2s_get_clockrate);
  398. static int s3c_i2s_probe(struct platform_device *pdev)
  399. {
  400. int ret = 0;
  401. s3cdbg("Entered %s\n", __FUNCTION__);
  402. //HIKO DEBUG: for RT5624
  403. // rt5624_power(true);
  404. // rt5624_i2s_init();
  405. s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
  406. if (s3c24xx_i2s.regs == NULL) {
  407. s3cdbg("[HIKO AUDIO] s3c24xx_i2s.regs == NULL\n");
  408. return -ENXIO;
  409. }
  410. s3c24xx_i2s.iis_clk=clk_get(&pdev->dev, "iis");
  411. if (s3c24xx_i2s.iis_clk == NULL) {
  412. s3cdbg("failed to get iis_clock\n");
  413. return -ENODEV;
  414. }
  415. ret = clk_enable(s3c24xx_i2s.iis_clk);
  416. //HIKO DEBUG: for RT5624
  417. // rt5624_i2c_init();
  418. //HIKO DEBUG: for RT5624
  419. s3c24xx_snd_txctrl(0);
  420. // s3c24xx_snd_txctrl(1);
  421. s3c24xx_snd_rxctrl(0);
  422. // s3c24xx_snd_rxctrl(1);
  423. return 0;
  424. }
  425. #ifdef CONFIG_PM
  426. static int s3c_i2s_suspend(struct platform_device *dev,
  427. struct snd_soc_cpu_dai *dai)
  428. {
  429. s3cdbg("Entered %s\n", __FUNCTION__);
  430. return 0;
  431. }
  432. static int s3c_i2s_resume(struct platform_device *pdev,
  433. struct snd_soc_cpu_dai *dai)
  434. {
  435. s3cdbg("Entered %s\n", __FUNCTION__);
  436. return 0;
  437. }
  438. #else
  439. #define s3c_i2s_suspend NULL
  440. #define s3c_i2s_resume NULL
  441. #endif
  442. #define S3C24XX_I2S_RATES \
  443. (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
  444. SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
  445. SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
  446. struct snd_soc_cpu_dai s3c_i2s_dai = {
  447. .name = "s3c-i2s",
  448. .id = 0,
  449. .type = SND_SOC_DAI_I2S,
  450. .probe = s3c_i2s_probe,
  451. .suspend = s3c_i2s_suspend,
  452. .resume = s3c_i2s_resume,
  453. .playback = {
  454. .channels_min = 2,
  455. .channels_max = 2,
  456. .rates = S3C24XX_I2S_RATES,
  457. .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
  458. .capture = {
  459. .channels_min = 2,
  460. .channels_max = 2,
  461. .rates = S3C24XX_I2S_RATES,
  462. .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
  463. .ops = {
  464. .shutdown = s3c64xx_i2s_shutdown,
  465. .trigger = s3c_i2s_trigger,
  466. .hw_params = s3c_i2s_hw_params,},
  467. .dai_ops = {
  468. .set_fmt = s3c_i2s_set_fmt,
  469. .set_clkdiv = s3c_i2s_set_clkdiv,
  470. .set_sysclk = s3c_i2s_set_sysclk,
  471. },
  472. };
  473. /*
  474. * For RT5624 setting MCLK first
  475. */
  476. int s3c_i2s_set_iispcr_clkdiv_rt5624(unsigned char div)
  477. {
  478. u32 reg;
  479. u32 iomap_buf;
  480. bool has_exist = false;
  481. s3cdbg("Entered %s : \n", __FUNCTION__);
  482. if (s3c24xx_i2s.regs) {
  483. iomap_buf = s3c24xx_i2s.regs;
  484. has_exist = true;
  485. } else {
  486. iomap_buf = ioremap(S3C2410_PA_IIS, 0x100);
  487. }
  488. reg = readl(iomap_buf + S3C2443_IISPSR);
  489. reg &= ~(S3C_IISPSR_PS_MASK|S3C_IISPSR_PSRAEN);
  490. writel(reg , iomap_buf + S3C2443_IISPSR);
  491. //Setting divider value
  492. reg |= (div<<8 | S3C_IISPSR_PSRAEN);
  493. writel(reg, iomap_buf + S3C2443_IISPSR);
  494. if (!has_exist)
  495. iounmap(iomap_buf);
  496. return 0;
  497. }
  498. EXPORT_SYMBOL_GPL(s3c_i2s_set_iispcr_clkdiv_rt5624);
  499. /*
  500. * For RT5624 setting MCLK first
  501. */
  502. int s3c_i2s_set_iisclk_clkdiv_rt5624(unsigned char div)
  503. {
  504. u32 reg;
  505. u32 iomap_buf;
  506. bool has_exist = false;
  507. s3cdbg("Entered %s : \n", __FUNCTION__);
  508. if (s3c24xx_i2s.regs) {
  509. iomap_buf = s3c24xx_i2s.regs;
  510. has_exist = true;
  511. } else {
  512. iomap_buf = ioremap(S3C2410_PA_IIS, 0x100);
  513. }
  514. iomap_buf = ioremap(S3C2410_PA_IIS, 0x100);
  515. reg = readl(iomap_buf + S3C2443_SCLKCON);
  516. reg |= S3C2443_SCLKCON_I2SCLK;
  517. writel(reg , iomap_buf + S3C2443_SCLKCON);
  518. //Setting divider value
  519. // reg |= (div<<8 | S3C_IISPSR_PSRAEN);
  520. // writel(reg, s3c24xx_i2s.regs + S3C2443_IISPSR);
  521. if (!has_exist)
  522. iounmap(iomap_buf);
  523. return 0;
  524. }
  525. EXPORT_SYMBOL_GPL(s3c_i2s_set_iisclk_clkdiv_rt5624);
  526. /*
  527. ** get the iismod value
  528. */
  529. u32 get_iismod()
  530. {
  531. if (!s3c24xx_i2s.regs)
  532. return readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
  533. }
  534. EXPORT_SYMBOL_GPL(get_iismod);
  535. /*
  536. ** set the iismod value
  537. */
  538. void set_iismod(u32 iismod)
  539. {
  540. writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
  541. }
  542. EXPORT_SYMBOL_GPL(set_iismod);
  543. /*
  544. ** get the iiscon value
  545. */
  546. u32 get_iiscon()
  547. {
  548. return readl(s3c24xx_i2s.regs + S3C2410_IISCON);
  549. }
  550. EXPORT_SYMBOL_GPL(get_iiscon);
  551. /*
  552. ** set the iiscon value
  553. */
  554. void set_iiscon(u32 iiscon)
  555. {
  556. writel(iiscon, s3c24xx_i2s.regs + S3C2410_IISCON);
  557. }
  558. EXPORT_SYMBOL_GPL(set_iiscon);
  559. /*
  560. ** get the iisfic value
  561. */
  562. u32 get_iisfic()
  563. {
  564. return readl(s3c24xx_i2s.regs + S3C2443_IISFIC);
  565. }
  566. EXPORT_SYMBOL_GPL(get_iisfic);
  567. /*
  568. ** set the iiscon value
  569. */
  570. void set_iisfic(u32 iisfic)
  571. {
  572. writel(iisfic, s3c24xx_i2s.regs + S3C2443_IISFIC);
  573. }
  574. EXPORT_SYMBOL_GPL(set_iisfic);
  575. /*
  576. ** get the iispsr value
  577. */
  578. u32 get_iispsr()
  579. {
  580. return readl(s3c24xx_i2s.regs + S3C2443_IISPSR);
  581. }
  582. EXPORT_SYMBOL_GPL(get_iispsr);
  583. /*
  584. ** set the iispsr value
  585. */
  586. void set_iispsr(u32 iispsr)
  587. {
  588. writel(iispsr, s3c24xx_i2s.regs + S3C2443_IISPSR);
  589. }
  590. EXPORT_SYMBOL_GPL(set_iispsr);
  591. /*
  592. ** get the iistxd value
  593. */
  594. u32 get_iistxd()
  595. {
  596. return readl(s3c24xx_i2s.regs + S3C2410_IISFIFO);
  597. }
  598. EXPORT_SYMBOL_GPL(get_iistxd);
  599. /*
  600. ** set the iistxd value
  601. */
  602. void set_iistxd(u32 iistxd)
  603. {
  604. writel(iistxd, s3c24xx_i2s.regs + S3C2410_IISFIFO);
  605. }
  606. EXPORT_SYMBOL_GPL(set_iistxd);
  607. /*
  608. ** get the iisrxd value
  609. */
  610. u32 get_iisrxd()
  611. {
  612. return readl(s3c24xx_i2s.regs + S3C2410_IISFIFORX);
  613. }
  614. EXPORT_SYMBOL_GPL(get_iisrxd);
  615. /*
  616. ** set the iisrxd value
  617. */
  618. void set_iisrxd(u32 iisrxd)
  619. {
  620. writel(iisrxd, s3c24xx_i2s.regs + S3C2410_IISFIFORX);
  621. }
  622. EXPORT_SYMBOL_GPL(set_iisrxd);
  623. EXPORT_SYMBOL_GPL(s3c_i2s_dai);
  624. /* Module information */
  625. MODULE_AUTHOR("Ryu, <ryu.real@gmail.com>");
  626. MODULE_DESCRIPTION("s3c2450 I2S SoC Interface");
  627. MODULE_LICENSE("GPL");