dmasound_paula.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. /*
  2. * linux/sound/oss/dmasound/dmasound_paula.c
  3. *
  4. * Amiga `Paula' DMA Sound Driver
  5. *
  6. * See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits
  7. * prior to 28/01/2001
  8. *
  9. * 28/01/2001 [0.1] Iain Sandoe
  10. * - added versioning
  11. * - put in and populated the hardware_afmts field.
  12. * [0.2] - put in SNDCTL_DSP_GETCAPS value.
  13. * [0.3] - put in constraint on state buffer usage.
  14. * [0.4] - put in default hard/soft settings
  15. */
  16. #include <linux/module.h>
  17. #include <linux/config.h>
  18. #include <linux/mm.h>
  19. #include <linux/init.h>
  20. #include <linux/ioport.h>
  21. #include <linux/soundcard.h>
  22. #include <linux/interrupt.h>
  23. #include <asm/uaccess.h>
  24. #include <asm/setup.h>
  25. #include <asm/amigahw.h>
  26. #include <asm/amigaints.h>
  27. #include <asm/machdep.h>
  28. #include "dmasound.h"
  29. #define DMASOUND_PAULA_REVISION 0
  30. #define DMASOUND_PAULA_EDITION 4
  31. #define custom amiga_custom
  32. /*
  33. * The minimum period for audio depends on htotal (for OCS/ECS/AGA)
  34. * (Imported from arch/m68k/amiga/amisound.c)
  35. */
  36. extern volatile u_short amiga_audio_min_period;
  37. /*
  38. * amiga_mksound() should be able to restore the period after beeping
  39. * (Imported from arch/m68k/amiga/amisound.c)
  40. */
  41. extern u_short amiga_audio_period;
  42. /*
  43. * Audio DMA masks
  44. */
  45. #define AMI_AUDIO_OFF (DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3)
  46. #define AMI_AUDIO_8 (DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1)
  47. #define AMI_AUDIO_14 (AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3)
  48. /*
  49. * Helper pointers for 16(14)-bit sound
  50. */
  51. static int write_sq_block_size_half, write_sq_block_size_quarter;
  52. /*** Low level stuff *********************************************************/
  53. static void *AmiAlloc(unsigned int size, gfp_t flags);
  54. static void AmiFree(void *obj, unsigned int size);
  55. static int AmiIrqInit(void);
  56. #ifdef MODULE
  57. static void AmiIrqCleanUp(void);
  58. #endif
  59. static void AmiSilence(void);
  60. static void AmiInit(void);
  61. static int AmiSetFormat(int format);
  62. static int AmiSetVolume(int volume);
  63. static int AmiSetTreble(int treble);
  64. static void AmiPlayNextFrame(int index);
  65. static void AmiPlay(void);
  66. static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp);
  67. #ifdef CONFIG_HEARTBEAT
  68. /*
  69. * Heartbeat interferes with sound since the 7 kHz low-pass filter and the
  70. * power LED are controlled by the same line.
  71. */
  72. #ifdef CONFIG_APUS
  73. #define mach_heartbeat ppc_md.heartbeat
  74. #endif
  75. static void (*saved_heartbeat)(int) = NULL;
  76. static inline void disable_heartbeat(void)
  77. {
  78. if (mach_heartbeat) {
  79. saved_heartbeat = mach_heartbeat;
  80. mach_heartbeat = NULL;
  81. }
  82. AmiSetTreble(dmasound.treble);
  83. }
  84. static inline void enable_heartbeat(void)
  85. {
  86. if (saved_heartbeat)
  87. mach_heartbeat = saved_heartbeat;
  88. }
  89. #else /* !CONFIG_HEARTBEAT */
  90. #define disable_heartbeat() do { } while (0)
  91. #define enable_heartbeat() do { } while (0)
  92. #endif /* !CONFIG_HEARTBEAT */
  93. /*** Mid level stuff *********************************************************/
  94. static void AmiMixerInit(void);
  95. static int AmiMixerIoctl(u_int cmd, u_long arg);
  96. static int AmiWriteSqSetup(void);
  97. static int AmiStateInfo(char *buffer, size_t space);
  98. /*** Translations ************************************************************/
  99. /* ++TeSche: radically changed for new expanding purposes...
  100. *
  101. * These two routines now deal with copying/expanding/translating the samples
  102. * from user space into our buffer at the right frequency. They take care about
  103. * how much data there's actually to read, how much buffer space there is and
  104. * to convert samples into the right frequency/encoding. They will only work on
  105. * complete samples so it may happen they leave some bytes in the input stream
  106. * if the user didn't write a multiple of the current sample size. They both
  107. * return the number of bytes they've used from both streams so you may detect
  108. * such a situation. Luckily all programs should be able to cope with that.
  109. *
  110. * I think I've optimized anything as far as one can do in plain C, all
  111. * variables should fit in registers and the loops are really short. There's
  112. * one loop for every possible situation. Writing a more generalized and thus
  113. * parameterized loop would only produce slower code. Feel free to optimize
  114. * this in assembler if you like. :)
  115. *
  116. * I think these routines belong here because they're not yet really hardware
  117. * independent, especially the fact that the Falcon can play 16bit samples
  118. * only in stereo is hardcoded in both of them!
  119. *
  120. * ++geert: split in even more functions (one per format)
  121. */
  122. /*
  123. * Native format
  124. */
  125. static ssize_t ami_ct_s8(const u_char __user *userPtr, size_t userCount,
  126. u_char frame[], ssize_t *frameUsed, ssize_t frameLeft)
  127. {
  128. ssize_t count, used;
  129. if (!dmasound.soft.stereo) {
  130. void *p = &frame[*frameUsed];
  131. count = min_t(unsigned long, userCount, frameLeft) & ~1;
  132. used = count;
  133. if (copy_from_user(p, userPtr, count))
  134. return -EFAULT;
  135. } else {
  136. u_char *left = &frame[*frameUsed>>1];
  137. u_char *right = left+write_sq_block_size_half;
  138. count = min_t(unsigned long, userCount, frameLeft)>>1 & ~1;
  139. used = count*2;
  140. while (count > 0) {
  141. if (get_user(*left++, userPtr++)
  142. || get_user(*right++, userPtr++))
  143. return -EFAULT;
  144. count--;
  145. }
  146. }
  147. *frameUsed += used;
  148. return used;
  149. }
  150. /*
  151. * Copy and convert 8 bit data
  152. */
  153. #define GENERATE_AMI_CT8(funcname, convsample) \
  154. static ssize_t funcname(const u_char __user *userPtr, size_t userCount, \
  155. u_char frame[], ssize_t *frameUsed, \
  156. ssize_t frameLeft) \
  157. { \
  158. ssize_t count, used; \
  159. \
  160. if (!dmasound.soft.stereo) { \
  161. u_char *p = &frame[*frameUsed]; \
  162. count = min_t(size_t, userCount, frameLeft) & ~1; \
  163. used = count; \
  164. while (count > 0) { \
  165. u_char data; \
  166. if (get_user(data, userPtr++)) \
  167. return -EFAULT; \
  168. *p++ = convsample(data); \
  169. count--; \
  170. } \
  171. } else { \
  172. u_char *left = &frame[*frameUsed>>1]; \
  173. u_char *right = left+write_sq_block_size_half; \
  174. count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \
  175. used = count*2; \
  176. while (count > 0) { \
  177. u_char data; \
  178. if (get_user(data, userPtr++)) \
  179. return -EFAULT; \
  180. *left++ = convsample(data); \
  181. if (get_user(data, userPtr++)) \
  182. return -EFAULT; \
  183. *right++ = convsample(data); \
  184. count--; \
  185. } \
  186. } \
  187. *frameUsed += used; \
  188. return used; \
  189. }
  190. #define AMI_CT_ULAW(x) (dmasound_ulaw2dma8[(x)])
  191. #define AMI_CT_ALAW(x) (dmasound_alaw2dma8[(x)])
  192. #define AMI_CT_U8(x) ((x) ^ 0x80)
  193. GENERATE_AMI_CT8(ami_ct_ulaw, AMI_CT_ULAW)
  194. GENERATE_AMI_CT8(ami_ct_alaw, AMI_CT_ALAW)
  195. GENERATE_AMI_CT8(ami_ct_u8, AMI_CT_U8)
  196. /*
  197. * Copy and convert 16 bit data
  198. */
  199. #define GENERATE_AMI_CT_16(funcname, convsample) \
  200. static ssize_t funcname(const u_char __user *userPtr, size_t userCount, \
  201. u_char frame[], ssize_t *frameUsed, \
  202. ssize_t frameLeft) \
  203. { \
  204. const u_short __user *ptr = (const u_short __user *)userPtr; \
  205. ssize_t count, used; \
  206. u_short data; \
  207. \
  208. if (!dmasound.soft.stereo) { \
  209. u_char *high = &frame[*frameUsed>>1]; \
  210. u_char *low = high+write_sq_block_size_half; \
  211. count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \
  212. used = count*2; \
  213. while (count > 0) { \
  214. if (get_user(data, ptr++)) \
  215. return -EFAULT; \
  216. data = convsample(data); \
  217. *high++ = data>>8; \
  218. *low++ = (data>>2) & 0x3f; \
  219. count--; \
  220. } \
  221. } else { \
  222. u_char *lefth = &frame[*frameUsed>>2]; \
  223. u_char *leftl = lefth+write_sq_block_size_quarter; \
  224. u_char *righth = lefth+write_sq_block_size_half; \
  225. u_char *rightl = righth+write_sq_block_size_quarter; \
  226. count = min_t(size_t, userCount, frameLeft)>>2 & ~1; \
  227. used = count*4; \
  228. while (count > 0) { \
  229. if (get_user(data, ptr++)) \
  230. return -EFAULT; \
  231. data = convsample(data); \
  232. *lefth++ = data>>8; \
  233. *leftl++ = (data>>2) & 0x3f; \
  234. if (get_user(data, ptr++)) \
  235. return -EFAULT; \
  236. data = convsample(data); \
  237. *righth++ = data>>8; \
  238. *rightl++ = (data>>2) & 0x3f; \
  239. count--; \
  240. } \
  241. } \
  242. *frameUsed += used; \
  243. return used; \
  244. }
  245. #define AMI_CT_S16BE(x) (x)
  246. #define AMI_CT_U16BE(x) ((x) ^ 0x8000)
  247. #define AMI_CT_S16LE(x) (le2be16((x)))
  248. #define AMI_CT_U16LE(x) (le2be16((x)) ^ 0x8000)
  249. GENERATE_AMI_CT_16(ami_ct_s16be, AMI_CT_S16BE)
  250. GENERATE_AMI_CT_16(ami_ct_u16be, AMI_CT_U16BE)
  251. GENERATE_AMI_CT_16(ami_ct_s16le, AMI_CT_S16LE)
  252. GENERATE_AMI_CT_16(ami_ct_u16le, AMI_CT_U16LE)
  253. static TRANS transAmiga = {
  254. .ct_ulaw = ami_ct_ulaw,
  255. .ct_alaw = ami_ct_alaw,
  256. .ct_s8 = ami_ct_s8,
  257. .ct_u8 = ami_ct_u8,
  258. .ct_s16be = ami_ct_s16be,
  259. .ct_u16be = ami_ct_u16be,
  260. .ct_s16le = ami_ct_s16le,
  261. .ct_u16le = ami_ct_u16le,
  262. };
  263. /*** Low level stuff *********************************************************/
  264. static inline void StopDMA(void)
  265. {
  266. custom.aud[0].audvol = custom.aud[1].audvol = 0;
  267. custom.aud[2].audvol = custom.aud[3].audvol = 0;
  268. custom.dmacon = AMI_AUDIO_OFF;
  269. enable_heartbeat();
  270. }
  271. static void *AmiAlloc(unsigned int size, gfp_t flags)
  272. {
  273. return amiga_chip_alloc((long)size, "dmasound [Paula]");
  274. }
  275. static void AmiFree(void *obj, unsigned int size)
  276. {
  277. amiga_chip_free (obj);
  278. }
  279. static int __init AmiIrqInit(void)
  280. {
  281. /* turn off DMA for audio channels */
  282. StopDMA();
  283. /* Register interrupt handler. */
  284. if (request_irq(IRQ_AMIGA_AUD0, AmiInterrupt, 0, "DMA sound",
  285. AmiInterrupt))
  286. return 0;
  287. return 1;
  288. }
  289. #ifdef MODULE
  290. static void AmiIrqCleanUp(void)
  291. {
  292. /* turn off DMA for audio channels */
  293. StopDMA();
  294. /* release the interrupt */
  295. free_irq(IRQ_AMIGA_AUD0, AmiInterrupt);
  296. }
  297. #endif /* MODULE */
  298. static void AmiSilence(void)
  299. {
  300. /* turn off DMA for audio channels */
  301. StopDMA();
  302. }
  303. static void AmiInit(void)
  304. {
  305. int period, i;
  306. AmiSilence();
  307. if (dmasound.soft.speed)
  308. period = amiga_colorclock/dmasound.soft.speed-1;
  309. else
  310. period = amiga_audio_min_period;
  311. dmasound.hard = dmasound.soft;
  312. dmasound.trans_write = &transAmiga;
  313. if (period < amiga_audio_min_period) {
  314. /* we would need to squeeze the sound, but we won't do that */
  315. period = amiga_audio_min_period;
  316. } else if (period > 65535) {
  317. period = 65535;
  318. }
  319. dmasound.hard.speed = amiga_colorclock/(period+1);
  320. for (i = 0; i < 4; i++)
  321. custom.aud[i].audper = period;
  322. amiga_audio_period = period;
  323. }
  324. static int AmiSetFormat(int format)
  325. {
  326. int size;
  327. /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */
  328. switch (format) {
  329. case AFMT_QUERY:
  330. return dmasound.soft.format;
  331. case AFMT_MU_LAW:
  332. case AFMT_A_LAW:
  333. case AFMT_U8:
  334. case AFMT_S8:
  335. size = 8;
  336. break;
  337. case AFMT_S16_BE:
  338. case AFMT_U16_BE:
  339. case AFMT_S16_LE:
  340. case AFMT_U16_LE:
  341. size = 16;
  342. break;
  343. default: /* :-) */
  344. size = 8;
  345. format = AFMT_S8;
  346. }
  347. dmasound.soft.format = format;
  348. dmasound.soft.size = size;
  349. if (dmasound.minDev == SND_DEV_DSP) {
  350. dmasound.dsp.format = format;
  351. dmasound.dsp.size = dmasound.soft.size;
  352. }
  353. AmiInit();
  354. return format;
  355. }
  356. #define VOLUME_VOXWARE_TO_AMI(v) \
  357. (((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100)
  358. #define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64)
  359. static int AmiSetVolume(int volume)
  360. {
  361. dmasound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff);
  362. custom.aud[0].audvol = dmasound.volume_left;
  363. dmasound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);
  364. custom.aud[1].audvol = dmasound.volume_right;
  365. if (dmasound.hard.size == 16) {
  366. if (dmasound.volume_left == 64 && dmasound.volume_right == 64) {
  367. custom.aud[2].audvol = 1;
  368. custom.aud[3].audvol = 1;
  369. } else {
  370. custom.aud[2].audvol = 0;
  371. custom.aud[3].audvol = 0;
  372. }
  373. }
  374. return VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) |
  375. (VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8);
  376. }
  377. static int AmiSetTreble(int treble)
  378. {
  379. dmasound.treble = treble;
  380. if (treble < 50)
  381. ciaa.pra &= ~0x02;
  382. else
  383. ciaa.pra |= 0x02;
  384. return treble;
  385. }
  386. #define AMI_PLAY_LOADED 1
  387. #define AMI_PLAY_PLAYING 2
  388. #define AMI_PLAY_MASK 3
  389. static void AmiPlayNextFrame(int index)
  390. {
  391. u_char *start, *ch0, *ch1, *ch2, *ch3;
  392. u_long size;
  393. /* used by AmiPlay() if all doubts whether there really is something
  394. * to be played are already wiped out.
  395. */
  396. start = write_sq.buffers[write_sq.front];
  397. size = (write_sq.count == index ? write_sq.rear_size
  398. : write_sq.block_size)>>1;
  399. if (dmasound.hard.stereo) {
  400. ch0 = start;
  401. ch1 = start+write_sq_block_size_half;
  402. size >>= 1;
  403. } else {
  404. ch0 = start;
  405. ch1 = start;
  406. }
  407. disable_heartbeat();
  408. custom.aud[0].audvol = dmasound.volume_left;
  409. custom.aud[1].audvol = dmasound.volume_right;
  410. if (dmasound.hard.size == 8) {
  411. custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
  412. custom.aud[0].audlen = size;
  413. custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
  414. custom.aud[1].audlen = size;
  415. custom.dmacon = AMI_AUDIO_8;
  416. } else {
  417. size >>= 1;
  418. custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
  419. custom.aud[0].audlen = size;
  420. custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
  421. custom.aud[1].audlen = size;
  422. if (dmasound.volume_left == 64 && dmasound.volume_right == 64) {
  423. /* We can play pseudo 14-bit only with the maximum volume */
  424. ch3 = ch0+write_sq_block_size_quarter;
  425. ch2 = ch1+write_sq_block_size_quarter;
  426. custom.aud[2].audvol = 1; /* we are being affected by the beeps */
  427. custom.aud[3].audvol = 1; /* restoring volume here helps a bit */
  428. custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2);
  429. custom.aud[2].audlen = size;
  430. custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);
  431. custom.aud[3].audlen = size;
  432. custom.dmacon = AMI_AUDIO_14;
  433. } else {
  434. custom.aud[2].audvol = 0;
  435. custom.aud[3].audvol = 0;
  436. custom.dmacon = AMI_AUDIO_8;
  437. }
  438. }
  439. write_sq.front = (write_sq.front+1) % write_sq.max_count;
  440. write_sq.active |= AMI_PLAY_LOADED;
  441. }
  442. static void AmiPlay(void)
  443. {
  444. int minframes = 1;
  445. custom.intena = IF_AUD0;
  446. if (write_sq.active & AMI_PLAY_LOADED) {
  447. /* There's already a frame loaded */
  448. custom.intena = IF_SETCLR | IF_AUD0;
  449. return;
  450. }
  451. if (write_sq.active & AMI_PLAY_PLAYING)
  452. /* Increase threshold: frame 1 is already being played */
  453. minframes = 2;
  454. if (write_sq.count < minframes) {
  455. /* Nothing to do */
  456. custom.intena = IF_SETCLR | IF_AUD0;
  457. return;
  458. }
  459. if (write_sq.count <= minframes &&
  460. write_sq.rear_size < write_sq.block_size && !write_sq.syncing) {
  461. /* hmmm, the only existing frame is not
  462. * yet filled and we're not syncing?
  463. */
  464. custom.intena = IF_SETCLR | IF_AUD0;
  465. return;
  466. }
  467. AmiPlayNextFrame(minframes);
  468. custom.intena = IF_SETCLR | IF_AUD0;
  469. }
  470. static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp)
  471. {
  472. int minframes = 1;
  473. custom.intena = IF_AUD0;
  474. if (!write_sq.active) {
  475. /* Playing was interrupted and sq_reset() has already cleared
  476. * the sq variables, so better don't do anything here.
  477. */
  478. WAKE_UP(write_sq.sync_queue);
  479. return IRQ_HANDLED;
  480. }
  481. if (write_sq.active & AMI_PLAY_PLAYING) {
  482. /* We've just finished a frame */
  483. write_sq.count--;
  484. WAKE_UP(write_sq.action_queue);
  485. }
  486. if (write_sq.active & AMI_PLAY_LOADED)
  487. /* Increase threshold: frame 1 is already being played */
  488. minframes = 2;
  489. /* Shift the flags */
  490. write_sq.active = (write_sq.active<<1) & AMI_PLAY_MASK;
  491. if (!write_sq.active)
  492. /* No frame is playing, disable audio DMA */
  493. StopDMA();
  494. custom.intena = IF_SETCLR | IF_AUD0;
  495. if (write_sq.count >= minframes)
  496. /* Try to play the next frame */
  497. AmiPlay();
  498. if (!write_sq.active)
  499. /* Nothing to play anymore.
  500. Wake up a process waiting for audio output to drain. */
  501. WAKE_UP(write_sq.sync_queue);
  502. return IRQ_HANDLED;
  503. }
  504. /*** Mid level stuff *********************************************************/
  505. /*
  506. * /dev/mixer abstraction
  507. */
  508. static void __init AmiMixerInit(void)
  509. {
  510. dmasound.volume_left = 64;
  511. dmasound.volume_right = 64;
  512. custom.aud[0].audvol = dmasound.volume_left;
  513. custom.aud[3].audvol = 1; /* For pseudo 14bit */
  514. custom.aud[1].audvol = dmasound.volume_right;
  515. custom.aud[2].audvol = 1; /* For pseudo 14bit */
  516. dmasound.treble = 50;
  517. }
  518. static int AmiMixerIoctl(u_int cmd, u_long arg)
  519. {
  520. int data;
  521. switch (cmd) {
  522. case SOUND_MIXER_READ_DEVMASK:
  523. return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE);
  524. case SOUND_MIXER_READ_RECMASK:
  525. return IOCTL_OUT(arg, 0);
  526. case SOUND_MIXER_READ_STEREODEVS:
  527. return IOCTL_OUT(arg, SOUND_MASK_VOLUME);
  528. case SOUND_MIXER_READ_VOLUME:
  529. return IOCTL_OUT(arg,
  530. VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) |
  531. VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8);
  532. case SOUND_MIXER_WRITE_VOLUME:
  533. IOCTL_IN(arg, data);
  534. return IOCTL_OUT(arg, dmasound_set_volume(data));
  535. case SOUND_MIXER_READ_TREBLE:
  536. return IOCTL_OUT(arg, dmasound.treble);
  537. case SOUND_MIXER_WRITE_TREBLE:
  538. IOCTL_IN(arg, data);
  539. return IOCTL_OUT(arg, dmasound_set_treble(data));
  540. }
  541. return -EINVAL;
  542. }
  543. static int AmiWriteSqSetup(void)
  544. {
  545. write_sq_block_size_half = write_sq.block_size>>1;
  546. write_sq_block_size_quarter = write_sq_block_size_half>>1;
  547. return 0;
  548. }
  549. static int AmiStateInfo(char *buffer, size_t space)
  550. {
  551. int len = 0;
  552. len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n",
  553. dmasound.volume_left);
  554. len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n",
  555. dmasound.volume_right);
  556. if (len >= space) {
  557. printk(KERN_ERR "dmasound_paula: overlowed state buffer alloc.\n") ;
  558. len = space ;
  559. }
  560. return len;
  561. }
  562. /*** Machine definitions *****************************************************/
  563. static SETTINGS def_hard = {
  564. .format = AFMT_S8,
  565. .stereo = 0,
  566. .size = 8,
  567. .speed = 8000
  568. } ;
  569. static SETTINGS def_soft = {
  570. .format = AFMT_U8,
  571. .stereo = 0,
  572. .size = 8,
  573. .speed = 8000
  574. } ;
  575. static MACHINE machAmiga = {
  576. .name = "Amiga",
  577. .name2 = "AMIGA",
  578. .owner = THIS_MODULE,
  579. .dma_alloc = AmiAlloc,
  580. .dma_free = AmiFree,
  581. .irqinit = AmiIrqInit,
  582. #ifdef MODULE
  583. .irqcleanup = AmiIrqCleanUp,
  584. #endif /* MODULE */
  585. .init = AmiInit,
  586. .silence = AmiSilence,
  587. .setFormat = AmiSetFormat,
  588. .setVolume = AmiSetVolume,
  589. .setTreble = AmiSetTreble,
  590. .play = AmiPlay,
  591. .mixer_init = AmiMixerInit,
  592. .mixer_ioctl = AmiMixerIoctl,
  593. .write_sq_setup = AmiWriteSqSetup,
  594. .state_info = AmiStateInfo,
  595. .min_dsp_speed = 8000,
  596. .version = ((DMASOUND_PAULA_REVISION<<8) | DMASOUND_PAULA_EDITION),
  597. .hardware_afmts = (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */
  598. .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */
  599. };
  600. /*** Config & Setup **********************************************************/
  601. int __init dmasound_paula_init(void)
  602. {
  603. int err;
  604. if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_AUDIO)) {
  605. if (!request_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40,
  606. "dmasound [Paula]"))
  607. return -EBUSY;
  608. dmasound.mach = machAmiga;
  609. dmasound.mach.default_hard = def_hard ;
  610. dmasound.mach.default_soft = def_soft ;
  611. err = dmasound_init();
  612. if (err)
  613. release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);
  614. return err;
  615. } else
  616. return -ENODEV;
  617. }
  618. static void __exit dmasound_paula_cleanup(void)
  619. {
  620. dmasound_deinit();
  621. release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);
  622. }
  623. module_init(dmasound_paula_init);
  624. module_exit(dmasound_paula_cleanup);
  625. MODULE_LICENSE("GPL");