ac97.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2015 Michael Gerow
  5. * Copyright (C) 2015-2018 K. Lange
  6. *
  7. * Driver for the Intel AC'97.
  8. *
  9. * See <http://www.intel.com/design/chipsets/manuals/29802801.pdf>.
  10. */
  11. #include <kernel/logging.h>
  12. #include <kernel/mem.h>
  13. #include <kernel/module.h>
  14. #include <kernel/mod/snd.h>
  15. #include <kernel/printf.h>
  16. #include <kernel/pci.h>
  17. #include <kernel/system.h>
  18. /* Utility macros */
  19. #define N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))
  20. /* BARs! */
  21. #define AC97_NAMBAR 0x10 /* Native Audio Mixer Base Address Register */
  22. #define AC97_NABMBAR 0x14 /* Native Audio Bus Mastering Base Address Register */
  23. /* Bus mastering IO port offsets */
  24. #define AC97_PO_BDBAR 0x10 /* PCM out buffer descriptor BAR */
  25. #define AC97_PO_CIV 0x14 /* PCM out current index value */
  26. #define AC97_PO_LVI 0x15 /* PCM out last valid index */
  27. #define AC97_PO_SR 0x16 /* PCM out status register */
  28. #define AC97_PO_PICB 0x18 /* PCM out position in current buffer register */
  29. #define AC97_PO_CR 0x1B /* PCM out control register */
  30. /* Bus mastering misc */
  31. /* Buffer descriptor list constants */
  32. #define AC97_BDL_LEN 32 /* Buffer descriptor list length */
  33. #define AC97_BDL_BUFFER_LEN 0x1000 /* Length of buffer in BDL */
  34. #define AC97_CL_GET_LENGTH(cl) ((cl) & 0xFFFF) /* Decode length from cl */
  35. #define AC97_CL_SET_LENGTH(cl, v) ((cl) = (v) & 0xFFFF) /* Encode length to cl */
  36. #define AC97_CL_BUP ((uint32_t)1 << 30) /* Buffer underrun policy in cl */
  37. #define AC97_CL_IOC ((uint32_t)1 << 31) /* Interrupt on completion flag in cl */
  38. /* PCM out control register flags */
  39. #define AC97_X_CR_RPBM (1 << 0) /* Run/pause bus master */
  40. #define AC97_X_CR_RR (1 << 1) /* Reset registers */
  41. #define AC97_X_CR_LVBIE (1 << 2) /* Last valid buffer interrupt enable */
  42. #define AC97_X_CR_FEIE (1 << 3) /* FIFO error interrupt enable */
  43. #define AC97_X_CR_IOCE (1 << 4) /* Interrupt on completion enable */
  44. /* Status register flags */
  45. #define AC97_X_SR_DCH (1 << 0) /* DMA controller halted */
  46. #define AC97_X_SR_CELV (1 << 1) /* Current equals last valid */
  47. #define AC97_X_SR_LVBCI (1 << 2) /* Last valid buffer completion interrupt */
  48. #define AC97_X_SR_BCIS (1 << 3) /* Buffer completion interrupt status */
  49. #define AC97_X_SR_FIFOE (1 << 4) /* FIFO error */
  50. /* Mixer IO port offsets */
  51. #define AC97_RESET 0x00
  52. #define AC97_MASTER_VOLUME 0x02
  53. #define AC97_AUX_OUT_VOLUME 0x04
  54. #define AC97_MONO_VOLUME 0x06
  55. #define AC97_PCM_OUT_VOLUME 0x18
  56. /* snd values */
  57. #define AC97_SND_NAME "Intel AC'97"
  58. #define AC97_PLAYBACK_SPEED 48000
  59. #define AC97_PLAYBACK_FORMAT SND_FORMAT_L16SLE
  60. /* An entry in a buffer dscriptor list */
  61. typedef struct {
  62. uint32_t pointer; /* Pointer to buffer */
  63. uint32_t cl; /* Control values and buffer length */
  64. } __attribute__((packed)) ac97_bdl_entry_t;
  65. typedef struct {
  66. uint32_t pci_device;
  67. uint16_t nabmbar; /* Native audio bus mastring BAR */
  68. uint16_t nambar; /* Native audio mixing BAR */
  69. size_t irq; /* This ac97's irq */
  70. uint8_t lvi; /* The currently set last valid index */
  71. uint8_t bits; /* How many bits of volume are supported (5 or 6) */
  72. ac97_bdl_entry_t * bdl; /* Buffer descriptor list */
  73. uint16_t * bufs[AC97_BDL_LEN]; /* Virtual addresses for buffers in BDL */
  74. uint32_t bdl_p;
  75. uint32_t mask;
  76. } ac97_device_t;
  77. static ac97_device_t _device;
  78. #define AC97_KNOB_PCM_OUT (SND_KNOB_VENDOR + 0)
  79. static snd_knob_t _knobs[] = {
  80. {
  81. "Master",
  82. SND_KNOB_MASTER
  83. },
  84. {
  85. "PCM Out",
  86. SND_KNOB_VENDOR + 0
  87. }
  88. };
  89. static int ac97_mixer_read(uint32_t knob_id, uint32_t *val);
  90. static int ac97_mixer_write(uint32_t knob_id, uint32_t val);
  91. static snd_device_t _snd = {
  92. .name = AC97_SND_NAME,
  93. .device = &_device,
  94. .playback_speed = AC97_PLAYBACK_SPEED,
  95. .playback_format = AC97_PLAYBACK_FORMAT,
  96. .knobs = _knobs,
  97. .num_knobs = N_ELEMENTS(_knobs),
  98. .mixer_read = ac97_mixer_read,
  99. .mixer_write = ac97_mixer_write,
  100. };
  101. /*
  102. * This could be unnecessary if we instead allocate just two buffers and make
  103. * the ac97 think there are more.
  104. */
  105. static void find_ac97(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * extra) {
  106. ac97_device_t * ac97 = extra;
  107. if ((vendorid == 0x8086) && (deviceid == 0x2415)) {
  108. ac97->pci_device = device;
  109. }
  110. }
  111. #define DIVISION 0x1000
  112. static int irq_handler(struct regs * regs) {
  113. uint16_t sr = inports(_device.nabmbar + AC97_PO_SR);
  114. if (!sr) return 0;
  115. if (sr & AC97_X_SR_BCIS) {
  116. size_t f = (_device.lvi + 2) % AC97_BDL_LEN;
  117. for (size_t i = 0; i < AC97_BDL_BUFFER_LEN * sizeof(*_device.bufs[0]); i += DIVISION) {
  118. snd_request_buf(&_snd, DIVISION, (uint8_t *)_device.bufs[f] + i);
  119. //switch_task(1);
  120. }
  121. _device.lvi = (_device.lvi + 1) % AC97_BDL_LEN;
  122. outportb(_device.nabmbar + AC97_PO_LVI, _device.lvi);
  123. } else if (sr & AC97_X_SR_LVBCI) {
  124. debug_print(NOTICE, "ac97 irq is lvbci");
  125. } else if (sr & AC97_X_SR_FIFOE) {
  126. debug_print(NOTICE, "ac97 irq is fifoe");
  127. } else {
  128. /* don't handle it */
  129. return 0;
  130. }
  131. debug_print(NOTICE, "ac97 status register: 0x%4x", sr);
  132. outports(_device.nabmbar + AC97_PO_SR, sr & 0x1E);
  133. irq_ack(_device.irq);
  134. return 1;
  135. }
  136. /* Currently we just assume right and left are the same */
  137. static int ac97_mixer_read(uint32_t knob_id, uint32_t *val) {
  138. uint16_t tmp;
  139. switch (knob_id) {
  140. case SND_KNOB_MASTER:
  141. tmp = inports(_device.nambar + AC97_MASTER_VOLUME);
  142. if (tmp == 0x8000) {
  143. *val = 0;
  144. } else {
  145. /* 6 bit value */
  146. *val = (tmp & _device.mask) << (sizeof(*val) * 8 - _device.bits);
  147. *val = ~*val;
  148. *val &= (uint32_t)_device.mask << (sizeof(*val) * 8 - _device.bits);
  149. }
  150. break;
  151. case AC97_KNOB_PCM_OUT:
  152. tmp = inports(_device.nambar + AC97_PCM_OUT_VOLUME);
  153. if (tmp == 0x8000) {
  154. *val = 0;
  155. } else {
  156. /* 5 bit value */
  157. *val = (tmp & 0x1f) << (sizeof(*val) * 8 - 5);
  158. *val = ~*val;
  159. *val &= 0x1f << (sizeof(*val) * 8 - 5);
  160. }
  161. break;
  162. default:
  163. return -1;
  164. }
  165. return 0;
  166. }
  167. static int ac97_mixer_write(uint32_t knob_id, uint32_t val) {
  168. switch (knob_id) {
  169. case SND_KNOB_MASTER: {
  170. uint16_t encoded;
  171. if (val == 0x0) {
  172. encoded = 0x8000;
  173. } else {
  174. /* 0 is the highest volume */
  175. val = ~val;
  176. /* 6 bit value */
  177. val >>= (sizeof(val) * 8 - _device.bits);
  178. encoded = (val & 0xFF) | (val << 8);
  179. }
  180. outports(_device.nambar + AC97_MASTER_VOLUME, encoded);
  181. break;
  182. }
  183. case AC97_KNOB_PCM_OUT: {
  184. uint16_t encoded;
  185. if (val == 0x0) {
  186. encoded = 0x8000;
  187. } else {
  188. /* 0 is the highest volume */
  189. val = ~val;
  190. /* 5 bit value */
  191. val >>= (sizeof(val) * 8 - 5);
  192. encoded = (val & 0xFF) | (val << 8);
  193. }
  194. outports(_device.nambar + AC97_PCM_OUT_VOLUME, encoded);
  195. break;
  196. }
  197. default:
  198. return -1;
  199. }
  200. return 0;
  201. }
  202. static int init(void) {
  203. debug_print(NOTICE, "Initializing AC97");
  204. pci_scan(&find_ac97, -1, &_device);
  205. if (!_device.pci_device) {
  206. return 1;
  207. }
  208. _device.nabmbar = pci_read_field(_device.pci_device, AC97_NABMBAR, 2) & ((uint32_t) -1) << 1;
  209. _device.nambar = pci_read_field(_device.pci_device, PCI_BAR0, 4) & ((uint32_t) -1) << 1;
  210. _device.irq = pci_get_interrupt(_device.pci_device);
  211. irq_install_handler(_device.irq, irq_handler, "ac97");
  212. /* Enable all matter of interrupts */
  213. outportb(_device.nabmbar + AC97_PO_CR, AC97_X_CR_FEIE | AC97_X_CR_IOCE);
  214. /* Enable bus mastering and disable memory mapped space */
  215. pci_write_field(_device.pci_device, PCI_COMMAND, 2, 0x5);
  216. /* Default the PCM output to full volume. */
  217. outports(_device.nambar + AC97_PCM_OUT_VOLUME, 0x0000);
  218. /* Allocate our BDL and our buffers */
  219. _device.bdl = (void *)kmalloc_p(AC97_BDL_LEN * sizeof(*_device.bdl), &_device.bdl_p);
  220. memset(_device.bdl, 0, AC97_BDL_LEN * sizeof(*_device.bdl));
  221. for (int i = 0; i < AC97_BDL_LEN; i++) {
  222. _device.bufs[i] = (uint16_t *)kmalloc_p(AC97_BDL_BUFFER_LEN * sizeof(*_device.bufs[0]),
  223. &_device.bdl[i].pointer);
  224. memset(_device.bufs[i], 0, AC97_BDL_BUFFER_LEN * sizeof(*_device.bufs[0]));
  225. AC97_CL_SET_LENGTH(_device.bdl[i].cl, AC97_BDL_BUFFER_LEN);
  226. /* Set all buffers to interrupt */
  227. _device.bdl[i].cl |= AC97_CL_IOC;
  228. }
  229. /* Tell the ac97 where our BDL is */
  230. outportl(_device.nabmbar + AC97_PO_BDBAR, _device.bdl_p);
  231. /* Set the LVI to be the last index */
  232. _device.lvi = 2;
  233. outportb(_device.nabmbar + AC97_PO_LVI, _device.lvi);
  234. /* detect whether device supports MSB */
  235. outports(_device.nambar + AC97_MASTER_VOLUME, 0x2020);
  236. uint16_t t = inports(_device.nambar + AC97_MASTER_VOLUME) & 0x1f;
  237. if (t == 0x1f) {
  238. debug_print(WARNING, "This device only supports 5 bits of audio volume.");
  239. _device.bits = 5;
  240. _device.mask = 0x1f;
  241. outports(_device.nambar + AC97_MASTER_VOLUME, 0x0f0f);
  242. } else {
  243. _device.bits = 6;
  244. _device.mask = 0x3f;
  245. outports(_device.nambar + AC97_MASTER_VOLUME, 0x1f1f);
  246. }
  247. snd_register(&_snd);
  248. /* Start things playing */
  249. outportb(_device.nabmbar + AC97_PO_CR, inportb(_device.nabmbar + AC97_PO_CR) | AC97_X_CR_RPBM);
  250. debug_print(NOTICE, "AC97 initialized successfully");
  251. return 0;
  252. }
  253. static int fini(void) {
  254. snd_unregister(&_snd);
  255. free(_device.bdl);
  256. for (int i = 0; i < AC97_BDL_LEN; i++) {
  257. free(_device.bufs[i]);
  258. }
  259. return 0;
  260. }
  261. MODULE_DEF(ac97, init, fini);
  262. MODULE_DEPENDS(snd);