root/drivers/sound/trix.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. trix_read
  2. trix_write
  3. download_boot
  4. trix_set_wss_port
  5. probe_trix_wss
  6. attach_trix_wss
  7. probe_trix_sb
  8. attach_trix_sb
  9. attach_trix_mpu
  10. probe_trix_mpu
  11. unload_trix_wss
  12. unload_trix_mpu
  13. unload_trix_sb

   1 /*
   2  * sound/trix.c
   3  *
   4  * Low level driver for the MediaTriX AudioTriX Pro
   5  * (MT-0002-PC Control Chip)
   6  *
   7  * Copyright by Hannu Savolainen 1995
   8  *
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions are
  11  * met: 1. Redistributions of source code must retain the above copyright
  12  * notice, this list of conditions and the following disclaimer. 2.
  13  * Redistributions in binary form must reproduce the above copyright notice,
  14  * this list of conditions and the following disclaimer in the documentation
  15  * and/or other materials provided with the distribution.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  *
  29  */
  30 
  31 #include "sound_config.h"
  32 
  33 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_TRIX)
  34 
  35 #ifdef INCLUDE_TRIX_BOOT
  36 #include "trix_boot.h"
  37 #endif
  38 
  39 static int      kilroy_was_here = 0;    /* Don't detect twice */
  40 static int      sb_initialized = 0;
  41 static int      mpu_initialized = 0;
  42 
  43 static sound_os_info *trix_osp = NULL;
  44 
  45 static unsigned char
  46 trix_read (int addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48   outb ((unsigned char) addr, 0x390);   /* MT-0002-PC ASIC address */
  49   return inb (0x391);           /* MT-0002-PC ASIC data */
  50 }
  51 
  52 static void
  53 trix_write (int addr, int data)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55   outb ((unsigned char) addr, 0x390);   /* MT-0002-PC ASIC address */
  56   outb ((unsigned char) data, 0x391);   /* MT-0002-PC ASIC data */
  57 }
  58 
  59 static void
  60 download_boot (int base)
     /* [previous][next][first][last][top][bottom][index][help] */
  61 {
  62 #ifdef INCLUDE_TRIX_BOOT
  63   int             i = 0, n = sizeof (trix_boot);
  64 
  65   trix_write (0xf8, 0x00);      /* ??????? */
  66   outb (0x01, base + 6);        /* Clear the internal data pointer */
  67   outb (0x00, base + 6);        /* Restart */
  68 
  69   /*
  70      *  Write the boot code to the RAM upload/download register.
  71      *  Each write increments the internal data pointer.
  72    */
  73   outb (0x01, base + 6);        /* Clear the internal data pointer */
  74   outb (0x1A, 0x390);           /* Select RAM download/upload port */
  75 
  76   for (i = 0; i < n; i++)
  77     outb (trix_boot[i], 0x391);
  78   for (i = n; i < 10016; i++)   /* Clear up to first 16 bytes of data RAM */
  79     outb (0x00, 0x391);
  80   outb (0x00, base + 6);        /* Reset */
  81   outb (0x50, 0x390);           /* ?????? */
  82 #endif
  83 }
  84 
  85 static int
  86 trix_set_wss_port (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
  87 {
  88   unsigned char   addr_bits;
  89 
  90   if (check_region (0x390, 2))
  91     {
  92       printk ("AudioTriX: Config port I/O conflict\n");
  93       return 0;
  94     }
  95 
  96   if (kilroy_was_here)          /* Already initialized */
  97     return 0;
  98 
  99   if (trix_read (0x15) != 0x71) /* No asic signature */
 100     {
 101       DDB (printk ("No AudioTriX ASIC signature found\n"));
 102       return 0;
 103     }
 104 
 105   request_region (0x390, 2, "AudioTriX");
 106 
 107   kilroy_was_here = 1;
 108 
 109   /*
 110    * Reset some registers.
 111    */
 112 
 113   trix_write (0x13, 0);
 114   trix_write (0x14, 0);
 115 
 116   /*
 117      * Configure the ASIC to place the codec to the proper I/O location
 118    */
 119 
 120   switch (hw_config->io_base)
 121     {
 122     case 0x530:
 123       addr_bits = 0;
 124       break;
 125     case 0x604:
 126       addr_bits = 1;
 127       break;
 128     case 0xE80:
 129       addr_bits = 2;
 130       break;
 131     case 0xF40:
 132       addr_bits = 3;
 133       break;
 134     default:
 135       return 0;
 136     }
 137 
 138   trix_write (0x19, (trix_read (0x19) & 0x03) | addr_bits);
 139   return 1;
 140 }
 141 
 142 /*
 143  *    Probe and attach routines for the Windows Sound System mode of
 144  *      AudioTriX Pro
 145  */
 146 
 147 int
 148 probe_trix_wss (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 149 {
 150   /*
 151      * Check if the IO port returns valid signature. The original MS Sound
 152      * system returns 0x04 while some cards (AudioTriX Pro for example)
 153      * return 0x00.
 154    */
 155   if (check_region (hw_config->io_base, 8))
 156     {
 157       printk ("AudioTriX: MSS I/O port conflict\n");
 158       return 0;
 159     }
 160 
 161   trix_osp = hw_config->osp;
 162 
 163   if (!trix_set_wss_port (hw_config))
 164     return 0;
 165 
 166   if ((inb (hw_config->io_base + 3) & 0x3f) != 0x00)
 167     {
 168       DDB (printk ("No MSS signature detected on port 0x%x\n", hw_config->io_base));
 169       return 0;
 170     }
 171 
 172   if (hw_config->irq > 11)
 173     {
 174       printk ("AudioTriX: Bad WSS IRQ %d\n", hw_config->irq);
 175       return 0;
 176     }
 177 
 178   if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
 179     {
 180       printk ("AudioTriX: Bad WSS DMA %d\n", hw_config->dma);
 181       return 0;
 182     }
 183 
 184   if (hw_config->dma2 != -1)
 185     if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3)
 186       {
 187         printk ("AudioTriX: Bad capture DMA %d\n", hw_config->dma2);
 188         return 0;
 189       }
 190 
 191   /*
 192      * Check that DMA0 is not in use with a 8 bit board.
 193    */
 194 
 195   if (hw_config->dma == 0 && inb (hw_config->io_base + 3) & 0x80)
 196     {
 197       printk ("AudioTriX: Can't use DMA0 with a 8 bit card\n");
 198       return 0;
 199     }
 200 
 201   if (hw_config->irq > 7 && hw_config->irq != 9 && inb (hw_config->io_base + 3) & 0x80)
 202     {
 203       printk ("AudioTriX: Can't use IRQ%d with a 8 bit card\n", hw_config->irq);
 204       return 0;
 205     }
 206 
 207   return ad1848_detect (hw_config->io_base + 4, NULL, hw_config->osp);
 208 }
 209 
 210 long
 211 attach_trix_wss (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 212 {
 213   static unsigned char interrupt_bits[12] =
 214   {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20};
 215   char            bits;
 216 
 217   static unsigned char dma_bits[4] =
 218   {1, 2, 0, 3};
 219 
 220   int             config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
 221   int             dma1 = hw_config->dma, dma2 = hw_config->dma2;
 222 
 223   trix_osp = hw_config->osp;
 224 
 225   if (!kilroy_was_here)
 226     {
 227       DDB (printk ("AudioTriX: Attach called but not probed yet???\n"));
 228       return mem_start;
 229     }
 230 
 231   /*
 232      * Set the IRQ and DMA addresses.
 233    */
 234 
 235   bits = interrupt_bits[hw_config->irq];
 236   if (bits == -1)
 237     {
 238       printk ("AudioTriX: Bad IRQ (%d)\n", hw_config->irq);
 239       return mem_start;
 240     }
 241 
 242   outb (bits | 0x40, config_port);
 243   if ((inb (version_port) & 0x40) == 0)
 244     printk ("[IRQ Conflict?]");
 245 
 246   if (hw_config->dma2 == -1)    /* Single DMA mode */
 247     {
 248       bits |= dma_bits[dma1];
 249       dma2 = dma1;
 250     }
 251   else
 252     {
 253       unsigned char   tmp;
 254 
 255       tmp = trix_read (0x13) & ~30;
 256       trix_write (0x13, tmp | 0x80 | (dma1 << 4));
 257 
 258       tmp = trix_read (0x14) & ~30;
 259       trix_write (0x14, tmp | 0x80 | (dma2 << 4));
 260     }
 261 
 262   outb (bits, config_port);     /* Write IRQ+DMA setup */
 263 
 264   ad1848_init ("AudioTriX Pro", hw_config->io_base + 4,
 265                hw_config->irq,
 266                dma1,
 267                dma2,
 268                0,
 269                hw_config->osp);
 270   request_region (hw_config->io_base, 4, "MSS config");
 271   return mem_start;
 272 }
 273 
 274 int
 275 probe_trix_sb (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 276 {
 277 
 278   int             tmp;
 279   unsigned char   conf;
 280   static char     irq_translate[] =
 281   {-1, -1, -1, 0, 1, 2, -1, 3};
 282 
 283 #ifndef INCLUDE_TRIX_BOOT
 284   return 0;                     /* No boot code -> no fun */
 285 #endif
 286   if (!kilroy_was_here)
 287     return 0;                   /* AudioTriX Pro has not been detected earlier */
 288 
 289   if (sb_initialized)
 290     return 0;
 291 
 292   if (check_region (hw_config->io_base, 16))
 293     {
 294       printk ("AudioTriX: SB I/O port conflict\n");
 295       return 0;
 296     }
 297 
 298   if (hw_config->io_base & 0xffffff8f != 0x200)
 299     return 0;
 300 
 301   tmp = hw_config->irq;
 302   if (tmp > 7)
 303     return 0;
 304   if (irq_translate[tmp] == -1)
 305     return 0;
 306 
 307   tmp = hw_config->dma;
 308   if (tmp != 1 && tmp != 3)
 309     return 0;
 310 
 311   conf = 0x84;                  /* DMA and IRQ enable */
 312   conf |= hw_config->io_base & 0x70;    /* I/O address bits */
 313   conf |= irq_translate[hw_config->irq];
 314   if (hw_config->dma == 3)
 315     conf |= 0x08;
 316   trix_write (0x1b, conf);
 317 
 318   download_boot (hw_config->io_base);
 319   sb_initialized = 1;
 320 
 321   return 1;
 322 }
 323 
 324 long
 325 attach_trix_sb (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 326 {
 327 #ifndef EXCLUDE_SB
 328   extern int      sb_no_recording;
 329 
 330   sb_dsp_disable_midi ();
 331   sb_no_recording = 1;
 332 #endif
 333   printk (" <AudioTriX (SB)>");
 334   return mem_start;
 335 }
 336 
 337 long
 338 attach_trix_mpu (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 339 {
 340 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
 341   return attach_mpu401 (mem_start, hw_config);
 342 #else
 343   return mem_start;
 344 #endif
 345 }
 346 
 347 int
 348 probe_trix_mpu (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 349 {
 350 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
 351   unsigned char   conf;
 352   static char     irq_bits[] =
 353   {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5};
 354 
 355   if (!kilroy_was_here)
 356     {
 357       DDB (printk ("Trix: WSS and SB modes must be initialized before MPU\n"));
 358       return 0;                 /* AudioTriX Pro has not been detected earlier */
 359     }
 360 
 361   if (!sb_initialized)
 362     {
 363       DDB (printk ("Trix: SB mode must be initialized before MPU\n"));
 364       return 0;
 365     }
 366 
 367   if (mpu_initialized)
 368     {
 369       DDB (printk ("Trix: MPU mode already initialized\n"));
 370       return 0;
 371     }
 372 
 373   if (check_region (hw_config->io_base, 4))
 374     {
 375       printk ("AudioTriX: MPU I/O port conflict\n");
 376       return 0;
 377     }
 378 
 379   if (hw_config->irq > 9)
 380     {
 381       printk ("AudioTriX: Bad MPU IRQ %d\n", hw_config->irq);
 382       return 0;
 383     }
 384 
 385   if (irq_bits[hw_config->irq] == -1)
 386     {
 387       printk ("AudioTriX: Bad MPU IRQ %d\n", hw_config->irq);
 388       return 0;
 389     }
 390 
 391   switch (hw_config->io_base)
 392     {
 393     case 0x330:
 394       conf = 0x00;
 395       break;
 396     case 0x370:
 397       conf = 0x04;
 398       break;
 399     case 0x3b0:
 400       conf = 0x08;
 401       break;
 402     case 0x3f0:
 403       conf = 0x0c;
 404       break;
 405     default:
 406       return 0;                 /* Invalid port */
 407     }
 408 
 409   conf |= irq_bits[hw_config->irq] << 4;
 410 
 411   trix_write (0x19, (trix_read (0x19) & 0x83) | conf);
 412 
 413   mpu_initialized = 1;
 414 
 415   return probe_mpu401 (hw_config);
 416 #else
 417   return 0;
 418 #endif
 419 }
 420 
 421 void
 422 unload_trix_wss (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 423 {
 424   int             dma2 = hw_config->dma2;
 425 
 426   if (dma2 == -1)
 427     dma2 = hw_config->dma;
 428 
 429   release_region (0x390, 2);
 430   release_region (hw_config->io_base, 4);
 431 
 432   ad1848_unload (hw_config->io_base + 4,
 433                  hw_config->irq,
 434                  hw_config->dma,
 435                  dma2,
 436                  0);
 437 }
 438 
 439 void
 440 unload_trix_mpu (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 441 {
 442 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
 443   unload_mpu401 (hw_config);
 444 #endif
 445 }
 446 void
 447 unload_trix_sb (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 448 {
 449 }
 450 
 451 
 452 #endif

/* [previous][next][first][last][top][bottom][index][help] */