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

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