ad1848_lib.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /*
  2. * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  3. * Routines for control of AD1848/AD1847/CS4248
  4. *
  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
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. *
  20. */
  21. #define SNDRV_MAIN_OBJECT_FILE
  22. #include <linux/delay.h>
  23. #include <linux/init.h>
  24. #include <linux/interrupt.h>
  25. #include <linux/slab.h>
  26. #include <linux/ioport.h>
  27. #include <sound/core.h>
  28. #include <sound/ad1848.h>
  29. #include <sound/control.h>
  30. #include <sound/tlv.h>
  31. #include <sound/pcm_params.h>
  32. #include <asm/io.h>
  33. #include <asm/dma.h>
  34. MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
  35. MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
  36. MODULE_LICENSE("GPL");
  37. #if 0
  38. #define SNDRV_DEBUG_MCE
  39. #endif
  40. /*
  41. * Some variables
  42. */
  43. static unsigned char snd_ad1848_original_image[16] =
  44. {
  45. 0x00, /* 00 - lic */
  46. 0x00, /* 01 - ric */
  47. 0x9f, /* 02 - la1ic */
  48. 0x9f, /* 03 - ra1ic */
  49. 0x9f, /* 04 - la2ic */
  50. 0x9f, /* 05 - ra2ic */
  51. 0xbf, /* 06 - loc */
  52. 0xbf, /* 07 - roc */
  53. 0x20, /* 08 - dfr */
  54. AD1848_AUTOCALIB, /* 09 - ic */
  55. 0x00, /* 0a - pc */
  56. 0x00, /* 0b - ti */
  57. 0x00, /* 0c - mi */
  58. 0x00, /* 0d - lbc */
  59. 0x00, /* 0e - dru */
  60. 0x00, /* 0f - drl */
  61. };
  62. /*
  63. * Basic I/O functions
  64. */
  65. static void snd_ad1848_wait(struct snd_wss *chip)
  66. {
  67. int timeout;
  68. for (timeout = 250; timeout > 0; timeout--) {
  69. if ((inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) == 0)
  70. break;
  71. udelay(100);
  72. }
  73. }
  74. void snd_ad1848_out(struct snd_wss *chip,
  75. unsigned char reg,
  76. unsigned char value)
  77. {
  78. snd_ad1848_wait(chip);
  79. #ifdef CONFIG_SND_DEBUG
  80. if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT)
  81. snd_printk(KERN_WARNING "auto calibration time out - "
  82. "reg = 0x%x, value = 0x%x\n", reg, value);
  83. #endif
  84. outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL));
  85. outb(chip->image[reg] = value, chip->port + CS4231P(REG));
  86. mb();
  87. snd_printdd("codec out - reg 0x%x = 0x%x\n",
  88. chip->mce_bit | reg, value);
  89. }
  90. EXPORT_SYMBOL(snd_ad1848_out);
  91. static unsigned char snd_ad1848_in(struct snd_wss *chip, unsigned char reg)
  92. {
  93. snd_ad1848_wait(chip);
  94. #ifdef CONFIG_SND_DEBUG
  95. if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT)
  96. snd_printk(KERN_WARNING "auto calibration time out - "
  97. "reg = 0x%x\n", reg);
  98. #endif
  99. outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL));
  100. mb();
  101. return inb(chip->port + CS4231P(REG));
  102. }
  103. #if 0
  104. static void snd_ad1848_debug(struct snd_wss *chip)
  105. {
  106. printk(KERN_DEBUG "AD1848 REGS: INDEX = 0x%02x ", inb(chip->port + CS4231P(REGSEL)));
  107. printk(KERN_DEBUG " STATUS = 0x%02x\n", inb(chip->port + CS4231P(STATUS)));
  108. printk(KERN_DEBUG " 0x00: left input = 0x%02x ", snd_ad1848_in(chip, 0x00));
  109. printk(KERN_DEBUG " 0x08: playback format = 0x%02x\n", snd_ad1848_in(chip, 0x08));
  110. printk(KERN_DEBUG " 0x01: right input = 0x%02x ", snd_ad1848_in(chip, 0x01));
  111. printk(KERN_DEBUG " 0x09: iface (CFIG 1) = 0x%02x\n", snd_ad1848_in(chip, 0x09));
  112. printk(KERN_DEBUG " 0x02: AUXA left = 0x%02x ", snd_ad1848_in(chip, 0x02));
  113. printk(KERN_DEBUG " 0x0a: pin control = 0x%02x\n", snd_ad1848_in(chip, 0x0a));
  114. printk(KERN_DEBUG " 0x03: AUXA right = 0x%02x ", snd_ad1848_in(chip, 0x03));
  115. printk(KERN_DEBUG " 0x0b: init & status = 0x%02x\n", snd_ad1848_in(chip, 0x0b));
  116. printk(KERN_DEBUG " 0x04: AUXB left = 0x%02x ", snd_ad1848_in(chip, 0x04));
  117. printk(KERN_DEBUG " 0x0c: revision & mode = 0x%02x\n", snd_ad1848_in(chip, 0x0c));
  118. printk(KERN_DEBUG " 0x05: AUXB right = 0x%02x ", snd_ad1848_in(chip, 0x05));
  119. printk(KERN_DEBUG " 0x0d: loopback = 0x%02x\n", snd_ad1848_in(chip, 0x0d));
  120. printk(KERN_DEBUG " 0x06: left output = 0x%02x ", snd_ad1848_in(chip, 0x06));
  121. printk(KERN_DEBUG " 0x0e: data upr count = 0x%02x\n", snd_ad1848_in(chip, 0x0e));
  122. printk(KERN_DEBUG " 0x07: right output = 0x%02x ", snd_ad1848_in(chip, 0x07));
  123. printk(KERN_DEBUG " 0x0f: data lwr count = 0x%02x\n", snd_ad1848_in(chip, 0x0f));
  124. }
  125. #endif
  126. /*
  127. * AD1848 detection / MCE routines
  128. */
  129. static void snd_ad1848_mce_up(struct snd_wss *chip)
  130. {
  131. unsigned long flags;
  132. int timeout;
  133. snd_ad1848_wait(chip);
  134. #ifdef CONFIG_SND_DEBUG
  135. if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT)
  136. snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n");
  137. #endif
  138. spin_lock_irqsave(&chip->reg_lock, flags);
  139. chip->mce_bit |= AD1848_MCE;
  140. timeout = inb(chip->port + CS4231P(REGSEL));
  141. if (timeout == 0x80)
  142. snd_printk(KERN_WARNING "mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
  143. if (!(timeout & AD1848_MCE))
  144. outb(chip->mce_bit | (timeout & 0x1f),
  145. chip->port + CS4231P(REGSEL));
  146. spin_unlock_irqrestore(&chip->reg_lock, flags);
  147. }
  148. static void snd_ad1848_mce_down(struct snd_wss *chip)
  149. {
  150. unsigned long flags, timeout;
  151. int reg;
  152. spin_lock_irqsave(&chip->reg_lock, flags);
  153. for (timeout = 5; timeout > 0; timeout--)
  154. inb(chip->port + CS4231P(REGSEL));
  155. /* end of cleanup sequence */
  156. for (timeout = 12000;
  157. timeout > 0 && (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT);
  158. timeout--)
  159. udelay(100);
  160. snd_printdd("(1) timeout = %ld\n", timeout);
  161. #ifdef CONFIG_SND_DEBUG
  162. if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT)
  163. snd_printk(KERN_WARNING
  164. "mce_down [0x%lx] - auto calibration time out (0)\n",
  165. chip->port + CS4231P(REGSEL));
  166. #endif
  167. chip->mce_bit &= ~AD1848_MCE;
  168. reg = inb(chip->port + CS4231P(REGSEL));
  169. outb(chip->mce_bit | (reg & 0x1f), chip->port + CS4231P(REGSEL));
  170. if (reg == 0x80)
  171. snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
  172. if ((reg & AD1848_MCE) == 0) {
  173. spin_unlock_irqrestore(&chip->reg_lock, flags);
  174. return;
  175. }
  176. /*
  177. * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low.
  178. * It may take up to 5 sample periods (at most 907 us @ 5.5125 kHz) for
  179. * the process to _start_, so it is important to wait at least that long
  180. * before checking. Otherwise we might think AC has finished when it
  181. * has in fact not begun. It could take 128 (no AC) or 384 (AC) cycles
  182. * for ACI to drop. This gives a wait of at most 70 ms with a more
  183. * typical value of 3-9 ms.
  184. */
  185. timeout = jiffies + msecs_to_jiffies(250);
  186. do {
  187. spin_unlock_irqrestore(&chip->reg_lock, flags);
  188. msleep(1);
  189. spin_lock_irqsave(&chip->reg_lock, flags);
  190. reg = snd_ad1848_in(chip, AD1848_TEST_INIT) &
  191. AD1848_CALIB_IN_PROGRESS;
  192. } while (reg && time_before(jiffies, timeout));
  193. spin_unlock_irqrestore(&chip->reg_lock, flags);
  194. if (reg)
  195. snd_printk(KERN_ERR
  196. "mce_down - auto calibration time out (2)\n");
  197. snd_printdd("(4) jiffies = %lu\n", jiffies);
  198. snd_printd("mce_down - exit = 0x%x\n",
  199. inb(chip->port + CS4231P(REGSEL)));
  200. }
  201. static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id)
  202. {
  203. struct snd_wss *chip = dev_id;
  204. if ((chip->mode & WSS_MODE_PLAY) && chip->playback_substream)
  205. snd_pcm_period_elapsed(chip->playback_substream);
  206. if ((chip->mode & WSS_MODE_RECORD) && chip->capture_substream)
  207. snd_pcm_period_elapsed(chip->capture_substream);
  208. outb(0, chip->port + CS4231P(STATUS)); /* clear global interrupt bit */
  209. return IRQ_HANDLED;
  210. }
  211. /*
  212. */
  213. static void snd_ad1848_thinkpad_twiddle(struct snd_wss *chip, int on)
  214. {
  215. int tmp;
  216. if (!chip->thinkpad_flag) return;
  217. outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
  218. tmp = inb(AD1848_THINKPAD_CTL_PORT2);
  219. if (on)
  220. /* turn it on */
  221. tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
  222. else
  223. /* turn it off */
  224. tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
  225. outb(tmp, AD1848_THINKPAD_CTL_PORT2);
  226. }
  227. #ifdef CONFIG_PM
  228. static void snd_ad1848_suspend(struct snd_wss *chip)
  229. {
  230. snd_pcm_suspend_all(chip->pcm);
  231. if (chip->thinkpad_flag)
  232. snd_ad1848_thinkpad_twiddle(chip, 0);
  233. }
  234. static void snd_ad1848_resume(struct snd_wss *chip)
  235. {
  236. int i;
  237. if (chip->thinkpad_flag)
  238. snd_ad1848_thinkpad_twiddle(chip, 1);
  239. /* clear any pendings IRQ */
  240. inb(chip->port + CS4231P(STATUS));
  241. outb(0, chip->port + CS4231P(STATUS));
  242. mb();
  243. snd_ad1848_mce_down(chip);
  244. for (i = 0; i < 16; i++)
  245. snd_ad1848_out(chip, i, chip->image[i]);
  246. snd_ad1848_mce_up(chip);
  247. snd_ad1848_mce_down(chip);
  248. }
  249. #endif /* CONFIG_PM */
  250. static int snd_ad1848_probe(struct snd_wss *chip)
  251. {
  252. unsigned long flags;
  253. int i, id, rev, ad1847;
  254. unsigned char *ptr;
  255. #if 0
  256. snd_ad1848_debug(chip);
  257. #endif
  258. id = ad1847 = 0;
  259. for (i = 0; i < 1000; i++) {
  260. mb();
  261. if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT)
  262. udelay(500);
  263. else {
  264. spin_lock_irqsave(&chip->reg_lock, flags);
  265. snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);
  266. snd_ad1848_out(chip, AD1848_LEFT_INPUT, 0xaa);
  267. snd_ad1848_out(chip, AD1848_RIGHT_INPUT, 0x45);
  268. rev = snd_ad1848_in(chip, AD1848_RIGHT_INPUT);
  269. if (rev == 0x65) {
  270. spin_unlock_irqrestore(&chip->reg_lock, flags);
  271. id = 1;
  272. ad1847 = 1;
  273. break;
  274. }
  275. if (snd_ad1848_in(chip, AD1848_LEFT_INPUT) == 0xaa && rev == 0x45) {
  276. spin_unlock_irqrestore(&chip->reg_lock, flags);
  277. id = 1;
  278. break;
  279. }
  280. spin_unlock_irqrestore(&chip->reg_lock, flags);
  281. }
  282. }
  283. if (id != 1)
  284. return -ENODEV; /* no valid device found */
  285. if (chip->hardware == WSS_HW_DETECT) {
  286. if (ad1847) {
  287. chip->hardware = WSS_HW_AD1847;
  288. } else {
  289. chip->hardware = WSS_HW_AD1848;
  290. rev = snd_ad1848_in(chip, AD1848_MISC_INFO);
  291. if (rev & 0x80) {
  292. chip->hardware = WSS_HW_CS4248;
  293. } else if ((rev & 0x0f) == 0x0a) {
  294. snd_ad1848_out(chip, AD1848_MISC_INFO, 0x40);
  295. for (i = 0; i < 16; ++i) {
  296. if (snd_ad1848_in(chip, i) != snd_ad1848_in(chip, i + 16)) {
  297. chip->hardware = WSS_HW_CMI8330;
  298. break;
  299. }
  300. }
  301. snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);
  302. }
  303. }
  304. }
  305. spin_lock_irqsave(&chip->reg_lock, flags);
  306. inb(chip->port + CS4231P(STATUS)); /* clear any pendings IRQ */
  307. outb(0, chip->port + CS4231P(STATUS));
  308. mb();
  309. spin_unlock_irqrestore(&chip->reg_lock, flags);
  310. chip->image[AD1848_MISC_INFO] = 0x00;
  311. chip->image[AD1848_IFACE_CTRL] =
  312. (chip->image[AD1848_IFACE_CTRL] & ~AD1848_SINGLE_DMA) | AD1848_SINGLE_DMA;
  313. ptr = (unsigned char *) &chip->image;
  314. snd_ad1848_mce_down(chip);
  315. spin_lock_irqsave(&chip->reg_lock, flags);
  316. for (i = 0; i < 16; i++) /* ok.. fill all AD1848 registers */
  317. snd_ad1848_out(chip, i, *ptr++);
  318. spin_unlock_irqrestore(&chip->reg_lock, flags);
  319. snd_ad1848_mce_up(chip);
  320. /* init needed for WSS pcm */
  321. spin_lock_irqsave(&chip->reg_lock, flags);
  322. chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE |
  323. AD1848_PLAYBACK_PIO |
  324. AD1848_CAPTURE_ENABLE |
  325. AD1848_CAPTURE_PIO |
  326. AD1848_CALIB_MODE);
  327. chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB;
  328. snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
  329. spin_unlock_irqrestore(&chip->reg_lock, flags);
  330. snd_ad1848_mce_down(chip);
  331. return 0; /* all things are ok.. */
  332. }
  333. /*
  334. */
  335. static int snd_ad1848_free(struct snd_wss *chip)
  336. {
  337. release_and_free_resource(chip->res_port);
  338. if (chip->irq >= 0)
  339. free_irq(chip->irq, (void *) chip);
  340. if (chip->dma1 >= 0) {
  341. snd_dma_disable(chip->dma1);
  342. free_dma(chip->dma1);
  343. }
  344. kfree(chip);
  345. return 0;
  346. }
  347. static int snd_ad1848_dev_free(struct snd_device *device)
  348. {
  349. struct snd_wss *chip = device->device_data;
  350. return snd_ad1848_free(chip);
  351. }
  352. int snd_ad1848_create(struct snd_card *card,
  353. unsigned long port,
  354. int irq, int dma,
  355. unsigned short hardware,
  356. struct snd_wss **rchip)
  357. {
  358. static struct snd_device_ops ops = {
  359. .dev_free = snd_ad1848_dev_free,
  360. };
  361. struct snd_wss *chip;
  362. int err;
  363. *rchip = NULL;
  364. chip = kzalloc(sizeof(*chip), GFP_KERNEL);
  365. if (chip == NULL)
  366. return -ENOMEM;
  367. spin_lock_init(&chip->reg_lock);
  368. chip->card = card;
  369. chip->port = port;
  370. chip->irq = -1;
  371. chip->dma1 = -1;
  372. chip->dma2 = -1;
  373. chip->single_dma = 1;
  374. chip->hardware = hardware;
  375. memcpy(&chip->image, &snd_ad1848_original_image, sizeof(snd_ad1848_original_image));
  376. if ((chip->res_port = request_region(port, 4, "AD1848")) == NULL) {
  377. snd_printk(KERN_ERR "ad1848: can't grab port 0x%lx\n", port);
  378. snd_ad1848_free(chip);
  379. return -EBUSY;
  380. }
  381. if (request_irq(irq, snd_ad1848_interrupt, IRQF_DISABLED, "AD1848", (void *) chip)) {
  382. snd_printk(KERN_ERR "ad1848: can't grab IRQ %d\n", irq);
  383. snd_ad1848_free(chip);
  384. return -EBUSY;
  385. }
  386. chip->irq = irq;
  387. if (request_dma(dma, "AD1848")) {
  388. snd_printk(KERN_ERR "ad1848: can't grab DMA %d\n", dma);
  389. snd_ad1848_free(chip);
  390. return -EBUSY;
  391. }
  392. chip->dma1 = dma;
  393. chip->dma2 = dma;
  394. if (hardware == WSS_HW_THINKPAD) {
  395. chip->thinkpad_flag = 1;
  396. chip->hardware = WSS_HW_DETECT; /* reset */
  397. snd_ad1848_thinkpad_twiddle(chip, 1);
  398. }
  399. if (snd_ad1848_probe(chip) < 0) {
  400. snd_ad1848_free(chip);
  401. return -ENODEV;
  402. }
  403. /* Register device */
  404. if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
  405. snd_ad1848_free(chip);
  406. return err;
  407. }
  408. #ifdef CONFIG_PM
  409. chip->suspend = snd_ad1848_suspend;
  410. chip->resume = snd_ad1848_resume;
  411. #endif
  412. *rchip = chip;
  413. return 0;
  414. }
  415. EXPORT_SYMBOL(snd_ad1848_create);
  416. /*
  417. * INIT part
  418. */
  419. static int __init alsa_ad1848_init(void)
  420. {
  421. return 0;
  422. }
  423. static void __exit alsa_ad1848_exit(void)
  424. {
  425. }
  426. module_init(alsa_ad1848_init)
  427. module_exit(alsa_ad1848_exit)