root/drivers/sound/mad16.c

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

DEFINITIONS

This source file includes following definitions.
  1. mad_read
  2. mad_write
  3. detect_mad16
  4. probe_mad16
  5. attach_mad16
  6. attach_mad16_mpu
  7. probe_mad16_mpu
  8. unload_mad16
  9. unload_mad16_mpu

   1 /*
   2  * sound/mad16.c
   3  *
   4  * Initialization code for OPTi MAD16 compatible audio chips. Including
   5  *
   6  *      OPTi 82C928     MAD16           (replaced by C929)
   7  *      OAK OTI-601D    Mozart
   8  *      OPTi 82C929     MAD16 Pro
   9  *
  10  * These audio interface chips don't prduce sound themselves. They just
  11  * connect some other components (OPL-[234] and a WSS compatible codec)
  12  * to the PC bus and perform I/O, DMA and IRQ address decoding. There is
  13  * also a UART for the MPU-401 mode (not 82C928/Mozart).
  14  * The Mozart chip appears to be compatible with the 82C928 (can anybody
  15  * confirm this?).
  16  *
  17  * NOTE! If you want to set CD-ROM address and/or joystick enable, define
  18  *       MAD16_CONF in local.h as combination of the following bits:
  19  *
  20  *      0x01    - joystick disabled
  21  *
  22  *      CD-ROM type selection (select just one):
  23  *      0x00    - none
  24  *      0x02    - Sony 31A
  25  *      0x04    - Mitsumi
  26  *      0x06    - Panasonic (type "LaserMate", not "SoundBlaster")
  27  *      0x08    - Secondary IDE (address 0x170)
  28  *      0x0a    - Primary IDE (address 0x1F0)
  29  *      
  30  *      For example Mitsumi with joystick disabled = 0x04|0x01 = 0x05
  31  *      For example LaserMate (for use with sbpcd) plus joystick = 0x06
  32  *      
  33  *    MAD16_CDSEL:
  34  *      This defaults to CD I/O 0x340, no IRQ and DMA3 
  35  *      (DMA5 with Mitsumi or IDE). If you like to change these, define
  36  *      MAD16_CDSEL with the following bits:
  37  *
  38  *      CD-ROM port: 0x00=340, 0x40=330, 0x80=360 or 0xc0=320
  39  *      OPL4 select: 0x20=OPL4, 0x00=OPL3
  40  *      CD-ROM irq: 0x00=disabled, 0x04=IRQ5, 0x08=IRQ7, 0x0a=IRQ3, 0x10=IRQ9,
  41  *                  0x14=IRQ10 and 0x18=IRQ11.
  42  *
  43  *      CD-ROM DMA (Sony or Panasonic): 0x00=DMA3, 0x01=DMA2, 0x02=DMA1 or 0x03=disabled
  44  *   or
  45  *      CD-ROM DMA (Mitsumi or IDE):    0x00=DMA5, 0x01=DMA6, 0x02=DMA7 or 0x03=disabled
  46  *
  47  *      For use with sbpcd, address 0x340, set MAD16_CDSEL to 0x03 or 0x23.
  48  *
  49  * Copyright by Hannu Savolainen 1995
  50  *
  51  * Redistribution and use in source and binary forms, with or without
  52  * modification, are permitted provided that the following conditions are
  53  * met: 1. Redistributions of source code must retain the above copyright
  54  * notice, this list of conditions and the following disclaimer. 2.
  55  * Redistributions in binary form must reproduce the above copyright notice,
  56  * this list of conditions and the following disclaimer in the documentation
  57  * and/or other materials provided with the distribution.
  58  *
  59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  60  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  61  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  62  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  63  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  64  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  65  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  66  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  67  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  68  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  69  * SUCH DAMAGE.
  70  *
  71  */
  72 
  73 #include "sound_config.h"
  74 
  75 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_MAD16)
  76 
  77 static int      already_initialized = 0;
  78 
  79 #define C928    1
  80 #define MOZART  2
  81 #define C929    3
  82 
  83 /*
  84  *    Registers
  85  *
  86  *      The MAD16 occupies I/O ports 0xf8d to 0xf93 (fixed locations).
  87  *      All ports are inactive by default. They can be activated by
  88  *      writing 0xE2 or 0xE3 to the password register. The password is valid
  89  *      only until the next I/O read or write.
  90  */
  91 
  92 #define MC1_PORT        0xf8d   /* SB address, CDROM interface type, joystick */
  93 #define MC2_PORT        0xf8e   /* CDROM address, IRQ, DMA, plus OPL4 bit */
  94 #define MC3_PORT        0xf8f
  95 #define PASSWD_REG      0xf8f
  96 #define MC4_PORT        0xf90
  97 #define MC5_PORT        0xf91
  98 #define MC6_PORT        0xf92
  99 #define MC7_PORT        0xf93
 100 
 101 static int      board_type = C928;
 102 
 103 static sound_os_info *mad16_osp;
 104 
 105 #ifndef DDB
 106 #define DDB(x)
 107 #endif
 108 
 109 static unsigned char
 110 mad_read (int port)
     /* [previous][next][first][last][top][bottom][index][help] */
 111 {
 112   unsigned long   flags;
 113   unsigned char   tmp;
 114 
 115   save_flags (flags);
 116   cli ();
 117 
 118   switch (board_type)           /* Output password */
 119     {
 120     case C928:
 121     case MOZART:
 122       outb (0xE2, PASSWD_REG);
 123       break;
 124 
 125     case C929:
 126       outb (0xE3, PASSWD_REG);
 127       break;
 128     }
 129 
 130   tmp = inb (port);
 131   restore_flags (flags);
 132 
 133   return tmp;
 134 }
 135 
 136 static void
 137 mad_write (int port, int value)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139   unsigned long   flags;
 140 
 141   save_flags (flags);
 142   cli ();
 143 
 144   switch (board_type)           /* Output password */
 145     {
 146     case C928:
 147     case MOZART:
 148       outb (0xE2, PASSWD_REG);
 149       break;
 150 
 151     case C929:
 152       outb (0xE3, PASSWD_REG);
 153       break;
 154     }
 155 
 156   outb ((unsigned char) (value & 0xff), port);
 157   restore_flags (flags);
 158 }
 159 
 160 static int
 161 detect_mad16 (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163   unsigned char   tmp, tmp2;
 164 
 165 /*
 166  * Check that reading a register doesn't return bus float (0xff)
 167  * when the card is accessed using password. This may fail in case
 168  * the card is in low power mode. Normally at least the power saving mode
 169  * bit should be 0.
 170  */
 171   if ((tmp = mad_read (MC1_PORT)) == 0xff)
 172     {
 173       DDB (printk ("MC1_PORT returned 0xff\n"));
 174       return 0;
 175     }
 176 /*
 177  * Now check that the gate is closed on first I/O after writing
 178  * the password. (This is how a MAD16 compatible card works).
 179  */
 180 
 181   if ((tmp2 = inb (MC1_PORT)) == tmp)   /* It didn't close */
 182     {
 183       DDB (printk ("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
 184       return 0;
 185     }
 186 
 187   mad_write (MC1_PORT, tmp ^ 0x80);     /* Togge a bit */
 188 
 189   if ((tmp2 = mad_read (MC1_PORT)) != (tmp ^ 0x80))     /* Compare the bit */
 190     {
 191       mad_write (MC1_PORT, tmp);        /* Restore */
 192       DDB (printk ("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
 193       return 0;
 194     }
 195 
 196   mad_write (MC1_PORT, tmp);    /* Restore */
 197   return 1;                     /* Bingo */
 198 
 199 }
 200 
 201 int
 202 probe_mad16 (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204   int             i;
 205   static int      valid_ports[] =
 206   {0x530, 0xe80, 0xf40, 0x604};
 207   unsigned char   tmp;
 208   unsigned char   cs4231_mode = 0;
 209 
 210   int             ad_flags = 0;
 211 
 212   if (already_initialized)
 213     return 0;
 214 
 215   mad16_osp = hw_config->osp;
 216 /*
 217  *    Check that all ports return 0xff (bus float) when no password
 218  *      is written to the password register.
 219  */
 220 
 221   DDB (printk ("--- Detecting MAD16 / Mozart ---\n"));
 222 
 223 
 224 /*
 225  *    Then try to detect with the old password
 226  */
 227   board_type = C928;
 228 
 229   DDB (printk ("Detect using password = 0xE2\n"));
 230 
 231   if (!detect_mad16 ())         /* No luck. Try different model */
 232     {
 233       board_type = C929;
 234 
 235       DDB (printk ("Detect using password = 0xE3\n"));
 236 
 237       if (!detect_mad16 ())
 238         return 0;
 239 
 240       DDB (printk ("mad16.c: 82C929 detected\n"));
 241     }
 242   else
 243     {
 244       unsigned char   model;
 245 
 246       if (((model = mad_read (MC3_PORT)) & 0x03) == 0x03)
 247         {
 248           DDB (printk ("mad16.c: Mozart detected\n"));
 249           board_type = MOZART;
 250         }
 251       else
 252         {
 253           DDB (printk ("mad16.c: 82C928 detected???\n"));
 254           board_type = C928;
 255         }
 256     }
 257 
 258   for (i = 0xf8d; i <= 0xf93; i++)
 259     DDB (printk ("port %03x = %03x\n", i, mad_read (i)));
 260 
 261 /*
 262  * Set the WSS address
 263  */
 264 
 265   tmp = 0x80;                   /* Enable WSS, Disable SB */
 266 
 267   for (i = 0; i < 5; i++)
 268     {
 269       if (i > 3)                /* Not a valid port */
 270         {
 271           printk ("MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
 272           return 0;
 273         }
 274 
 275       if (valid_ports[i] == hw_config->io_base)
 276         {
 277           tmp |= i << 4;        /* WSS port select bits */
 278           break;
 279         }
 280     }
 281 
 282 /*
 283  * Set optional CD-ROM and joystick settings.
 284  */
 285 
 286 #ifdef MAD16_CONF
 287   tmp |= ((MAD16_CONF) & 0x0f); /* CD-ROM and joystick bits */
 288 #endif
 289   mad_write (MC1_PORT, tmp);
 290 
 291 #if defined(MAD16_CONF) && defined(MAD16_CDSEL)
 292   tmp = MAD16_CDSEL;
 293 #else
 294   tmp = 0x03;
 295 #endif
 296 
 297 #ifdef MAD16_OPL4
 298   tmp |= 0x20;                  /* Enable OPL4 access */
 299 #endif
 300 
 301   mad_write (MC2_PORT, tmp);
 302   mad_write (MC3_PORT, 0xf0);   /* Disable SB */
 303 
 304   if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, mad16_osp))
 305     return 0;
 306 
 307   if (ad_flags & (AD_F_CS4231 | AD_F_CS4248))
 308     cs4231_mode = 0x02;         /* CS4248/CS4231 sync delay switch */
 309 
 310   if (board_type == C929)
 311     {
 312       mad_write (MC4_PORT, 0xa2);
 313       mad_write (MC5_PORT, 0xA5 | cs4231_mode);
 314       mad_write (MC6_PORT, 0x03);       /* Disable MPU401 */
 315     }
 316   else
 317     {
 318       mad_write (MC4_PORT, 0x02);
 319       mad_write (MC5_PORT, 0x30 | cs4231_mode);
 320     }
 321 
 322   for (i = 0xf8d; i <= 0xf93; i++)
 323     DDB (printk ("port %03x after init = %03x\n", i, mad_read (i)));
 324 
 325 /*
 326  *    Verify the WSS parameters
 327  */
 328 
 329   if (check_region (hw_config->io_base, 8))
 330     {
 331       printk ("MSS: I/O port conflict\n");
 332       return 0;
 333     }
 334 
 335   /*
 336      * Check if the IO port returns valid signature. The original MS Sound
 337      * system returns 0x04 while some cards (AudioTriX Pro for example)
 338      * return 0x00.
 339    */
 340 
 341   if ((inb (hw_config->io_base + 3) & 0x3f) != 0x04 &&
 342       (inb (hw_config->io_base + 3) & 0x3f) != 0x00)
 343     {
 344       DDB (printk ("No MSS signature detected on port 0x%x (0x%x)\n",
 345                    hw_config->io_base, inb (hw_config->io_base + 3)));
 346       return 0;
 347     }
 348 
 349   if (hw_config->irq > 11)
 350     {
 351       printk ("MSS: Bad IRQ %d\n", hw_config->irq);
 352       return 0;
 353     }
 354 
 355   if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
 356     {
 357       printk ("MSS: Bad DMA %d\n", hw_config->dma);
 358       return 0;
 359     }
 360 
 361   /*
 362      * Check that DMA0 is not in use with a 8 bit board.
 363    */
 364 
 365   if (hw_config->dma == 0 && inb (hw_config->io_base + 3) & 0x80)
 366     {
 367       printk ("MSS: Can't use DMA0 with a 8 bit card/slot\n");
 368       return 0;
 369     }
 370 
 371   if (hw_config->irq > 7 && hw_config->irq != 9 && inb (hw_config->io_base + 3) & 0x80)
 372     {
 373       printk ("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
 374       return 0;
 375     }
 376 
 377   return 1;
 378 }
 379 
 380 long
 381 attach_mad16 (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 382 {
 383 
 384   static char     interrupt_bits[12] =
 385   {
 386     -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
 387   };
 388   char            bits;
 389 
 390   static char     dma_bits[4] =
 391   {
 392     1, 2, 0, 3
 393   };
 394 
 395   int             config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
 396   int             ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2;
 397   unsigned char   dma2_bit = 0;
 398 
 399   already_initialized = 1;
 400 
 401   if (!ad1848_detect (hw_config->io_base + 4, &ad_flags, mad16_osp))
 402     return mem_start;
 403 
 404   /*
 405      * Set the IRQ and DMA addresses.
 406    */
 407 
 408   bits = interrupt_bits[hw_config->irq];
 409   if (bits == -1)
 410     return mem_start;
 411 
 412   outb (bits | 0x40, config_port);
 413   if ((inb (version_port) & 0x40) == 0)
 414     printk ("[IRQ Conflict?]");
 415 
 416 /*
 417  * Handle the capture DMA channel
 418  */
 419 
 420   if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma)
 421     {
 422       if ((dma == 0 && dma2 == 1) ||
 423           (dma == 1 && dma2 == 0) ||
 424           (dma == 3 && dma2 == 0))
 425         {
 426           dma2_bit = 0x04;      /* Enable capture DMA */
 427         }
 428       else
 429         {
 430           printk ("MAD16: Invalid capture DMA\n");
 431           dma2 = dma;
 432         }
 433     }
 434   else
 435     dma2 = dma;
 436 
 437   outb (bits | dma_bits[dma] | dma2_bit, config_port);  /* Write IRQ+DMA setup */
 438 
 439   ad1848_init ("MAD16 WSS", hw_config->io_base + 4,
 440                hw_config->irq,
 441                dma,
 442                dma2, 0,
 443                hw_config->osp);
 444   request_region (hw_config->io_base, 4, "MAD16 WSS config");
 445 
 446   return mem_start;
 447 }
 448 
 449 long
 450 attach_mad16_mpu (long mem_start, struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 451 {
 452   if (board_type < C929)        /* Early chip. No MPU support. Just SB MIDI */
 453     {
 454 #ifndef EXCLUDE_MIDI
 455 
 456       if (mad_read (MC1_PORT) & 0x20)
 457         hw_config->io_base = 0x240;
 458       else
 459         hw_config->io_base = 0x220;
 460 
 461       return mad16_sb_dsp_init (mem_start, hw_config);
 462 #else
 463       return 0;
 464 #endif
 465     }
 466 
 467 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
 468   if (!already_initialized)
 469     return mem_start;
 470 
 471   return attach_mpu401 (mem_start, hw_config);
 472 #else
 473   return mem_start;
 474 #endif
 475 }
 476 
 477 int
 478 probe_mad16_mpu (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 479 {
 480 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
 481   static int      mpu_attached = 0;
 482   static int      valid_ports[] =
 483   {0x330, 0x320, 0x310, 0x300};
 484   static short    valid_irqs[] =
 485   {9, 10, 5, 7};
 486   unsigned char   tmp;
 487 
 488   int             i;            /* A variable with secret power */
 489 
 490   if (!already_initialized)     /* The MSS port must be initialized first */
 491     return 0;
 492 
 493   if (mpu_attached)             /* Don't let them call this twice */
 494     return 0;
 495   mpu_attached = 1;
 496 
 497   if (board_type < C929)        /* Early chip. No MPU support. Just SB MIDI */
 498     {
 499 
 500 #ifndef EXCLUDE_MIDI
 501       unsigned char   tmp;
 502 
 503       tmp = mad_read (MC3_PORT);
 504 
 505       /* 
 506        * MAD16 SB base is defined by the WSS base. It cannot be changed 
 507        * alone.
 508        * Ignore configured I/O base. Use the active setting. 
 509        */
 510 
 511       if (mad_read (MC1_PORT) & 0x20)
 512         hw_config->io_base = 0x240;
 513       else
 514         hw_config->io_base = 0x220;
 515 
 516       switch (hw_config->irq)
 517         {
 518         case 5:
 519           tmp = (tmp & 0x3f) | 0x80;
 520           break;
 521         case 7:
 522           tmp = (tmp & 0x3f);
 523           break;
 524         case 11:
 525           tmp = (tmp & 0x3f) | 0x40;
 526           break;
 527         default:
 528           printk ("mad16/Mozart: Invalid MIDI IRQ\n");
 529           return 0;
 530         }
 531 
 532       mad_write (MC3_PORT, tmp | 0x04);
 533       return mad16_sb_dsp_detect (hw_config);
 534 #else
 535       return 0;
 536 #endif
 537     }
 538 
 539   tmp = 0x83;                   /* MPU-401 enable */
 540 
 541 /*
 542  * Set the MPU base bits
 543  */
 544 
 545   for (i = 0; i < 5; i++)
 546     {
 547       if (i > 3)                /* Out of array bounds */
 548         {
 549           printk ("MAD16 / Mozart: Invalid MIDI port 0x%x\n", hw_config->io_base);
 550           return 0;
 551         }
 552 
 553       if (valid_ports[i] == hw_config->io_base)
 554         {
 555           tmp |= i << 5;
 556           break;
 557         }
 558     }
 559 
 560 /*
 561  * Set the MPU IRQ bits
 562  */
 563 
 564   for (i = 0; i < 5; i++)
 565     {
 566       if (i > 3)                /* Out of array bounds */
 567         {
 568           printk ("MAD16 / Mozart: Invalid MIDI IRQ %d\n", hw_config->irq);
 569           return 0;
 570         }
 571 
 572       if (valid_irqs[i] == hw_config->irq)
 573         {
 574           tmp |= i << 3;
 575           break;
 576         }
 577     }
 578   mad_write (MC6_PORT, tmp);    /* Write MPU401 config */
 579 
 580   return probe_mpu401 (hw_config);
 581 #else
 582   return 0;
 583 #endif
 584 }
 585 
 586 void
 587 unload_mad16 (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 588 {
 589   ad1848_unload (hw_config->io_base + 4,
 590                  hw_config->irq,
 591                  hw_config->dma,
 592                  hw_config->dma2, 0);
 593   release_region (hw_config->io_base, 4);
 594 
 595 }
 596 
 597 void
 598 unload_mad16_mpu (struct address_info *hw_config)
     /* [previous][next][first][last][top][bottom][index][help] */
 599 {
 600 #if (!defined(EXCLUDE_MPU401) || !defined(EXCLUDE_MPU_EMU)) && !defined(EXCLUDE_MIDI)
 601   unload_mpu401 (hw_config);
 602 #endif
 603 }
 604 
 605 /* That's all folks */
 606 #endif

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