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

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