sgalaxy.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * sound/sgalaxy.c
  3. *
  4. * Low level driver for Aztech Sound Galaxy cards.
  5. * Copyright 1998 Artur Skawina <skawina@geocities.com>
  6. *
  7. * Supported cards:
  8. * Aztech Sound Galaxy Waverider Pro 32 - 3D
  9. * Aztech Sound Galaxy Washington 16
  10. *
  11. * Based on cs4232.c by Hannu Savolainen and Alan Cox.
  12. *
  13. *
  14. * Copyright (C) by Hannu Savolainen 1993-1997
  15. *
  16. * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  17. * Version 2 (June 1991). See the "COPYING" file distributed with this software
  18. * for more info.
  19. *
  20. * Changes:
  21. * 11-10-2000 Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
  22. * Added __init to sb_rst() and sb_cmd()
  23. */
  24. #include <linux/init.h>
  25. #include <linux/module.h>
  26. #include "sound_config.h"
  27. #include "ad1848.h"
  28. static void sleep( unsigned howlong )
  29. {
  30. current->state = TASK_INTERRUPTIBLE;
  31. schedule_timeout(howlong);
  32. }
  33. #define DPORT 0x80
  34. /* Sound Blaster regs */
  35. #define SBDSP_RESET 0x6
  36. #define SBDSP_READ 0xA
  37. #define SBDSP_COMMAND 0xC
  38. #define SBDSP_STATUS SBDSP_COMMAND
  39. #define SBDSP_DATA_AVAIL 0xE
  40. static int __init sb_rst(int base)
  41. {
  42. int i;
  43. outb( 1, base+SBDSP_RESET ); /* reset the DSP */
  44. outb( 0, base+SBDSP_RESET );
  45. for ( i=0; i<500; i++ ) /* delay */
  46. inb(DPORT);
  47. for ( i=0; i<100000; i++ )
  48. {
  49. if ( inb( base+SBDSP_DATA_AVAIL )&0x80 )
  50. break;
  51. }
  52. if ( inb( base+SBDSP_READ )!=0xAA )
  53. return 0;
  54. return 1;
  55. }
  56. static int __init sb_cmd( int base, unsigned char val )
  57. {
  58. int i;
  59. for ( i=100000; i; i-- )
  60. {
  61. if ( (inb( base+SBDSP_STATUS )&0x80)==0 )
  62. {
  63. outb( val, base+SBDSP_COMMAND );
  64. break;
  65. }
  66. }
  67. return i; /* i>0 == success */
  68. }
  69. #define ai_sgbase driver_use_1
  70. static int __init probe_sgalaxy( struct address_info *ai )
  71. {
  72. struct resource *ports;
  73. int n;
  74. if (!request_region(ai->io_base, 4, "WSS config")) {
  75. printk(KERN_ERR "sgalaxy: WSS IO port 0x%03x not available\n", ai->io_base);
  76. return 0;
  77. }
  78. ports = request_region(ai->io_base + 4, 4, "ad1848");
  79. if (!ports) {
  80. printk(KERN_ERR "sgalaxy: WSS IO port 0x%03x not available\n", ai->io_base);
  81. release_region(ai->io_base, 4);
  82. return 0;
  83. }
  84. if (!request_region( ai->ai_sgbase, 0x10, "SoundGalaxy SB")) {
  85. printk(KERN_ERR "sgalaxy: SB IO port 0x%03x not available\n", ai->ai_sgbase);
  86. release_region(ai->io_base + 4, 4);
  87. release_region(ai->io_base, 4);
  88. return 0;
  89. }
  90. if (ad1848_detect(ports, NULL, ai->osp))
  91. goto out; /* The card is already active, check irq etc... */
  92. /* switch to MSS/WSS mode */
  93. sb_rst( ai->ai_sgbase );
  94. sb_cmd( ai->ai_sgbase, 9 );
  95. sb_cmd( ai->ai_sgbase, 0 );
  96. sleep( HZ/10 );
  97. out:
  98. if (!probe_ms_sound(ai, ports)) {
  99. release_region(ai->io_base + 4, 4);
  100. release_region(ai->io_base, 4);
  101. release_region(ai->ai_sgbase, 0x10);
  102. return 0;
  103. }
  104. attach_ms_sound(ai, ports, THIS_MODULE);
  105. n=ai->slots[0];
  106. if (n!=-1 && audio_devs[n]->mixer_dev != -1 ) {
  107. AD1848_REROUTE( SOUND_MIXER_LINE1, SOUND_MIXER_LINE ); /* Line-in */
  108. AD1848_REROUTE( SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH ); /* FM+Wavetable*/
  109. AD1848_REROUTE( SOUND_MIXER_LINE3, SOUND_MIXER_CD ); /* CD */
  110. }
  111. return 1;
  112. }
  113. static void __exit unload_sgalaxy( struct address_info *ai )
  114. {
  115. unload_ms_sound( ai );
  116. release_region( ai->ai_sgbase, 0x10 );
  117. }
  118. static struct address_info cfg;
  119. static int __initdata io = -1;
  120. static int __initdata irq = -1;
  121. static int __initdata dma = -1;
  122. static int __initdata dma2 = -1;
  123. static int __initdata sgbase = -1;
  124. module_param(io, int, 0);
  125. module_param(irq, int, 0);
  126. module_param(dma, int, 0);
  127. module_param(dma2, int, 0);
  128. module_param(sgbase, int, 0);
  129. static int __init init_sgalaxy(void)
  130. {
  131. cfg.io_base = io;
  132. cfg.irq = irq;
  133. cfg.dma = dma;
  134. cfg.dma2 = dma2;
  135. cfg.ai_sgbase = sgbase;
  136. if (cfg.io_base == -1 || cfg.irq == -1 || cfg.dma == -1 || cfg.ai_sgbase == -1 ) {
  137. printk(KERN_ERR "sgalaxy: io, irq, dma and sgbase must be set.\n");
  138. return -EINVAL;
  139. }
  140. if ( probe_sgalaxy(&cfg) == 0 )
  141. return -ENODEV;
  142. return 0;
  143. }
  144. static void __exit cleanup_sgalaxy(void)
  145. {
  146. unload_sgalaxy(&cfg);
  147. }
  148. module_init(init_sgalaxy);
  149. module_exit(cleanup_sgalaxy);
  150. #ifndef MODULE
  151. static int __init setup_sgalaxy(char *str)
  152. {
  153. /* io, irq, dma, dma2, sgbase */
  154. int ints[6];
  155. str = get_options(str, ARRAY_SIZE(ints), ints);
  156. io = ints[1];
  157. irq = ints[2];
  158. dma = ints[3];
  159. dma2 = ints[4];
  160. sgbase = ints[5];
  161. return 1;
  162. }
  163. __setup("sgalaxy=", setup_sgalaxy);
  164. #endif
  165. MODULE_LICENSE("GPL");