dmasound_paula.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:19k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/sound/dmasound/dmasound_paula.c
  3.  *
  4.  *  Amiga `Paula' DMA Sound Driver
  5.  *
  6.  *  See linux/drivers/sound/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 <asm/uaccess.h>
  23. #include <asm/setup.h>
  24. #include <asm/amigahw.h>
  25. #include <asm/amigaints.h>
  26. #include <asm/machdep.h>
  27. #include "dmasound.h"
  28. #define DMASOUND_PAULA_REVISION 0
  29. #define DMASOUND_PAULA_EDITION 4
  30.    /*
  31.     * The minimum period for audio depends on htotal (for OCS/ECS/AGA)
  32.     * (Imported from arch/m68k/amiga/amisound.c)
  33.     */
  34. extern volatile u_short amiga_audio_min_period;
  35.    /*
  36.     * amiga_mksound() should be able to restore the period after beeping
  37.     * (Imported from arch/m68k/amiga/amisound.c)
  38.     */
  39. extern u_short amiga_audio_period;
  40.    /*
  41.     * Audio DMA masks
  42.     */
  43. #define AMI_AUDIO_OFF (DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3)
  44. #define AMI_AUDIO_8 (DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1)
  45. #define AMI_AUDIO_14 (AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3)
  46.     /*
  47.      *  Helper pointers for 16(14)-bit sound
  48.      */
  49. static int write_sq_block_size_half, write_sq_block_size_quarter;
  50. /*** Low level stuff *********************************************************/
  51. static void AmiOpen(void);
  52. static void AmiRelease(void);
  53. static void *AmiAlloc(unsigned int size, int 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 void 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 void 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 *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 *userPtr, size_t userCount,
  155. u_char frame[], ssize_t *frameUsed,
  156. ssize_t frameLeft)
  157. {
  158. ssize_t count, used;
  159. if (!dmasound.soft.stereo) {
  160. u_char *p = &frame[*frameUsed];
  161. count = min_t(size_t, userCount, frameLeft) & ~1;
  162. used = count;
  163. while (count > 0) {
  164. u_char data;
  165. if (get_user(data, userPtr++))
  166. return -EFAULT;
  167. *p++ = convsample(data);
  168. count--;
  169. }
  170. } else {
  171. u_char *left = &frame[*frameUsed>>1];
  172. u_char *right = left+write_sq_block_size_half;
  173. count = min_t(size_t, userCount, frameLeft)>>1 & ~1;
  174. used = count*2;
  175. while (count > 0) {
  176. u_char data;
  177. if (get_user(data, userPtr++))
  178. return -EFAULT;
  179. *left++ = convsample(data);
  180. if (get_user(data, userPtr++))
  181. return -EFAULT;
  182. *right++ = convsample(data);
  183. count--;
  184. }
  185. }
  186. *frameUsed += used;
  187. return used;
  188. }
  189. #define AMI_CT_ULAW(x) (dmasound_ulaw2dma8[(x)])
  190. #define AMI_CT_ALAW(x) (dmasound_alaw2dma8[(x)])
  191. #define AMI_CT_U8(x) ((x) ^ 0x80)
  192. GENERATE_AMI_CT8(ami_ct_ulaw, AMI_CT_ULAW)
  193. GENERATE_AMI_CT8(ami_ct_alaw, AMI_CT_ALAW)
  194. GENERATE_AMI_CT8(ami_ct_u8, AMI_CT_U8)
  195.     /*
  196.      *  Copy and convert 16 bit data
  197.      */
  198. #define GENERATE_AMI_CT_16(funcname, convsample)
  199. static ssize_t funcname(const u_char *userPtr, size_t userCount,
  200. u_char frame[], ssize_t *frameUsed,
  201. ssize_t frameLeft)
  202. {
  203. ssize_t count, used;
  204. u_short data;
  205. if (!dmasound.soft.stereo) {
  206. u_char *high = &frame[*frameUsed>>1];
  207. u_char *low = high+write_sq_block_size_half;
  208. count = min_t(size_t, userCount, frameLeft)>>1 & ~1;
  209. used = count*2;
  210. while (count > 0) {
  211. if (get_user(data, ((u_short *)userPtr)++))
  212. return -EFAULT;
  213. data = convsample(data);
  214. *high++ = data>>8;
  215. *low++ = (data>>2) & 0x3f;
  216. count--;
  217. }
  218. } else {
  219. u_char *lefth = &frame[*frameUsed>>2];
  220. u_char *leftl = lefth+write_sq_block_size_quarter;
  221. u_char *righth = lefth+write_sq_block_size_half;
  222. u_char *rightl = righth+write_sq_block_size_quarter;
  223. count = min_t(size_t, userCount, frameLeft)>>2 & ~1;
  224. used = count*4;
  225. while (count > 0) {
  226. if (get_user(data, ((u_short *)userPtr)++))
  227. return -EFAULT;
  228. data = convsample(data);
  229. *lefth++ = data>>8;
  230. *leftl++ = (data>>2) & 0x3f;
  231. if (get_user(data, ((u_short *)userPtr)++))
  232. return -EFAULT;
  233. data = convsample(data);
  234. *righth++ = data>>8;
  235. *rightl++ = (data>>2) & 0x3f;
  236. count--;
  237. }
  238. }
  239. *frameUsed += used;
  240. return used;
  241. }
  242. #define AMI_CT_S16BE(x) (x)
  243. #define AMI_CT_U16BE(x) ((x) ^ 0x8000)
  244. #define AMI_CT_S16LE(x) (le2be16((x)))
  245. #define AMI_CT_U16LE(x) (le2be16((x)) ^ 0x8000)
  246. GENERATE_AMI_CT_16(ami_ct_s16be, AMI_CT_S16BE)
  247. GENERATE_AMI_CT_16(ami_ct_u16be, AMI_CT_U16BE)
  248. GENERATE_AMI_CT_16(ami_ct_s16le, AMI_CT_S16LE)
  249. GENERATE_AMI_CT_16(ami_ct_u16le, AMI_CT_U16LE)
  250. static TRANS transAmiga = {
  251. ct_ulaw: ami_ct_ulaw,
  252. ct_alaw: ami_ct_alaw,
  253. ct_s8: ami_ct_s8,
  254. ct_u8: ami_ct_u8,
  255. ct_s16be: ami_ct_s16be,
  256. ct_u16be: ami_ct_u16be,
  257. ct_s16le: ami_ct_s16le,
  258. ct_u16le: ami_ct_u16le,
  259. };
  260. /*** Low level stuff *********************************************************/
  261. static void AmiOpen(void)
  262. {
  263. MOD_INC_USE_COUNT;
  264. }
  265. static void AmiRelease(void)
  266. {
  267. MOD_DEC_USE_COUNT;
  268. }
  269. static inline void StopDMA(void)
  270. {
  271. custom.aud[0].audvol = custom.aud[1].audvol = 0;
  272. custom.aud[2].audvol = custom.aud[3].audvol = 0;
  273. custom.dmacon = AMI_AUDIO_OFF;
  274. enable_heartbeat();
  275. }
  276. static void *AmiAlloc(unsigned int size, int flags)
  277. {
  278. return amiga_chip_alloc((long)size, "dmasound [Paula]");
  279. }
  280. static void AmiFree(void *obj, unsigned int size)
  281. {
  282. amiga_chip_free (obj);
  283. }
  284. static int __init AmiIrqInit(void)
  285. {
  286. /* turn off DMA for audio channels */
  287. StopDMA();
  288. /* Register interrupt handler. */
  289. if (request_irq(IRQ_AMIGA_AUD0, AmiInterrupt, 0, "DMA sound",
  290. AmiInterrupt))
  291. return 0;
  292. return 1;
  293. }
  294. #ifdef MODULE
  295. static void AmiIrqCleanUp(void)
  296. {
  297. /* turn off DMA for audio channels */
  298. StopDMA();
  299. /* release the interrupt */
  300. free_irq(IRQ_AMIGA_AUD0, AmiInterrupt);
  301. }
  302. #endif /* MODULE */
  303. static void AmiSilence(void)
  304. {
  305. /* turn off DMA for audio channels */
  306. StopDMA();
  307. }
  308. static void AmiInit(void)
  309. {
  310. int period, i;
  311. AmiSilence();
  312. if (dmasound.soft.speed)
  313. period = amiga_colorclock/dmasound.soft.speed-1;
  314. else
  315. period = amiga_audio_min_period;
  316. dmasound.hard = dmasound.soft;
  317. dmasound.trans_write = &transAmiga;
  318. if (period < amiga_audio_min_period) {
  319. /* we would need to squeeze the sound, but we won't do that */
  320. period = amiga_audio_min_period;
  321. } else if (period > 65535) {
  322. period = 65535;
  323. }
  324. dmasound.hard.speed = amiga_colorclock/(period+1);
  325. for (i = 0; i < 4; i++)
  326. custom.aud[i].audper = period;
  327. amiga_audio_period = period;
  328. }
  329. static int AmiSetFormat(int format)
  330. {
  331. int size;
  332. /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */
  333. switch (format) {
  334. case AFMT_QUERY:
  335. return dmasound.soft.format;
  336. case AFMT_MU_LAW:
  337. case AFMT_A_LAW:
  338. case AFMT_U8:
  339. case AFMT_S8:
  340. size = 8;
  341. break;
  342. case AFMT_S16_BE:
  343. case AFMT_U16_BE:
  344. case AFMT_S16_LE:
  345. case AFMT_U16_LE:
  346. size = 16;
  347. break;
  348. default: /* :-) */
  349. size = 8;
  350. format = AFMT_S8;
  351. }
  352. dmasound.soft.format = format;
  353. dmasound.soft.size = size;
  354. if (dmasound.minDev == SND_DEV_DSP) {
  355. dmasound.dsp.format = format;
  356. dmasound.dsp.size = dmasound.soft.size;
  357. }
  358. AmiInit();
  359. return format;
  360. }
  361. #define VOLUME_VOXWARE_TO_AMI(v) 
  362. (((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100)
  363. #define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64)
  364. static int AmiSetVolume(int volume)
  365. {
  366. dmasound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff);
  367. custom.aud[0].audvol = dmasound.volume_left;
  368. dmasound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);
  369. custom.aud[1].audvol = dmasound.volume_right;
  370. if (dmasound.hard.size == 16) {
  371. if (dmasound.volume_left == 64 && dmasound.volume_right == 64) {
  372. custom.aud[2].audvol = 1;
  373. custom.aud[3].audvol = 1;
  374. } else {
  375. custom.aud[2].audvol = 0;
  376. custom.aud[3].audvol = 0;
  377. }
  378. }
  379. return VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) |
  380.        (VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8);
  381. }
  382. static int AmiSetTreble(int treble)
  383. {
  384. dmasound.treble = treble;
  385. if (treble < 50)
  386. ciaa.pra &= ~0x02;
  387. else
  388. ciaa.pra |= 0x02;
  389. return treble;
  390. }
  391. #define AMI_PLAY_LOADED 1
  392. #define AMI_PLAY_PLAYING 2
  393. #define AMI_PLAY_MASK 3
  394. static void AmiPlayNextFrame(int index)
  395. {
  396. u_char *start, *ch0, *ch1, *ch2, *ch3;
  397. u_long size;
  398. /* used by AmiPlay() if all doubts whether there really is something
  399.  * to be played are already wiped out.
  400.  */
  401. start = write_sq.buffers[write_sq.front];
  402. size = (write_sq.count == index ? write_sq.rear_size
  403. : write_sq.block_size)>>1;
  404. if (dmasound.hard.stereo) {
  405. ch0 = start;
  406. ch1 = start+write_sq_block_size_half;
  407. size >>= 1;
  408. } else {
  409. ch0 = start;
  410. ch1 = start;
  411. }
  412. disable_heartbeat();
  413. custom.aud[0].audvol = dmasound.volume_left;
  414. custom.aud[1].audvol = dmasound.volume_right;
  415. if (dmasound.hard.size == 8) {
  416. custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
  417. custom.aud[0].audlen = size;
  418. custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
  419. custom.aud[1].audlen = size;
  420. custom.dmacon = AMI_AUDIO_8;
  421. } else {
  422. size >>= 1;
  423. custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
  424. custom.aud[0].audlen = size;
  425. custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
  426. custom.aud[1].audlen = size;
  427. if (dmasound.volume_left == 64 && dmasound.volume_right == 64) {
  428. /* We can play pseudo 14-bit only with the maximum volume */
  429. ch3 = ch0+write_sq_block_size_quarter;
  430. ch2 = ch1+write_sq_block_size_quarter;
  431. custom.aud[2].audvol = 1;  /* we are being affected by the beeps */
  432. custom.aud[3].audvol = 1;  /* restoring volume here helps a bit */
  433. custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2);
  434. custom.aud[2].audlen = size;
  435. custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);
  436. custom.aud[3].audlen = size;
  437. custom.dmacon = AMI_AUDIO_14;
  438. } else {
  439. custom.aud[2].audvol = 0;
  440. custom.aud[3].audvol = 0;
  441. custom.dmacon = AMI_AUDIO_8;
  442. }
  443. }
  444. write_sq.front = (write_sq.front+1) % write_sq.max_count;
  445. write_sq.active |= AMI_PLAY_LOADED;
  446. }
  447. static void AmiPlay(void)
  448. {
  449. int minframes = 1;
  450. custom.intena = IF_AUD0;
  451. if (write_sq.active & AMI_PLAY_LOADED) {
  452. /* There's already a frame loaded */
  453. custom.intena = IF_SETCLR | IF_AUD0;
  454. return;
  455. }
  456. if (write_sq.active & AMI_PLAY_PLAYING)
  457. /* Increase threshold: frame 1 is already being played */
  458. minframes = 2;
  459. if (write_sq.count < minframes) {
  460. /* Nothing to do */
  461. custom.intena = IF_SETCLR | IF_AUD0;
  462. return;
  463. }
  464. if (write_sq.count <= minframes &&
  465.     write_sq.rear_size < write_sq.block_size && !write_sq.syncing) {
  466. /* hmmm, the only existing frame is not
  467.  * yet filled and we're not syncing?
  468.  */
  469. custom.intena = IF_SETCLR | IF_AUD0;
  470. return;
  471. }
  472. AmiPlayNextFrame(minframes);
  473. custom.intena = IF_SETCLR | IF_AUD0;
  474. }
  475. static void AmiInterrupt(int irq, void *dummy, struct pt_regs *fp)
  476. {
  477. int minframes = 1;
  478. custom.intena = IF_AUD0;
  479. if (!write_sq.active) {
  480. /* Playing was interrupted and sq_reset() has already cleared
  481.  * the sq variables, so better don't do anything here.
  482.  */
  483. WAKE_UP(write_sq.sync_queue);
  484. return;
  485. }
  486. if (write_sq.active & AMI_PLAY_PLAYING) {
  487. /* We've just finished a frame */
  488. write_sq.count--;
  489. WAKE_UP(write_sq.action_queue);
  490. }
  491. if (write_sq.active & AMI_PLAY_LOADED)
  492. /* Increase threshold: frame 1 is already being played */
  493. minframes = 2;
  494. /* Shift the flags */
  495. write_sq.active = (write_sq.active<<1) & AMI_PLAY_MASK;
  496. if (!write_sq.active)
  497. /* No frame is playing, disable audio DMA */
  498. StopDMA();
  499. custom.intena = IF_SETCLR | IF_AUD0;
  500. if (write_sq.count >= minframes)
  501. /* Try to play the next frame */
  502. AmiPlay();
  503. if (!write_sq.active)
  504. /* Nothing to play anymore.
  505.    Wake up a process waiting for audio output to drain. */
  506. WAKE_UP(write_sq.sync_queue);
  507. }
  508. /*** Mid level stuff *********************************************************/
  509. /*
  510.  * /dev/mixer abstraction
  511.  */
  512. static void __init AmiMixerInit(void)
  513. {
  514. dmasound.volume_left = 64;
  515. dmasound.volume_right = 64;
  516. custom.aud[0].audvol = dmasound.volume_left;
  517. custom.aud[3].audvol = 1; /* For pseudo 14bit */
  518. custom.aud[1].audvol = dmasound.volume_right;
  519. custom.aud[2].audvol = 1; /* For pseudo 14bit */
  520. dmasound.treble = 50;
  521. }
  522. static int AmiMixerIoctl(u_int cmd, u_long arg)
  523. {
  524. int data;
  525. switch (cmd) {
  526.     case SOUND_MIXER_READ_DEVMASK:
  527.     return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE);
  528.     case SOUND_MIXER_READ_RECMASK:
  529.     return IOCTL_OUT(arg, 0);
  530.     case SOUND_MIXER_READ_STEREODEVS:
  531.     return IOCTL_OUT(arg, SOUND_MASK_VOLUME);
  532.     case SOUND_MIXER_READ_VOLUME:
  533.     return IOCTL_OUT(arg,
  534.     VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) |
  535.     VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8);
  536.     case SOUND_MIXER_WRITE_VOLUME:
  537.     IOCTL_IN(arg, data);
  538.     return IOCTL_OUT(arg, dmasound_set_volume(data));
  539.     case SOUND_MIXER_READ_TREBLE:
  540.     return IOCTL_OUT(arg, dmasound.treble);
  541.     case SOUND_MIXER_WRITE_TREBLE:
  542.     IOCTL_IN(arg, data);
  543.     return IOCTL_OUT(arg, dmasound_set_treble(data));
  544. }
  545. return -EINVAL;
  546. }
  547. static void AmiWriteSqSetup(void)
  548. {
  549. write_sq_block_size_half = write_sq.block_size>>1;
  550. write_sq_block_size_quarter = write_sq_block_size_half>>1;
  551. }
  552. static int AmiStateInfo(char *buffer, size_t space)
  553. {
  554. int len = 0;
  555. len += sprintf(buffer+len, "tsound.volume_left = %d [0...64]n",
  556.        dmasound.volume_left);
  557. len += sprintf(buffer+len, "tsound.volume_right = %d [0...64]n",
  558.        dmasound.volume_right);
  559. if (len >= space) {
  560. printk(KERN_ERR "dmasound_paula: overlowed state buffer alloc.n") ;
  561. len = space ;
  562. }
  563. return len;
  564. }
  565. /*** Machine definitions *****************************************************/
  566. static SETTINGS def_hard = {
  567. format: AFMT_S8,
  568. stereo: 0,
  569. size: 8,
  570. speed: 8000
  571. } ;
  572. static SETTINGS def_soft = {
  573. format: AFMT_U8,
  574. stereo: 0,
  575. size: 8,
  576. speed: 8000
  577. } ;
  578. static MACHINE machAmiga = {
  579. name: "Amiga",
  580. name2: "AMIGA",
  581. open: AmiOpen,
  582. release: AmiRelease,
  583. dma_alloc: AmiAlloc,
  584. dma_free: AmiFree,
  585. irqinit: AmiIrqInit,
  586. #ifdef MODULE
  587. irqcleanup: AmiIrqCleanUp,
  588. #endif /* MODULE */
  589. init: AmiInit,
  590. silence: AmiSilence,
  591. setFormat: AmiSetFormat,
  592. setVolume: AmiSetVolume,
  593. setTreble: AmiSetTreble,
  594. play: AmiPlay,
  595. mixer_init: AmiMixerInit,
  596. mixer_ioctl: AmiMixerIoctl,
  597. write_sq_setup: AmiWriteSqSetup,
  598. state_info: AmiStateInfo,
  599. min_dsp_speed: 8000,
  600. version: ((DMASOUND_PAULA_REVISION<<8) | DMASOUND_PAULA_EDITION),
  601. hardware_afmts: (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */
  602.         capabilities:   DSP_CAP_BATCH          /* As per SNDCTL_DSP_GETCAPS */
  603. };
  604. /*** Config & Setup **********************************************************/
  605. int __init dmasound_paula_init(void)
  606. {
  607. int err;
  608. if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_AUDIO)) {
  609.     if (!request_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40,
  610.     "dmasound [Paula]"))
  611. return -EBUSY;
  612.     dmasound.mach = machAmiga;
  613.     dmasound.mach.default_hard = def_hard ;
  614.     dmasound.mach.default_soft = def_soft ;
  615.     err = dmasound_init();
  616.     if (err)
  617. release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);
  618.     return err;
  619. } else
  620.     return -ENODEV;
  621. }
  622. static void __exit dmasound_paula_cleanup(void)
  623. {
  624. dmasound_deinit();
  625. release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);
  626. }
  627. module_init(dmasound_paula_init);
  628. module_exit(dmasound_paula_cleanup);
  629. MODULE_LICENSE("GPL");