pdaudiocf_irq.c 9.0 KB

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