txx9aclc-ac97.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * TXx9 ACLC AC97 driver
  3. *
  4. * Copyright (C) 2009 Atsushi Nemoto
  5. *
  6. * Based on RBTX49xx patch from CELF patch archive.
  7. * (C) Copyright TOSHIBA CORPORATION 2004-2006
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. #include <linux/init.h>
  14. #include <linux/module.h>
  15. #include <linux/delay.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/io.h>
  18. #include <linux/gfp.h>
  19. #include <sound/core.h>
  20. #include <sound/pcm.h>
  21. #include <sound/soc.h>
  22. #include "txx9aclc.h"
  23. #define AC97_DIR \
  24. (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
  25. #define AC97_RATES \
  26. SNDRV_PCM_RATE_8000_48000
  27. #ifdef __BIG_ENDIAN
  28. #define AC97_FMTS SNDRV_PCM_FMTBIT_S16_BE
  29. #else
  30. #define AC97_FMTS SNDRV_PCM_FMTBIT_S16_LE
  31. #endif
  32. static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq);
  33. /* REVISIT: How to find txx9aclc_soc_device from snd_ac97? */
  34. static struct txx9aclc_soc_device *txx9aclc_soc_dev;
  35. static int txx9aclc_regready(struct txx9aclc_soc_device *dev)
  36. {
  37. struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
  38. return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY;
  39. }
  40. /* AC97 controller reads codec register */
  41. static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
  42. unsigned short reg)
  43. {
  44. struct txx9aclc_soc_device *dev = txx9aclc_soc_dev;
  45. struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
  46. void __iomem *base = drvdata->base;
  47. u32 dat;
  48. if (!(__raw_readl(base + ACINTSTS) & ACINT_CODECRDY(ac97->num)))
  49. return 0xffff;
  50. reg |= ac97->num << 7;
  51. dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ;
  52. __raw_writel(dat, base + ACREGACC);
  53. __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
  54. if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) {
  55. __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
  56. dev_err(dev->soc_dev.dev, "ac97 read timeout (reg %#x)\n", reg);
  57. dat = 0xffff;
  58. goto done;
  59. }
  60. dat = __raw_readl(base + ACREGACC);
  61. if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) {
  62. dev_err(dev->soc_dev.dev, "reg mismatch %x with %x\n",
  63. dat, reg);
  64. dat = 0xffff;
  65. goto done;
  66. }
  67. dat = (dat >> ACREGACC_DAT_SHIFT) & 0xffff;
  68. done:
  69. __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
  70. return dat;
  71. }
  72. /* AC97 controller writes to codec register */
  73. static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
  74. unsigned short val)
  75. {
  76. struct txx9aclc_soc_device *dev = txx9aclc_soc_dev;
  77. struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
  78. void __iomem *base = drvdata->base;
  79. __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) |
  80. (val << ACREGACC_DAT_SHIFT),
  81. base + ACREGACC);
  82. __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
  83. if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) {
  84. dev_err(dev->soc_dev.dev,
  85. "ac97 write timeout (reg %#x)\n", reg);
  86. }
  87. __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
  88. }
  89. static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97)
  90. {
  91. struct txx9aclc_soc_device *dev = txx9aclc_soc_dev;
  92. struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
  93. void __iomem *base = drvdata->base;
  94. u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY;
  95. __raw_writel(ACCTL_ENLINK, base + ACCTLDIS);
  96. mmiowb();
  97. udelay(1);
  98. __raw_writel(ACCTL_ENLINK, base + ACCTLEN);
  99. /* wait for primary codec ready status */
  100. __raw_writel(ready, base + ACINTEN);
  101. if (!wait_event_timeout(ac97_waitq,
  102. (__raw_readl(base + ACINTSTS) & ready) == ready,
  103. HZ)) {
  104. dev_err(&ac97->dev, "primary codec is not ready "
  105. "(status %#x)\n",
  106. __raw_readl(base + ACINTSTS));
  107. }
  108. __raw_writel(ACINT_REGACCRDY, base + ACINTSTS);
  109. __raw_writel(ready, base + ACINTDIS);
  110. }
  111. /* AC97 controller operations */
  112. struct snd_ac97_bus_ops soc_ac97_ops = {
  113. .read = txx9aclc_ac97_read,
  114. .write = txx9aclc_ac97_write,
  115. .reset = txx9aclc_ac97_cold_reset,
  116. };
  117. EXPORT_SYMBOL_GPL(soc_ac97_ops);
  118. static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id)
  119. {
  120. struct txx9aclc_plat_drvdata *drvdata = dev_id;
  121. void __iomem *base = drvdata->base;
  122. __raw_writel(__raw_readl(base + ACINTMSTS), base + ACINTDIS);
  123. wake_up(&ac97_waitq);
  124. return IRQ_HANDLED;
  125. }
  126. static int txx9aclc_ac97_probe(struct platform_device *pdev,
  127. struct snd_soc_dai *dai)
  128. {
  129. struct snd_soc_device *socdev = platform_get_drvdata(pdev);
  130. struct txx9aclc_soc_device *dev =
  131. container_of(socdev, struct txx9aclc_soc_device, soc_dev);
  132. dev->aclc_pdev = to_platform_device(dai->dev);
  133. txx9aclc_soc_dev = dev;
  134. return 0;
  135. }
  136. static void txx9aclc_ac97_remove(struct platform_device *pdev,
  137. struct snd_soc_dai *dai)
  138. {
  139. struct platform_device *aclc_pdev = to_platform_device(dai->dev);
  140. struct txx9aclc_plat_drvdata *drvdata = platform_get_drvdata(aclc_pdev);
  141. /* disable AC-link */
  142. __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS);
  143. txx9aclc_soc_dev = NULL;
  144. }
  145. struct snd_soc_dai txx9aclc_ac97_dai = {
  146. .name = "txx9aclc_ac97",
  147. .ac97_control = 1,
  148. .probe = txx9aclc_ac97_probe,
  149. .remove = txx9aclc_ac97_remove,
  150. .playback = {
  151. .rates = AC97_RATES,
  152. .formats = AC97_FMTS,
  153. .channels_min = 2,
  154. .channels_max = 2,
  155. },
  156. .capture = {
  157. .rates = AC97_RATES,
  158. .formats = AC97_FMTS,
  159. .channels_min = 2,
  160. .channels_max = 2,
  161. },
  162. };
  163. EXPORT_SYMBOL_GPL(txx9aclc_ac97_dai);
  164. static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
  165. {
  166. struct txx9aclc_plat_drvdata *drvdata;
  167. struct resource *r;
  168. int err;
  169. int irq;
  170. irq = platform_get_irq(pdev, 0);
  171. if (irq < 0)
  172. return irq;
  173. r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  174. if (!r)
  175. return -EBUSY;
  176. if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r),
  177. dev_name(&pdev->dev)))
  178. return -EBUSY;
  179. drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
  180. if (!drvdata)
  181. return -ENOMEM;
  182. platform_set_drvdata(pdev, drvdata);
  183. drvdata->physbase = r->start;
  184. if (sizeof(drvdata->physbase) > sizeof(r->start) &&
  185. r->start >= TXX9_DIRECTMAP_BASE &&
  186. r->start < TXX9_DIRECTMAP_BASE + 0x400000)
  187. drvdata->physbase |= 0xf00000000ull;
  188. drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
  189. if (!drvdata->base)
  190. return -EBUSY;
  191. err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq,
  192. IRQF_DISABLED, dev_name(&pdev->dev), drvdata);
  193. if (err < 0)
  194. return err;
  195. txx9aclc_ac97_dai.dev = &pdev->dev;
  196. return snd_soc_register_dai(&txx9aclc_ac97_dai);
  197. }
  198. static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
  199. {
  200. snd_soc_unregister_dai(&txx9aclc_ac97_dai);
  201. return 0;
  202. }
  203. static struct platform_driver txx9aclc_ac97_driver = {
  204. .probe = txx9aclc_ac97_dev_probe,
  205. .remove = __devexit_p(txx9aclc_ac97_dev_remove),
  206. .driver = {
  207. .name = "txx9aclc-ac97",
  208. .owner = THIS_MODULE,
  209. },
  210. };
  211. static int __init txx9aclc_ac97_init(void)
  212. {
  213. return platform_driver_register(&txx9aclc_ac97_driver);
  214. }
  215. static void __exit txx9aclc_ac97_exit(void)
  216. {
  217. platform_driver_unregister(&txx9aclc_ac97_driver);
  218. }
  219. module_init(txx9aclc_ac97_init);
  220. module_exit(txx9aclc_ac97_exit);
  221. MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
  222. MODULE_DESCRIPTION("TXx9 ACLC AC97 driver");
  223. MODULE_LICENSE("GPL");