pdaudiocf_irq.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Driver for Sound Core PDAudioCF soundcard
  4. *
  5. * Copyright (c) 2003 by Jaroslav Kysela <[email protected]>
  6. */
  7. #include <sound/core.h>
  8. #include "pdaudiocf.h"
  9. #include <sound/initval.h>
  10. #include <asm/irq_regs.h>
  11. /*
  12. *
  13. */
  14. irqreturn_t pdacf_interrupt(int irq, void *dev)
  15. {
  16. struct snd_pdacf *chip = dev;
  17. unsigned short stat;
  18. bool wake_thread = false;
  19. if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|
  20. PDAUDIOCF_STAT_IS_CONFIGURED|
  21. PDAUDIOCF_STAT_IS_SUSPENDED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
  22. return IRQ_HANDLED; /* IRQ_NONE here? */
  23. stat = inw(chip->port + PDAUDIOCF_REG_ISR);
  24. if (stat & (PDAUDIOCF_IRQLVL|PDAUDIOCF_IRQOVR)) {
  25. if (stat & PDAUDIOCF_IRQOVR) /* should never happen */
  26. snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n");
  27. if (chip->pcm_substream)
  28. wake_thread = true;
  29. if (!(stat & PDAUDIOCF_IRQAKM))
  30. stat |= PDAUDIOCF_IRQAKM; /* check rate */
  31. }
  32. if (get_irq_regs() != NULL)
  33. snd_ak4117_check_rate_and_errors(chip->ak4117, 0);
  34. return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
  35. }
  36. static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
  37. {
  38. while (size-- > 0) {
  39. *dst++ = inw(rdp_port) ^ xor;
  40. inw(rdp_port);
  41. }
  42. }
  43. static inline void pdacf_transfer_mono32(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
  44. {
  45. register u16 val1, val2;
  46. while (size-- > 0) {
  47. val1 = inw(rdp_port);
  48. val2 = inw(rdp_port);
  49. inw(rdp_port);
  50. *dst++ = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
  51. }
  52. }
  53. static inline void pdacf_transfer_stereo16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
  54. {
  55. while (size-- > 0) {
  56. *dst++ = inw(rdp_port) ^ xor;
  57. *dst++ = inw(rdp_port) ^ xor;
  58. }
  59. }
  60. static inline void pdacf_transfer_stereo32(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
  61. {
  62. register u16 val1, val2, val3;
  63. while (size-- > 0) {
  64. val1 = inw(rdp_port);
  65. val2 = inw(rdp_port);
  66. val3 = inw(rdp_port);
  67. *dst++ = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
  68. *dst++ = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor;
  69. }
  70. }
  71. static inline void pdacf_transfer_mono16sw(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
  72. {
  73. while (size-- > 0) {
  74. *dst++ = swab16(inw(rdp_port) ^ xor);
  75. inw(rdp_port);
  76. }
  77. }
  78. static inline void pdacf_transfer_mono32sw(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
  79. {
  80. register u16 val1, val2;
  81. while (size-- > 0) {
  82. val1 = inw(rdp_port);
  83. val2 = inw(rdp_port);
  84. inw(rdp_port);
  85. *dst++ = swab32((((val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor);
  86. }
  87. }
  88. static inline void pdacf_transfer_stereo16sw(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
  89. {
  90. while (size-- > 0) {
  91. *dst++ = swab16(inw(rdp_port) ^ xor);
  92. *dst++ = swab16(inw(rdp_port) ^ xor);
  93. }
  94. }
  95. static inline void pdacf_transfer_stereo32sw(u32 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
  96. {
  97. register u16 val1, val2, val3;
  98. while (size-- > 0) {
  99. val1 = inw(rdp_port);
  100. val2 = inw(rdp_port);
  101. val3 = inw(rdp_port);
  102. *dst++ = swab32((((val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor);
  103. *dst++ = swab32((((u32)val3 << 16) | (val2 & 0xff00)) ^ xor);
  104. }
  105. }
  106. static inline void pdacf_transfer_mono24le(u8 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
  107. {
  108. register u16 val1, val2;
  109. register u32 xval1;
  110. while (size-- > 0) {
  111. val1 = inw(rdp_port);
  112. val2 = inw(rdp_port);
  113. inw(rdp_port);
  114. xval1 = (((val2 & 0xff) << 8) | (val1 << 16)) ^ xor;
  115. *dst++ = (u8)(xval1 >> 8);
  116. *dst++ = (u8)(xval1 >> 16);
  117. *dst++ = (u8)(xval1 >> 24);
  118. }
  119. }
  120. static inline void pdacf_transfer_mono24be(u8 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
  121. {
  122. register u16 val1, val2;
  123. register u32 xval1;
  124. while (size-- > 0) {
  125. val1 = inw(rdp_port);
  126. val2 = inw(rdp_port);
  127. inw(rdp_port);
  128. xval1 = (((val2 & 0xff) << 8) | (val1 << 16)) ^ xor;
  129. *dst++ = (u8)(xval1 >> 24);
  130. *dst++ = (u8)(xval1 >> 16);
  131. *dst++ = (u8)(xval1 >> 8);
  132. }
  133. }
  134. static inline void pdacf_transfer_stereo24le(u8 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
  135. {
  136. register u16 val1, val2, val3;
  137. register u32 xval1, xval2;
  138. while (size-- > 0) {
  139. val1 = inw(rdp_port);
  140. val2 = inw(rdp_port);
  141. val3 = inw(rdp_port);
  142. xval1 = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
  143. xval2 = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor;
  144. *dst++ = (u8)(xval1 >> 8);
  145. *dst++ = (u8)(xval1 >> 16);
  146. *dst++ = (u8)(xval1 >> 24);
  147. *dst++ = (u8)(xval2 >> 8);
  148. *dst++ = (u8)(xval2 >> 16);
  149. *dst++ = (u8)(xval2 >> 24);
  150. }
  151. }
  152. static inline void pdacf_transfer_stereo24be(u8 *dst, u32 xor, unsigned int size, unsigned long rdp_port)
  153. {
  154. register u16 val1, val2, val3;
  155. register u32 xval1, xval2;
  156. while (size-- > 0) {
  157. val1 = inw(rdp_port);
  158. val2 = inw(rdp_port);
  159. val3 = inw(rdp_port);
  160. xval1 = ((((u32)val2 & 0xff) << 24) | ((u32)val1 << 8)) ^ xor;
  161. xval2 = (((u32)val3 << 16) | (val2 & 0xff00)) ^ xor;
  162. *dst++ = (u8)(xval1 >> 24);
  163. *dst++ = (u8)(xval1 >> 16);
  164. *dst++ = (u8)(xval1 >> 8);
  165. *dst++ = (u8)(xval2 >> 24);
  166. *dst++ = (u8)(xval2 >> 16);
  167. *dst++ = (u8)(xval2 >> 8);
  168. }
  169. }
  170. static void pdacf_transfer(struct snd_pdacf *chip, unsigned int size, unsigned int off)
  171. {
  172. unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD;
  173. unsigned int xor = chip->pcm_xor;
  174. if (chip->pcm_sample == 3) {
  175. if (chip->pcm_little) {
  176. if (chip->pcm_channels == 1) {
  177. pdacf_transfer_mono24le((char *)chip->pcm_area + (off * 3), xor, size, rdp_port);
  178. } else {
  179. pdacf_transfer_stereo24le((char *)chip->pcm_area + (off * 6), xor, size, rdp_port);
  180. }
  181. } else {
  182. if (chip->pcm_channels == 1) {
  183. pdacf_transfer_mono24be((char *)chip->pcm_area + (off * 3), xor, size, rdp_port);
  184. } else {
  185. pdacf_transfer_stereo24be((char *)chip->pcm_area + (off * 6), xor, size, rdp_port);
  186. }
  187. }
  188. return;
  189. }
  190. if (chip->pcm_swab == 0) {
  191. if (chip->pcm_channels == 1) {
  192. if (chip->pcm_frame == 2) {
  193. pdacf_transfer_mono16((u16 *)chip->pcm_area + off, xor, size, rdp_port);
  194. } else {
  195. pdacf_transfer_mono32((u32 *)chip->pcm_area + off, xor, size, rdp_port);
  196. }
  197. } else {
  198. if (chip->pcm_frame == 2) {
  199. pdacf_transfer_stereo16((u16 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
  200. } else {
  201. pdacf_transfer_stereo32((u32 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
  202. }
  203. }
  204. } else {
  205. if (chip->pcm_channels == 1) {
  206. if (chip->pcm_frame == 2) {
  207. pdacf_transfer_mono16sw((u16 *)chip->pcm_area + off, xor, size, rdp_port);
  208. } else {
  209. pdacf_transfer_mono32sw((u32 *)chip->pcm_area + off, xor, size, rdp_port);
  210. }
  211. } else {
  212. if (chip->pcm_frame == 2) {
  213. pdacf_transfer_stereo16sw((u16 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
  214. } else {
  215. pdacf_transfer_stereo32sw((u32 *)chip->pcm_area + (off * 2), xor, size, rdp_port);
  216. }
  217. }
  218. }
  219. }
  220. irqreturn_t pdacf_threaded_irq(int irq, void *dev)
  221. {
  222. struct snd_pdacf *chip = dev;
  223. int size, off, cont, rdp, wdp;
  224. if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
  225. return IRQ_HANDLED;
  226. if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream))
  227. return IRQ_HANDLED;
  228. rdp = inw(chip->port + PDAUDIOCF_REG_RDP);
  229. wdp = inw(chip->port + PDAUDIOCF_REG_WDP);
  230. /* printk(KERN_DEBUG "TASKLET: rdp = %x, wdp = %x\n", rdp, wdp); */
  231. size = wdp - rdp;
  232. if (size < 0)
  233. size += 0x10000;
  234. if (size == 0)
  235. size = 0x10000;
  236. size /= chip->pcm_frame;
  237. if (size > 64)
  238. size -= 32;
  239. #if 0
  240. chip->pcm_hwptr += size;
  241. chip->pcm_hwptr %= chip->pcm_size;
  242. chip->pcm_tdone += size;
  243. if (chip->pcm_frame == 2) {
  244. unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD;
  245. while (size-- > 0) {
  246. inw(rdp_port);
  247. inw(rdp_port);
  248. }
  249. } else {
  250. unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD;
  251. while (size-- > 0) {
  252. inw(rdp_port);
  253. inw(rdp_port);
  254. inw(rdp_port);
  255. }
  256. }
  257. #else
  258. off = chip->pcm_hwptr + chip->pcm_tdone;
  259. off %= chip->pcm_size;
  260. chip->pcm_tdone += size;
  261. while (size > 0) {
  262. cont = chip->pcm_size - off;
  263. if (cont > size)
  264. cont = size;
  265. pdacf_transfer(chip, cont, off);
  266. off += cont;
  267. off %= chip->pcm_size;
  268. size -= cont;
  269. }
  270. #endif
  271. mutex_lock(&chip->reg_lock);
  272. while (chip->pcm_tdone >= chip->pcm_period) {
  273. chip->pcm_hwptr += chip->pcm_period;
  274. chip->pcm_hwptr %= chip->pcm_size;
  275. chip->pcm_tdone -= chip->pcm_period;
  276. mutex_unlock(&chip->reg_lock);
  277. snd_pcm_period_elapsed(chip->pcm_substream);
  278. mutex_lock(&chip->reg_lock);
  279. }
  280. mutex_unlock(&chip->reg_lock);
  281. return IRQ_HANDLED;
  282. }