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 25#include <linux/init.h> 26#include <linux/module.h> 27 28#include "sound_config.h" 29#include "ad1848.h" 30 31static void sleep( unsigned howlong ) 32{ 33 current->state = TASK_INTERRUPTIBLE; 34 schedule_timeout(howlong); 35} 36 37#define DPORT 0x80 38 39/* Sound Blaster regs */ 40 41#define SBDSP_RESET 0x6 42#define SBDSP_READ 0xA 43#define SBDSP_COMMAND 0xC 44#define SBDSP_STATUS SBDSP_COMMAND 45#define SBDSP_DATA_AVAIL 0xE 46 47static int __init sb_rst(int base) 48{ 49 int i; 50 51 outb( 1, base+SBDSP_RESET ); /* reset the DSP */ 52 outb( 0, base+SBDSP_RESET ); 53 54 for ( i=0; i<500; i++ ) /* delay */ 55 inb(DPORT); 56 57 for ( i=0; i<100000; i++ ) 58 { 59 if ( inb( base+SBDSP_DATA_AVAIL )&0x80 ) 60 break; 61 } 62 63 if ( inb( base+SBDSP_READ )!=0xAA ) 64 return 0; 65 66 return 1; 67} 68 69static int __init sb_cmd( int base, unsigned char val ) 70{ 71 int i; 72 73 for ( i=100000; i; i-- ) 74 { 75 if ( (inb( base+SBDSP_STATUS )&0x80)==0 ) 76 { 77 outb( val, base+SBDSP_COMMAND ); 78 break; 79 } 80 } 81 return i; /* i>0 == success */ 82} 83 84 85#define ai_sgbase driver_use_1 86 87static int __init probe_sgalaxy( struct address_info *ai ) 88{ 89 if ( check_region( ai->io_base, 8 ) ) { 90 printk(KERN_ERR "sgalaxy: WSS IO port 0x%03x not available\n", ai->io_base); 91 return 0; 92 } 93 94 if ( ad1848_detect( ai->io_base+4, NULL, ai->osp ) ) 95 return probe_ms_sound(ai); /* The card is already active, check irq etc... */ 96 97 if ( check_region( ai->ai_sgbase, 0x10 ) ) { 98 printk(KERN_ERR "sgalaxy: SB IO port 0x%03x not available\n", ai->ai_sgbase); 99 return 0; 100 } 101 102 /* switch to MSS/WSS mode */ 103 104 sb_rst( ai->ai_sgbase ); 105 106 sb_cmd( ai->ai_sgbase, 9 ); 107 sb_cmd( ai->ai_sgbase, 0 ); 108 109 sleep( HZ/10 ); 110 111 return probe_ms_sound(ai); 112} 113 114static void __init attach_sgalaxy( struct address_info *ai ) 115{ 116 int n; 117 118 request_region( ai->ai_sgbase, 0x10, "SoundGalaxy SB" ); 119 120 attach_ms_sound(ai, THIS_MODULE); 121 n=ai->slots[0]; 122 123 if (n!=-1 && audio_devs[n]->mixer_dev != -1 ) { 124 AD1848_REROUTE( SOUND_MIXER_LINE1, SOUND_MIXER_LINE ); /* Line-in */ 125 AD1848_REROUTE( SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH ); /* FM+Wavetable*/ 126 AD1848_REROUTE( SOUND_MIXER_LINE3, SOUND_MIXER_CD ); /* CD */ 127 } 128} 129 130static void __exit unload_sgalaxy( struct address_info *ai ) 131{ 132 unload_ms_sound( ai ); 133 release_region( ai->ai_sgbase, 0x10 ); 134} 135 136static struct address_info cfg; 137 138static int __initdata io = -1; 139static int __initdata irq = -1; 140static int __initdata dma = -1; 141static int __initdata dma2 = -1; 142static int __initdata sgbase = -1; 143 144MODULE_PARM(io,"i"); 145MODULE_PARM(irq,"i"); 146MODULE_PARM(dma,"i"); 147MODULE_PARM(dma2,"i"); 148MODULE_PARM(sgbase,"i"); 149 150static int __init init_sgalaxy(void) 151{ 152 cfg.io_base = io; 153 cfg.irq = irq; 154 cfg.dma = dma; 155 cfg.dma2 = dma2; 156 cfg.ai_sgbase = sgbase; 157 158 if (cfg.io_base == -1 || cfg.irq == -1 || cfg.dma == -1 || cfg.ai_sgbase == -1 ) { 159 printk(KERN_ERR "sgalaxy: io, irq, dma and sgbase must be set.\n"); 160 return -EINVAL; 161 } 162 163 if ( probe_sgalaxy(&cfg) == 0 ) 164 return -ENODEV; 165 166 attach_sgalaxy(&cfg); 167 168 return 0; 169} 170 171static void __exit cleanup_sgalaxy(void) 172{ 173 unload_sgalaxy(&cfg); 174} 175 176module_init(init_sgalaxy); 177module_exit(cleanup_sgalaxy); 178 179#ifndef MODULE 180static int __init setup_sgalaxy(char *str) 181{ 182 /* io, irq, dma, dma2, sgbase */ 183 int ints[6]; 184 185 str = get_options(str, ARRAY_SIZE(ints), ints); 186 io = ints[1]; 187 irq = ints[2]; 188 dma = ints[3]; 189 dma2 = ints[4]; 190 sgbase = ints[5]; 191 192 return 1; 193} 194 195__setup("sgalaxy=", setup_sgalaxy); 196#endif 197MODULE_LICENSE("GPL"); 198