s3c6410_i2s.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. /*
  2. * Glue audio driver for the SA1111 compagnon chip & Philips UDA1341 codec.
  3. *
  4. * Copyright (C) 2007, Ryu Euiyoul <ryu.real@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License.
  8. */
  9. #include <linux/init.h>
  10. #include <linux/module.h>
  11. #include <linux/delay.h>
  12. #include <linux/clk.h>
  13. #include <linux/sched.h>
  14. #include <linux/sound.h>
  15. #include <linux/soundcard.h>
  16. #include <linux/errno.h>
  17. #include <linux/device.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/l3/l3.h>
  20. #include <linux/l3/uda1341.h>
  21. #include <linux/platform_device.h>
  22. #include <asm/hardware.h>
  23. #include <asm/semaphore.h>
  24. #include <asm/irq.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/dma.h>
  27. #include <asm/io.h>
  28. #include <asm/arch/dma.h>
  29. #include <asm/arch/regs-iis.h>
  30. #include <asm/arch/regs-gpio.h>
  31. #include <asm/arch/regs-s3c6400-clock.h>
  32. #include "s3c6400_pcm.h"
  33. #define DPRINTK( x... )
  34. //#define DPRINTK printk
  35. #define S_CLOCK_FREQ 384
  36. #define CONFIG_IIS_24BIT
  37. static DECLARE_MUTEX(s3c_lock);
  38. static int
  39. mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
  40. {
  41. printk("Warning: Set the mixer at %s, %d\n",__FUNCTION__,__LINE__);
  42. //return uda1341_mixer_ctl(uda1341, cmd, (void *)arg);
  43. return 0;
  44. }
  45. static struct file_operations uda1341_mixer_fops = {
  46. .owner = THIS_MODULE,
  47. .ioctl = mixer_ioctl,
  48. };
  49. static int l3_gpio_set(void)
  50. {
  51. s3c_gpio_cfgpin(S3C_GPN15, S3C_GPN15_OUTP); /* DAT */
  52. s3c_gpio_cfgpin(S3C_GPN14, S3C_GPN14_OUTP); /* MOD */
  53. s3c_gpio_cfgpin(S3C_GPN13, S3C_GPN13_OUTP); /* CLK */
  54. s3c_gpio_setpin(S3C_GPN15, 0);
  55. s3c_gpio_setpin(S3C_GPN14, 1);
  56. s3c_gpio_setpin(S3C_GPN13, 1);
  57. return 0;
  58. }
  59. static int l3_uda1342_set_addr(u8 dat)
  60. {
  61. u32 i, j;
  62. s3c_gpio_setpin(S3C_GPN13, 1);
  63. s3c_gpio_setpin(S3C_GPN15, 0);
  64. s3c_gpio_setpin(S3C_GPN14, 0);
  65. for(j=0; j<4; j++);
  66. for(i=0; i<8; i++){
  67. if(dat & 0x1){
  68. s3c_gpio_setpin(S3C_GPN13, 0);
  69. s3c_gpio_setpin(S3C_GPN15, 1);
  70. for(j=0; j<4; j++);
  71. s3c_gpio_setpin(S3C_GPN13, 1);
  72. s3c_gpio_setpin(S3C_GPN15, 1);
  73. for(j=0; j<4; j++);
  74. } else{
  75. s3c_gpio_setpin(S3C_GPN13, 0);
  76. s3c_gpio_setpin(S3C_GPN15, 0);
  77. for(j=0; j<4; j++);
  78. s3c_gpio_setpin(S3C_GPN13, 1);
  79. s3c_gpio_setpin(S3C_GPN15, 0);
  80. for(j=0; j<4; j++);
  81. }
  82. dat >>= 1;
  83. }
  84. s3c_gpio_setpin(S3C_GPN15, 0);
  85. s3c_gpio_setpin(S3C_GPN13, 1);
  86. s3c_gpio_setpin(S3C_GPN14, 1);
  87. return 0;
  88. }
  89. static int l3_uda1342_set_data(u8 dat)
  90. {
  91. u32 i, j;
  92. s3c_gpio_setpin(S3C_GPN15, 0);
  93. s3c_gpio_setpin(S3C_GPN13, 1);
  94. s3c_gpio_setpin(S3C_GPN14, 1);
  95. for(j=0; j<4; j++);
  96. for(i=0; i<8; i++){
  97. if(dat & 0x1){
  98. s3c_gpio_setpin(S3C_GPN13, 0);
  99. s3c_gpio_setpin(S3C_GPN15, 1);
  100. for(j=0; j<4; j++);
  101. s3c_gpio_setpin(S3C_GPN13, 1);
  102. s3c_gpio_setpin(S3C_GPN15, 1);
  103. for(j=0; j<4; j++);
  104. } else{
  105. s3c_gpio_setpin(S3C_GPN13, 0);
  106. s3c_gpio_setpin(S3C_GPN15, 0);
  107. for(j=0; j<4; j++);
  108. s3c_gpio_setpin(S3C_GPN13, 1);
  109. s3c_gpio_setpin(S3C_GPN15, 0);
  110. for(j=0; j<4; j++);
  111. }
  112. dat >>= 1;
  113. }
  114. s3c_gpio_setpin(S3C_GPN13, 1);
  115. s3c_gpio_setpin(S3C_GPN14, 1);
  116. s3c_gpio_setpin(S3C_GPN15, 0);
  117. return 0;
  118. }
  119. static int l3_uda1342_init(void)
  120. {
  121. l3_uda1342_set_addr(0x12);
  122. l3_uda1342_set_data(0x00);
  123. l3_uda1342_set_data(0x45);
  124. l3_uda1342_set_data(0x44);
  125. l3_uda1342_set_addr(0x12);
  126. l3_uda1342_set_data(0x00);
  127. l3_uda1342_set_data(0x44);
  128. l3_uda1342_set_data(0x44);
  129. return 0;
  130. }
  131. static int l3_uda1342_rec_init(void)
  132. {
  133. l3_uda1342_set_addr(0x12);
  134. l3_uda1342_set_data(0x80);
  135. l3_uda1342_set_data(0x0);
  136. l3_uda1342_set_data(0x14);
  137. l3_uda1342_set_addr(0x12);
  138. l3_uda1342_set_data(0x04);
  139. l3_uda1342_set_data(0xC0); /* 0xC0: ADC input amplifire gain 9dB */
  140. l3_uda1342_set_data(0x00); /* 0x0 : ADC mixer gain 0dB */
  141. return 0;
  142. }
  143. static long audio_set_dsp_speed(long val, int f_mode)
  144. {
  145. //u32 iispsr = 0, prescaler = 0;
  146. u32 iiscon = 0, iismod = 0, iisfic = 0;
  147. DPRINTK("%s : requested = %ld, f_mode = 0x%x\n",
  148. __FUNCTION__, val, f_mode);
  149. l3_gpio_set();
  150. l3_uda1342_init();
  151. if ( f_mode & FMODE_READ)
  152. l3_uda1342_rec_init();
  153. #if 0
  154. /* Setup the EPLL clock source */
  155. writel(0, S3C_EPLL_CON1);
  156. switch (val) {
  157. case 8000:
  158. case 16000:
  159. case 32000:
  160. writel((1 << 31) | (128 << 16) | (25 << 8) | (0 << 0),
  161. S3C_EPLL_CON0);
  162. break;
  163. case 48000:
  164. writel((1 << 31) | (192 << 16) | (25 << 8) | (0 << 0),
  165. S3C_EPLL_CON0);
  166. break;
  167. case 11025:
  168. case 22050:
  169. case 44100:
  170. default:
  171. writel((1 << 31) | (254 << 16) | (9 << 8) | (2 << 0),
  172. S3C_EPLL_CON0);
  173. break;
  174. }
  175. while (!(readl(S3C_EPLL_CON0) & (1 << 30)));
  176. //MUXepll : FOUTepll
  177. writel(readl(S3C_CLK_SRC) | S3C_CLKSRC_EPLL_CLKSEL, S3C_CLK_SRC);
  178. //AUDIO0 sel : FOUTepll
  179. writel((readl(S3C_CLK_SRC) & ~(0x7 << 7)) | (0 << 7), S3C_CLK_SRC);
  180. //CLK_DIV2 setting
  181. writel(0x0, S3C_CLK_DIV2);
  182. #endif
  183. /* FIFO is flushed before operation */
  184. iisfic = S3C_IIS_TX_FLUSH | S3C_IIS_RX_FLUSH;
  185. writel(iisfic, S3C_IIS0FIC);
  186. writel(0, S3C_IIS0FIC);
  187. #if 0
  188. /* Clear I2S prescaler value [13:8] and disable prescaler */
  189. iispsr = readl(S3C_IIS0PSR);
  190. iispsr &= ~((0x3f << 8) | (1 << 15));
  191. writel(iispsr, S3C_IIS0PSR);
  192. #endif
  193. /* Configure I2SMOD */
  194. iismod = S3C_IIS0MOD_IMS_EXTERNAL_MASTER | S3C_IIS0MOD_TXRXMODE
  195. | S3C_IIS0MOD_IIS;
  196. iismod |= S3C_IIS0MOD_384FS;
  197. #ifdef CONFIG_IIS_24BIT
  198. iismod |= S3C_IIS0MOD_48FS;
  199. iismod |= S3C_IIS0MOD_24BIT;
  200. #else
  201. iismod |= S3C_IIS0MOD_32FS;
  202. iismod |= S3C_IIS0MOD_16BIT;
  203. #endif
  204. writel(iismod, S3C_IIS0MOD);
  205. #if 0
  206. switch (val) {
  207. case 8000:
  208. case 11025:
  209. prescaler = 19;
  210. break;
  211. case 16000:
  212. case 22050:
  213. prescaler = 9;
  214. break;
  215. case 32000:
  216. case 44100:
  217. case 48000:
  218. default:
  219. prescaler = 4;
  220. break;
  221. }
  222. #endif
  223. // writel(readl(S3C_IIS0PSR) | (prescaler << 8) | (1 << 15),
  224. //writel(0x8020, S3C_IIS0PSR);
  225. iiscon = S3C_IIS0CON_TXDMACTIVE | S3C_IIS0CON_RXDMACTIVE;
  226. iiscon |= S3C_IIS0CON_I2SACTIVE;
  227. // iiscon |= (1<<16); /* underrun interrupt enable */
  228. #if 0
  229. DPRINTK("%s, IISCON: 0x%08x IISMOD: 0x%08x IISFIC : 0x%08x IISPSR: 0x%08x\n",
  230. __FUNCTION__, readl(S3C_IIS0CON),
  231. readl(S3C_IIS0MOD), readl(S3C_IIS0FIC), readl(S3C_IIS0PSR));
  232. #endif
  233. writel(iiscon, S3C_IIS0CON);
  234. return val;
  235. }
  236. static int s3c_audio_ioctl(struct inode *inode,
  237. struct file *file, uint cmd, ulong arg)
  238. {
  239. long val = 0;
  240. int ret = 0;
  241. audio_state_t *state = file->private_data;
  242. DPRINTK("%s : #### sound_mode = 0x%x\n", __FUNCTION__, state->sound_mode);
  243. switch (cmd) {
  244. case SNDCTL_DSP_STEREO:
  245. if (get_user(val, (int *) arg))
  246. return -EINVAL;
  247. state->sound_mode = (val) ? 2 : 1;
  248. return 0;
  249. case SNDCTL_DSP_CHANNELS:
  250. if (get_user(val, (int *) arg))
  251. return -EINVAL;
  252. if (val != 1 && val != 2)
  253. return -EINVAL;
  254. state->sound_mode = val;
  255. return put_user(val, (int *) arg);
  256. case SOUND_PCM_READ_CHANNELS:
  257. return put_user(state->sound_mode, (long *) arg);
  258. case SNDCTL_DSP_SPEED:
  259. ret = get_user(val, (long *) arg);
  260. if (ret)
  261. break;
  262. audio_set_dsp_speed(val, file->f_mode);
  263. break;
  264. case SOUND_PCM_READ_RATE:
  265. ret = put_user(val, (long *) arg);
  266. break;
  267. #if 0
  268. case SNDCTL_DSP_SETFMT:
  269. case SNDCTL_DSP_GETFMTS:
  270. /* we can do 16-bit only */
  271. ret = put_user(AFMT_S16_LE, (long *) arg);
  272. break;
  273. #endif
  274. default:
  275. /* Maybe this is meant for the mixer (as per OSS Docs) */
  276. // ret = mixer_ioctl(inode, file, cmd, arg);
  277. break;
  278. }
  279. return ret;
  280. }
  281. static void s3c_audio_shutdown(void *dummy)
  282. {
  283. unsigned long iiscon;
  284. /* close I2S port */
  285. s3c_gpio_cfgpin(S3C_GPD0, S3C_GPD0_INP);
  286. s3c_gpio_cfgpin(S3C_GPD1, S3C_GPD1_INP);
  287. s3c_gpio_cfgpin(S3C_GPD2, S3C_GPD2_INP);
  288. s3c_gpio_cfgpin(S3C_GPD3, S3C_GPD3_INP);
  289. s3c_gpio_cfgpin(S3C_GPD4, S3C_GPD4_INP);
  290. s3c_gpio_pullup(S3C_GPD0, 0);
  291. s3c_gpio_pullup(S3C_GPD1, 0);
  292. s3c_gpio_pullup(S3C_GPD2, 0);
  293. s3c_gpio_pullup(S3C_GPD3, 0);
  294. s3c_gpio_pullup(S3C_GPD4, 0);
  295. /* deactivate I2S */
  296. iiscon = readl(S3C_IIS0CON);
  297. iiscon &= !S3C_IIS0CON_I2SACTIVE;
  298. writel(iiscon, S3C_IIS0CON);
  299. DPRINTK("#### IISCON: 0x%08x IISMOD: 0x%08x IISPSR: 0x%08x\n",
  300. readl(S3C_IIS0CON), readl(S3C_IIS0MOD), readl(S3C_IIS0PSR));
  301. }
  302. static int s3c_select_clk(void)
  303. {
  304. /* PCLK & SCLK gating enable */
  305. writel(readl(S3C_PCLK_GATE) | S3C_CLKCON_PCLK_IIS0, S3C_PCLK_GATE);
  306. writel(readl(S3C_SCLK_GATE) | S3C_CLKCON_SCLK_AUDIO0,
  307. S3C_SCLK_GATE);
  308. return 0;
  309. }
  310. static int s3c_iis_config_pins(void)
  311. {
  312. /*Set I2S port to controll UDA1342 codec */
  313. s3c_gpio_cfgpin(S3C_GPD0, S3C_GPD0_I2S_CLK0);
  314. s3c_gpio_cfgpin(S3C_GPD1, S3C_GPD1_I2S_CDCLK0);
  315. s3c_gpio_cfgpin(S3C_GPD2, S3C_GPD2_I2S_LRCLK0);
  316. s3c_gpio_cfgpin(S3C_GPD3, S3C_GPD3_I2S_DI0);
  317. s3c_gpio_cfgpin(S3C_GPD4, S3C_GPD4_I2S_DO0);
  318. s3c_gpio_pullup(S3C_GPD0, 2);
  319. s3c_gpio_pullup(S3C_GPD1, 2);
  320. s3c_gpio_pullup(S3C_GPD2, 2);
  321. s3c_gpio_pullup(S3C_GPD3, 2);
  322. s3c_gpio_pullup(S3C_GPD4, 2);
  323. return 0;
  324. }
  325. static audio_stream_t output_stream = {
  326. id: "s3c64xx audio out ",
  327. subchannel: DMACH_I2S_OUT,
  328. };
  329. static audio_stream_t input_stream = {
  330. id: "s3c64xx audio in ",
  331. subchannel: DMACH_I2S_IN,
  332. };
  333. static audio_state_t audio_state = {
  334. .output_stream = &output_stream,
  335. .input_stream = &input_stream,
  336. .hw_shutdown = s3c_audio_shutdown,
  337. .client_ioctl = s3c_audio_ioctl,
  338. };
  339. static int s3c_audio_open(struct inode *inode, struct file *file)
  340. {
  341. s3c_iis_config_pins();
  342. s3c_select_clk();
  343. init_MUTEX(&audio_state.sem);
  344. return s3c_audio_attach(inode, file, &audio_state);
  345. }
  346. static irqreturn_t s3c_iis_irq(int irqno, void *dev_id)
  347. {
  348. u32 iiscon;
  349. iiscon = readl(S3C_IIS0CON);
  350. if((1<<17) & iiscon) {
  351. writel((1<<17)| iiscon, S3C_IIS0CON);
  352. }
  353. printk("%s: %d IISCON = 0x%08x\n",__FUNCTION__, __LINE__,readl(S3C_IIS0CON));
  354. return IRQ_HANDLED;
  355. }
  356. /*
  357. * Missing fields of this structure will be patched with the call
  358. * to s3c_audio_attach().
  359. */
  360. static struct file_operations s3c_audio_fops = {
  361. .owner = THIS_MODULE,
  362. .open = s3c_audio_open,
  363. };
  364. static int audio_dev_id, mixer_dev_id;
  365. static int s3c_audio_probe(struct device *_dev)
  366. {
  367. int ret;
  368. ret = request_irq(IRQ_IIS, s3c_iis_irq, SA_INTERRUPT,
  369. "s3c2410-iis", NULL);
  370. if (ret != 0) {
  371. printk("IIS: cannot claim IRQ\n");
  372. return 0;
  373. }
  374. audio_dev_id = register_sound_dsp(&s3c_audio_fops, -1);
  375. mixer_dev_id = register_sound_mixer(&uda1341_mixer_fops, -1);
  376. printk(KERN_INFO "Sound uda1342: dsp id %d mixer id %d\n",
  377. audio_dev_id, mixer_dev_id);
  378. flush_scheduled_work();
  379. return 0;
  380. }
  381. static int s3c_audio_remove(struct device *_dev)
  382. {
  383. unregister_sound_dsp(audio_dev_id);
  384. unregister_sound_mixer(mixer_dev_id);
  385. return 0;
  386. }
  387. #ifdef CONFIG_S3C64XX_PM
  388. static int s3c64xx_audio_suspend( u32 state)
  389. {
  390. return s3c_audio_suspend(&audio_state, state, SUSPEND_POWER_DOWN);
  391. }
  392. static int s3c64xx_audio_resume()
  393. {
  394. return s3c64xx_audio_resume(&audio_state, RESUME_ENABLE);
  395. }
  396. #endif
  397. static struct device_driver s3c_iis_driver = {
  398. .name = "s3c2410-iis",
  399. .bus = &platform_bus_type,
  400. .probe = s3c_audio_probe,
  401. .remove = s3c_audio_remove,
  402. #ifdef CONFIG_S3C64XX_PM
  403. .suspend = s3c64xx_audio_suspend,
  404. .resume = s3c64xx_audio_resume,
  405. #endif
  406. };
  407. static int __init s3c_uda1341_init(void)
  408. {
  409. DPRINTK("Sound: %s installed\n", __FUNCTION__);
  410. return driver_register(&s3c_iis_driver);
  411. }
  412. static void s3c_uda1341_exit(void)
  413. {
  414. driver_unregister(&s3c_iis_driver);
  415. }
  416. module_init(s3c_uda1341_init);
  417. module_exit(s3c_uda1341_exit);