linux/sound/isa/opti9xx/opti92x-ad1848.c
<<
>>
Prefs
   1/*
   2    card-opti92x-ad1848.c - driver for OPTi 82c92x based soundcards.
   3    Copyright (C) 1998-2000 by Massimo Piccioni <dafastidio@libero.it>
   4
   5    Part of this code was developed at the Italian Ministry of Air Defence,
   6    Sixth Division (oh, che pace ...), Rome.
   7
   8    Thanks to Maria Grazia Pollarini, Salvatore Vassallo.
   9
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 2 of the License, or
  13    (at your option) any later version.
  14
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19
  20    You should have received a copy of the GNU General Public License
  21    along with this program; if not, write to the Free Software
  22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  23*/
  24
  25
  26#include <linux/init.h>
  27#include <linux/err.h>
  28#include <linux/isa.h>
  29#include <linux/delay.h>
  30#include <linux/pnp.h>
  31#include <linux/module.h>
  32#include <linux/io.h>
  33#include <asm/dma.h>
  34#include <sound/core.h>
  35#include <sound/tlv.h>
  36#include <sound/wss.h>
  37#include <sound/mpu401.h>
  38#include <sound/opl3.h>
  39#ifndef OPTi93X
  40#include <sound/opl4.h>
  41#endif
  42#define SNDRV_LEGACY_FIND_FREE_IOPORT
  43#define SNDRV_LEGACY_FIND_FREE_IRQ
  44#define SNDRV_LEGACY_FIND_FREE_DMA
  45#include <sound/initval.h>
  46
  47MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
  48MODULE_LICENSE("GPL");
  49#ifdef OPTi93X
  50MODULE_DESCRIPTION("OPTi93X");
  51MODULE_SUPPORTED_DEVICE("{{OPTi,82C931/3}}");
  52#else   /* OPTi93X */
  53#ifdef CS4231
  54MODULE_DESCRIPTION("OPTi92X - CS4231");
  55MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (CS4231)},"
  56                "{OPTi,82C925 (CS4231)}}");
  57#else   /* CS4231 */
  58MODULE_DESCRIPTION("OPTi92X - AD1848");
  59MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)},"
  60                "{OPTi,82C925 (AD1848)},"
  61                "{OAK,Mozart}}");
  62#endif  /* CS4231 */
  63#endif  /* OPTi93X */
  64
  65static int index = SNDRV_DEFAULT_IDX1;  /* Index 0-MAX */
  66static char *id = SNDRV_DEFAULT_STR1;           /* ID for this card */
  67//static bool enable = SNDRV_DEFAULT_ENABLE1;   /* Enable this card */
  68#ifdef CONFIG_PNP
  69static bool isapnp = true;                      /* Enable ISA PnP detection */
  70#endif
  71static long port = SNDRV_DEFAULT_PORT1;         /* 0x530,0xe80,0xf40,0x604 */
  72static long mpu_port = SNDRV_DEFAULT_PORT1;     /* 0x300,0x310,0x320,0x330 */
  73static long fm_port = SNDRV_DEFAULT_PORT1;      /* 0x388 */
  74static int irq = SNDRV_DEFAULT_IRQ1;            /* 5,7,9,10,11 */
  75static int mpu_irq = SNDRV_DEFAULT_IRQ1;        /* 5,7,9,10 */
  76static int dma1 = SNDRV_DEFAULT_DMA1;           /* 0,1,3 */
  77#if defined(CS4231) || defined(OPTi93X)
  78static int dma2 = SNDRV_DEFAULT_DMA1;           /* 0,1,3 */
  79#endif  /* CS4231 || OPTi93X */
  80
  81module_param(index, int, 0444);
  82MODULE_PARM_DESC(index, "Index value for opti9xx based soundcard.");
  83module_param(id, charp, 0444);
  84MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard.");
  85//module_param(enable, bool, 0444);
  86//MODULE_PARM_DESC(enable, "Enable opti9xx soundcard.");
  87#ifdef CONFIG_PNP
  88module_param(isapnp, bool, 0444);
  89MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
  90#endif
  91module_param_hw(port, long, ioport, 0444);
  92MODULE_PARM_DESC(port, "WSS port # for opti9xx driver.");
  93module_param_hw(mpu_port, long, ioport, 0444);
  94MODULE_PARM_DESC(mpu_port, "MPU-401 port # for opti9xx driver.");
  95module_param_hw(fm_port, long, ioport, 0444);
  96MODULE_PARM_DESC(fm_port, "FM port # for opti9xx driver.");
  97module_param_hw(irq, int, irq, 0444);
  98MODULE_PARM_DESC(irq, "WSS irq # for opti9xx driver.");
  99module_param_hw(mpu_irq, int, irq, 0444);
 100MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for opti9xx driver.");
 101module_param_hw(dma1, int, dma, 0444);
 102MODULE_PARM_DESC(dma1, "1st dma # for opti9xx driver.");
 103#if defined(CS4231) || defined(OPTi93X)
 104module_param_hw(dma2, int, dma, 0444);
 105MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
 106#endif  /* CS4231 || OPTi93X */
 107
 108#define OPTi9XX_HW_82C928       1
 109#define OPTi9XX_HW_82C929       2
 110#define OPTi9XX_HW_82C924       3
 111#define OPTi9XX_HW_82C925       4
 112#define OPTi9XX_HW_82C930       5
 113#define OPTi9XX_HW_82C931       6
 114#define OPTi9XX_HW_82C933       7
 115#define OPTi9XX_HW_LAST         OPTi9XX_HW_82C933
 116
 117#define OPTi9XX_MC_REG(n)       n
 118
 119#ifdef OPTi93X
 120
 121#define OPTi93X_STATUS                  0x02
 122#define OPTi93X_PORT(chip, r)           ((chip)->port + OPTi93X_##r)
 123
 124#define OPTi93X_IRQ_PLAYBACK            0x04
 125#define OPTi93X_IRQ_CAPTURE             0x08
 126
 127#endif /* OPTi93X */
 128
 129struct snd_opti9xx {
 130        unsigned short hardware;
 131        unsigned char password;
 132        char name[7];
 133
 134        unsigned long mc_base;
 135        struct resource *res_mc_base;
 136        unsigned long mc_base_size;
 137#ifdef OPTi93X
 138        unsigned long mc_indir_index;
 139        struct resource *res_mc_indir;
 140#endif  /* OPTi93X */
 141        struct snd_wss *codec;
 142        unsigned long pwd_reg;
 143
 144        spinlock_t lock;
 145
 146        long wss_base;
 147        int irq;
 148};
 149
 150static int snd_opti9xx_pnp_is_probed;
 151
 152#ifdef CONFIG_PNP
 153
 154static const struct pnp_card_device_id snd_opti9xx_pnpids[] = {
 155#ifndef OPTi93X
 156        /* OPTi 82C924 */
 157        { .id = "OPT0924",
 158          .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } },
 159          .driver_data = 0x0924 },
 160        /* OPTi 82C925 */
 161        { .id = "OPT0925",
 162          .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } },
 163          .driver_data = 0x0925 },
 164#else
 165        /* OPTi 82C931/3 */
 166        { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } },
 167          .driver_data = 0x0931 },
 168#endif  /* OPTi93X */
 169        { .id = "" }
 170};
 171
 172MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);
 173
 174#endif  /* CONFIG_PNP */
 175
 176#define DEV_NAME KBUILD_MODNAME
 177
 178static char * snd_opti9xx_names[] = {
 179        "unknown",
 180        "82C928",       "82C929",
 181        "82C924",       "82C925",
 182        "82C930",       "82C931",       "82C933"
 183};
 184
 185static int snd_opti9xx_init(struct snd_opti9xx *chip,
 186                            unsigned short hardware)
 187{
 188        static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
 189
 190        chip->hardware = hardware;
 191        strcpy(chip->name, snd_opti9xx_names[hardware]);
 192
 193        spin_lock_init(&chip->lock);
 194
 195        chip->irq = -1;
 196
 197#ifndef OPTi93X
 198#ifdef CONFIG_PNP
 199        if (isapnp && chip->mc_base)
 200                /* PnP resource gives the least 10 bits */
 201                chip->mc_base |= 0xc00;
 202        else
 203#endif  /* CONFIG_PNP */
 204        {
 205                chip->mc_base = 0xf8c;
 206                chip->mc_base_size = opti9xx_mc_size[hardware];
 207        }
 208#else
 209                chip->mc_base_size = opti9xx_mc_size[hardware];
 210#endif
 211
 212        switch (hardware) {
 213#ifndef OPTi93X
 214        case OPTi9XX_HW_82C928:
 215        case OPTi9XX_HW_82C929:
 216                chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3;
 217                chip->pwd_reg = 3;
 218                break;
 219
 220        case OPTi9XX_HW_82C924:
 221        case OPTi9XX_HW_82C925:
 222                chip->password = 0xe5;
 223                chip->pwd_reg = 3;
 224                break;
 225#else   /* OPTi93X */
 226
 227        case OPTi9XX_HW_82C930:
 228        case OPTi9XX_HW_82C931:
 229        case OPTi9XX_HW_82C933:
 230                chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d;
 231                if (!chip->mc_indir_index)
 232                        chip->mc_indir_index = 0xe0e;
 233                chip->password = 0xe4;
 234                chip->pwd_reg = 0;
 235                break;
 236#endif  /* OPTi93X */
 237
 238        default:
 239                snd_printk(KERN_ERR "chip %d not supported\n", hardware);
 240                return -ENODEV;
 241        }
 242        return 0;
 243}
 244
 245static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip,
 246                                      unsigned char reg)
 247{
 248        unsigned long flags;
 249        unsigned char retval = 0xff;
 250
 251        spin_lock_irqsave(&chip->lock, flags);
 252        outb(chip->password, chip->mc_base + chip->pwd_reg);
 253
 254        switch (chip->hardware) {
 255#ifndef OPTi93X
 256        case OPTi9XX_HW_82C924:
 257        case OPTi9XX_HW_82C925:
 258                if (reg > 7) {
 259                        outb(reg, chip->mc_base + 8);
 260                        outb(chip->password, chip->mc_base + chip->pwd_reg);
 261                        retval = inb(chip->mc_base + 9);
 262                        break;
 263                }
 264
 265        case OPTi9XX_HW_82C928:
 266        case OPTi9XX_HW_82C929:
 267                retval = inb(chip->mc_base + reg);
 268                break;
 269#else   /* OPTi93X */
 270
 271        case OPTi9XX_HW_82C930:
 272        case OPTi9XX_HW_82C931:
 273        case OPTi9XX_HW_82C933:
 274                outb(reg, chip->mc_indir_index);
 275                outb(chip->password, chip->mc_base + chip->pwd_reg);
 276                retval = inb(chip->mc_indir_index + 1);
 277                break;
 278#endif  /* OPTi93X */
 279
 280        default:
 281                snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
 282        }
 283
 284        spin_unlock_irqrestore(&chip->lock, flags);
 285        return retval;
 286}
 287
 288static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
 289                              unsigned char value)
 290{
 291        unsigned long flags;
 292
 293        spin_lock_irqsave(&chip->lock, flags);
 294        outb(chip->password, chip->mc_base + chip->pwd_reg);
 295
 296        switch (chip->hardware) {
 297#ifndef OPTi93X
 298        case OPTi9XX_HW_82C924:
 299        case OPTi9XX_HW_82C925:
 300                if (reg > 7) {
 301                        outb(reg, chip->mc_base + 8);
 302                        outb(chip->password, chip->mc_base + chip->pwd_reg);
 303                        outb(value, chip->mc_base + 9);
 304                        break;
 305                }
 306
 307        case OPTi9XX_HW_82C928:
 308        case OPTi9XX_HW_82C929:
 309                outb(value, chip->mc_base + reg);
 310                break;
 311#else   /* OPTi93X */
 312
 313        case OPTi9XX_HW_82C930:
 314        case OPTi9XX_HW_82C931:
 315        case OPTi9XX_HW_82C933:
 316                outb(reg, chip->mc_indir_index);
 317                outb(chip->password, chip->mc_base + chip->pwd_reg);
 318                outb(value, chip->mc_indir_index + 1);
 319                break;
 320#endif  /* OPTi93X */
 321
 322        default:
 323                snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
 324        }
 325
 326        spin_unlock_irqrestore(&chip->lock, flags);
 327}
 328
 329
 330#define snd_opti9xx_write_mask(chip, reg, value, mask)  \
 331        snd_opti9xx_write(chip, reg,                    \
 332                (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask)))
 333
 334
 335static int snd_opti9xx_configure(struct snd_opti9xx *chip,
 336                                           long port,
 337                                           int irq, int dma1, int dma2,
 338                                           long mpu_port, int mpu_irq)
 339{
 340        unsigned char wss_base_bits;
 341        unsigned char irq_bits;
 342        unsigned char dma_bits;
 343        unsigned char mpu_port_bits = 0;
 344        unsigned char mpu_irq_bits;
 345
 346        switch (chip->hardware) {
 347#ifndef OPTi93X
 348        case OPTi9XX_HW_82C924:
 349                /* opti 929 mode (?), OPL3 clock output, audio enable */
 350                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc);
 351                /* enable wave audio */
 352                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
 353
 354        case OPTi9XX_HW_82C925:
 355                /* enable WSS mode */
 356                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
 357                /* OPL3 FM synthesis */
 358                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
 359                /* disable Sound Blaster IRQ and DMA */
 360                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
 361#ifdef CS4231
 362                /* cs4231/4248 fix enabled */
 363                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
 364#else
 365                /* cs4231/4248 fix disabled */
 366                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
 367#endif  /* CS4231 */
 368                break;
 369
 370        case OPTi9XX_HW_82C928:
 371        case OPTi9XX_HW_82C929:
 372                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
 373                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
 374                /*
 375                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xa2, 0xae);
 376                */
 377                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);
 378#ifdef CS4231
 379                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
 380#else
 381                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
 382#endif  /* CS4231 */
 383                break;
 384
 385#else   /* OPTi93X */
 386        case OPTi9XX_HW_82C931:
 387                /* disable 3D sound (set GPIO1 as output, low) */
 388                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(20), 0x04, 0x0c);
 389        case OPTi9XX_HW_82C933: /* FALL THROUGH */
 390                /*
 391                 * The BTC 1817DW has QS1000 wavetable which is connected
 392                 * to the serial digital input of the OPTI931.
 393                 */
 394                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(21), 0x82, 0xff);
 395                /* 
 396                 * This bit sets OPTI931 to automaticaly select FM
 397                 * or digital input signal.
 398                 */
 399                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01);
 400        case OPTi9XX_HW_82C930: /* FALL THROUGH */
 401                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03);
 402                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff);
 403                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 |
 404                        (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04),
 405                        0x34);
 406                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf);
 407                break;
 408#endif  /* OPTi93X */
 409
 410        default:
 411                snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
 412                return -EINVAL;
 413        }
 414
 415        /* PnP resource says it decodes only 10 bits of address */
 416        switch (port & 0x3ff) {
 417        case 0x130:
 418                chip->wss_base = 0x530;
 419                wss_base_bits = 0x00;
 420                break;
 421        case 0x204:
 422                chip->wss_base = 0x604;
 423                wss_base_bits = 0x03;
 424                break;
 425        case 0x280:
 426                chip->wss_base = 0xe80;
 427                wss_base_bits = 0x01;
 428                break;
 429        case 0x340:
 430                chip->wss_base = 0xf40;
 431                wss_base_bits = 0x02;
 432                break;
 433        default:
 434                snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port);
 435                goto __skip_base;
 436        }
 437        snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
 438
 439__skip_base:
 440        switch (irq) {
 441//#ifdef OPTi93X
 442        case 5:
 443                irq_bits = 0x05;
 444                break;
 445//#endif        /* OPTi93X */
 446        case 7:
 447                irq_bits = 0x01;
 448                break;
 449        case 9:
 450                irq_bits = 0x02;
 451                break;
 452        case 10:
 453                irq_bits = 0x03;
 454                break;
 455        case 11:
 456                irq_bits = 0x04;
 457                break;
 458        default:
 459                snd_printk(KERN_WARNING "WSS irq # %d not valid\n", irq);
 460                goto __skip_resources;
 461        }
 462
 463        switch (dma1) {
 464        case 0:
 465                dma_bits = 0x01;
 466                break;
 467        case 1:
 468                dma_bits = 0x02;
 469                break;
 470        case 3:
 471                dma_bits = 0x03;
 472                break;
 473        default:
 474                snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n", dma1);
 475                goto __skip_resources;
 476        }
 477
 478#if defined(CS4231) || defined(OPTi93X)
 479        if (dma1 == dma2) {
 480                snd_printk(KERN_ERR "don't want to share dmas\n");
 481                return -EBUSY;
 482        }
 483
 484        switch (dma2) {
 485        case 0:
 486        case 1:
 487                break;
 488        default:
 489                snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n", dma2);
 490                goto __skip_resources;
 491        }
 492        dma_bits |= 0x04;
 493#endif  /* CS4231 || OPTi93X */
 494
 495#ifndef OPTi93X
 496         outb(irq_bits << 3 | dma_bits, chip->wss_base);
 497#else /* OPTi93X */
 498        snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
 499#endif /* OPTi93X */
 500
 501__skip_resources:
 502        if (chip->hardware > OPTi9XX_HW_82C928) {
 503                switch (mpu_port) {
 504                case 0:
 505                case -1:
 506                        break;
 507                case 0x300:
 508                        mpu_port_bits = 0x03;
 509                        break;
 510                case 0x310:
 511                        mpu_port_bits = 0x02;
 512                        break;
 513                case 0x320:
 514                        mpu_port_bits = 0x01;
 515                        break;
 516                case 0x330:
 517                        mpu_port_bits = 0x00;
 518                        break;
 519                default:
 520                        snd_printk(KERN_WARNING
 521                                   "MPU-401 port 0x%lx not valid\n", mpu_port);
 522                        goto __skip_mpu;
 523                }
 524
 525                switch (mpu_irq) {
 526                case 5:
 527                        mpu_irq_bits = 0x02;
 528                        break;
 529                case 7:
 530                        mpu_irq_bits = 0x03;
 531                        break;
 532                case 9:
 533                        mpu_irq_bits = 0x00;
 534                        break;
 535                case 10:
 536                        mpu_irq_bits = 0x01;
 537                        break;
 538                default:
 539                        snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n",
 540                                mpu_irq);
 541                        goto __skip_mpu;
 542                }
 543
 544                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6),
 545                        (mpu_port <= 0) ? 0x00 :
 546                                0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
 547                        0xf8);
 548        }
 549__skip_mpu:
 550
 551        return 0;
 552}
 553
 554#ifdef OPTi93X
 555
 556static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_step, -9300, 300, 0);
 557static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
 558static const DECLARE_TLV_DB_SCALE(db_scale_4bit_12db_max, -3300, 300, 0);
 559
 560static struct snd_kcontrol_new snd_opti93x_controls[] = {
 561WSS_DOUBLE("Master Playback Switch", 0,
 562                OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
 563WSS_DOUBLE_TLV("Master Playback Volume", 0,
 564                OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1,
 565                db_scale_5bit_3db_step),
 566WSS_DOUBLE_TLV("PCM Playback Volume", 0,
 567                CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1,
 568                db_scale_5bit),
 569WSS_DOUBLE_TLV("FM Playback Volume", 0,
 570                CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1,
 571                db_scale_4bit_12db_max),
 572WSS_DOUBLE("Line Playback Switch", 0,
 573                CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
 574WSS_DOUBLE_TLV("Line Playback Volume", 0,
 575                CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1,
 576                db_scale_4bit_12db_max),
 577WSS_DOUBLE("Mic Playback Switch", 0,
 578                OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
 579WSS_DOUBLE_TLV("Mic Playback Volume", 0,
 580                OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1,
 581                db_scale_4bit_12db_max),
 582WSS_DOUBLE_TLV("CD Playback Volume", 0,
 583                CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1,
 584                db_scale_4bit_12db_max),
 585WSS_DOUBLE("Aux Playback Switch", 0,
 586                OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
 587WSS_DOUBLE_TLV("Aux Playback Volume", 0,
 588                OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1,
 589                db_scale_4bit_12db_max),
 590};
 591
 592static int snd_opti93x_mixer(struct snd_wss *chip)
 593{
 594        struct snd_card *card;
 595        unsigned int idx;
 596        struct snd_ctl_elem_id id1, id2;
 597        int err;
 598
 599        if (snd_BUG_ON(!chip || !chip->pcm))
 600                return -EINVAL;
 601
 602        card = chip->card;
 603
 604        strcpy(card->mixername, chip->pcm->name);
 605
 606        memset(&id1, 0, sizeof(id1));
 607        memset(&id2, 0, sizeof(id2));
 608        id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 609        /* reassign AUX0 switch to CD */
 610        strcpy(id1.name, "Aux Playback Switch");
 611        strcpy(id2.name, "CD Playback Switch");
 612        err = snd_ctl_rename_id(card, &id1, &id2);
 613        if (err < 0) {
 614                snd_printk(KERN_ERR "Cannot rename opti93x control\n");
 615                return err;
 616        }
 617        /* reassign AUX1 switch to FM */
 618        strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
 619        strcpy(id2.name, "FM Playback Switch");
 620        err = snd_ctl_rename_id(card, &id1, &id2);
 621        if (err < 0) {
 622                snd_printk(KERN_ERR "Cannot rename opti93x control\n");
 623                return err;
 624        }
 625        /* remove AUX1 volume */
 626        strcpy(id1.name, "Aux Playback Volume"); id1.index = 1;
 627        snd_ctl_remove_id(card, &id1);
 628
 629        /* Replace WSS volume controls with OPTi93x volume controls */
 630        id1.index = 0;
 631        for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
 632                strcpy(id1.name, snd_opti93x_controls[idx].name);
 633                snd_ctl_remove_id(card, &id1);
 634
 635                err = snd_ctl_add(card,
 636                                snd_ctl_new1(&snd_opti93x_controls[idx], chip));
 637                if (err < 0)
 638                        return err;
 639        }
 640        return 0;
 641}
 642
 643static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
 644{
 645        struct snd_opti9xx *chip = dev_id;
 646        struct snd_wss *codec = chip->codec;
 647        unsigned char status;
 648
 649        if (!codec)
 650                return IRQ_HANDLED;
 651
 652        status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11));
 653        if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
 654                snd_pcm_period_elapsed(codec->playback_substream);
 655        if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) {
 656                snd_wss_overrange(codec);
 657                snd_pcm_period_elapsed(codec->capture_substream);
 658        }
 659        outb(0x00, OPTi93X_PORT(codec, STATUS));
 660        return IRQ_HANDLED;
 661}
 662
 663#endif /* OPTi93X */
 664
 665static int snd_opti9xx_read_check(struct snd_opti9xx *chip)
 666{
 667        unsigned char value;
 668#ifdef OPTi93X
 669        unsigned long flags;
 670#endif
 671
 672        chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
 673                                           "OPTi9xx MC");
 674        if (chip->res_mc_base == NULL)
 675                return -EBUSY;
 676#ifndef OPTi93X
 677        value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1));
 678        if (value != 0xff && value != inb(chip->mc_base + OPTi9XX_MC_REG(1)))
 679                if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)))
 680                        return 0;
 681#else   /* OPTi93X */
 682        chip->res_mc_indir = request_region(chip->mc_indir_index, 2,
 683                                            "OPTi93x MC");
 684        if (chip->res_mc_indir == NULL)
 685                return -EBUSY;
 686
 687        spin_lock_irqsave(&chip->lock, flags);
 688        outb(chip->password, chip->mc_base + chip->pwd_reg);
 689        outb(((chip->mc_indir_index & 0x1f0) >> 4), chip->mc_base);
 690        spin_unlock_irqrestore(&chip->lock, flags);
 691
 692        value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7));
 693        snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value);
 694        if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value)
 695                return 0;
 696
 697        release_and_free_resource(chip->res_mc_indir);
 698        chip->res_mc_indir = NULL;
 699#endif  /* OPTi93X */
 700        release_and_free_resource(chip->res_mc_base);
 701        chip->res_mc_base = NULL;
 702
 703        return -ENODEV;
 704}
 705
 706static int snd_card_opti9xx_detect(struct snd_card *card,
 707                                   struct snd_opti9xx *chip)
 708{
 709        int i, err;
 710
 711#ifndef OPTi93X
 712        for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) {
 713#else
 714        for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) {
 715#endif
 716                err = snd_opti9xx_init(chip, i);
 717                if (err < 0)
 718                        return err;
 719
 720                err = snd_opti9xx_read_check(chip);
 721                if (err == 0)
 722                        return 1;
 723#ifdef OPTi93X
 724                chip->mc_indir_index = 0;
 725#endif
 726        }
 727        return -ENODEV;
 728}
 729
 730#ifdef CONFIG_PNP
 731static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
 732                                struct pnp_card_link *card,
 733                                const struct pnp_card_device_id *pid)
 734{
 735        struct pnp_dev *pdev;
 736        int err;
 737        struct pnp_dev *devmpu;
 738#ifndef OPTi93X
 739        struct pnp_dev *devmc;
 740#endif
 741
 742        pdev = pnp_request_card_device(card, pid->devs[0].id, NULL);
 743        if (pdev == NULL)
 744                return -EBUSY;
 745
 746        err = pnp_activate_dev(pdev);
 747        if (err < 0) {
 748                snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);
 749                return err;
 750        }
 751
 752#ifdef OPTi93X
 753        port = pnp_port_start(pdev, 0) - 4;
 754        fm_port = pnp_port_start(pdev, 1) + 8;
 755        /* adjust mc_indir_index - some cards report it at 0xe?d,
 756           other at 0xe?c but it really is always at 0xe?e */
 757        chip->mc_indir_index = (pnp_port_start(pdev, 3) & ~0xf) | 0xe;
 758#else
 759        devmc = pnp_request_card_device(card, pid->devs[2].id, NULL);
 760        if (devmc == NULL)
 761                return -EBUSY;
 762
 763        err = pnp_activate_dev(devmc);
 764        if (err < 0) {
 765                snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err);
 766                return err;
 767        }
 768
 769        port = pnp_port_start(pdev, 1);
 770        fm_port = pnp_port_start(pdev, 2) + 8;
 771        /*
 772         * The MC(0) is never accessed and card does not
 773         * include it in the PnP resource range. OPTI93x include it.
 774         */
 775        chip->mc_base = pnp_port_start(devmc, 0) - 1;
 776        chip->mc_base_size = pnp_port_len(devmc, 0) + 1;
 777#endif  /* OPTi93X */
 778        irq = pnp_irq(pdev, 0);
 779        dma1 = pnp_dma(pdev, 0);
 780#if defined(CS4231) || defined(OPTi93X)
 781        dma2 = pnp_dma(pdev, 1);
 782#endif  /* CS4231 || OPTi93X */
 783
 784        devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
 785
 786        if (devmpu && mpu_port > 0) {
 787                err = pnp_activate_dev(devmpu);
 788                if (err < 0) {
 789                        snd_printk(KERN_ERR "MPU401 pnp configure failure\n");
 790                        mpu_port = -1;
 791                } else {
 792                        mpu_port = pnp_port_start(devmpu, 0);
 793                        mpu_irq = pnp_irq(devmpu, 0);
 794                }
 795        }
 796        return pid->driver_data;
 797}
 798#endif  /* CONFIG_PNP */
 799
 800static void snd_card_opti9xx_free(struct snd_card *card)
 801{
 802        struct snd_opti9xx *chip = card->private_data;
 803
 804        if (chip) {
 805#ifdef OPTi93X
 806                if (chip->irq > 0) {
 807                        disable_irq(chip->irq);
 808                        free_irq(chip->irq, chip);
 809                }
 810                release_and_free_resource(chip->res_mc_indir);
 811#endif
 812                release_and_free_resource(chip->res_mc_base);
 813        }
 814}
 815
 816static int snd_opti9xx_probe(struct snd_card *card)
 817{
 818        static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
 819        int error;
 820        int xdma2;
 821        struct snd_opti9xx *chip = card->private_data;
 822        struct snd_wss *codec;
 823        struct snd_rawmidi *rmidi;
 824        struct snd_hwdep *synth;
 825
 826#if defined(CS4231) || defined(OPTi93X)
 827        xdma2 = dma2;
 828#else
 829        xdma2 = -1;
 830#endif
 831
 832        if (port == SNDRV_AUTO_PORT) {
 833                port = snd_legacy_find_free_ioport(possible_ports, 4);
 834                if (port < 0) {
 835                        snd_printk(KERN_ERR "unable to find a free WSS port\n");
 836                        return -EBUSY;
 837                }
 838        }
 839        error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2,
 840                                      mpu_port, mpu_irq);
 841        if (error)
 842                return error;
 843
 844        error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2,
 845#ifdef OPTi93X
 846                               WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
 847#else
 848                               WSS_HW_DETECT, 0,
 849#endif
 850                               &codec);
 851        if (error < 0)
 852                return error;
 853        chip->codec = codec;
 854        error = snd_wss_pcm(codec, 0);
 855        if (error < 0)
 856                return error;
 857        error = snd_wss_mixer(codec);
 858        if (error < 0)
 859                return error;
 860#ifdef OPTi93X
 861        error = snd_opti93x_mixer(codec);
 862        if (error < 0)
 863                return error;
 864#endif
 865#ifdef CS4231
 866        error = snd_wss_timer(codec, 0);
 867        if (error < 0)
 868                return error;
 869#endif
 870#ifdef OPTi93X
 871        error = request_irq(irq, snd_opti93x_interrupt,
 872                            0, DEV_NAME" - WSS", chip);
 873        if (error < 0) {
 874                snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq);
 875                return error;
 876        }
 877#endif
 878        chip->irq = irq;
 879        strcpy(card->driver, chip->name);
 880        sprintf(card->shortname, "OPTi %s", card->driver);
 881#if defined(CS4231) || defined(OPTi93X)
 882        snprintf(card->longname, sizeof(card->longname),
 883                 "%s, %s at 0x%lx, irq %d, dma %d&%d",
 884                 card->shortname, codec->pcm->name,
 885                 chip->wss_base + 4, irq, dma1, xdma2);
 886#else
 887        snprintf(card->longname, sizeof(card->longname),
 888                 "%s, %s at 0x%lx, irq %d, dma %d",
 889                 card->shortname, codec->pcm->name, chip->wss_base + 4, irq,
 890                 dma1);
 891#endif  /* CS4231 || OPTi93X */
 892
 893        if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
 894                rmidi = NULL;
 895        else {
 896                error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
 897                                mpu_port, 0, mpu_irq, &rmidi);
 898                if (error)
 899                        snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
 900                                   mpu_port);
 901        }
 902
 903        if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) {
 904                struct snd_opl3 *opl3 = NULL;
 905#ifndef OPTi93X
 906                if (chip->hardware == OPTi9XX_HW_82C928 ||
 907                    chip->hardware == OPTi9XX_HW_82C929 ||
 908                    chip->hardware == OPTi9XX_HW_82C924) {
 909                        struct snd_opl4 *opl4;
 910                        /* assume we have an OPL4 */
 911                        snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
 912                                               0x20, 0x20);
 913                        if (snd_opl4_create(card, fm_port, fm_port - 8,
 914                                            2, &opl3, &opl4) < 0) {
 915                                /* no luck, use OPL3 instead */
 916                                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
 917                                                       0x00, 0x20);
 918                        }
 919                }
 920#endif  /* !OPTi93X */
 921                if (!opl3 && snd_opl3_create(card, fm_port, fm_port + 2,
 922                                             OPL3_HW_AUTO, 0, &opl3) < 0) {
 923                        snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n",
 924                                   fm_port, fm_port + 4 - 1);
 925                }
 926                if (opl3) {
 927                        error = snd_opl3_hwdep_new(opl3, 0, 1, &synth);
 928                        if (error < 0)
 929                                return error;
 930                }
 931        }
 932
 933        return snd_card_register(card);
 934}
 935
 936static int snd_opti9xx_card_new(struct device *pdev, struct snd_card **cardp)
 937{
 938        struct snd_card *card;
 939        int err;
 940
 941        err = snd_card_new(pdev, index, id, THIS_MODULE,
 942                           sizeof(struct snd_opti9xx), &card);
 943        if (err < 0)
 944                return err;
 945        card->private_free = snd_card_opti9xx_free;
 946        *cardp = card;
 947        return 0;
 948}
 949
 950static int snd_opti9xx_isa_match(struct device *devptr,
 951                                 unsigned int dev)
 952{
 953#ifdef CONFIG_PNP
 954        if (snd_opti9xx_pnp_is_probed)
 955                return 0;
 956        if (isapnp)
 957                return 0;
 958#endif
 959        return 1;
 960}
 961
 962static int snd_opti9xx_isa_probe(struct device *devptr,
 963                                 unsigned int dev)
 964{
 965        struct snd_card *card;
 966        int error;
 967        static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
 968#ifdef OPTi93X
 969        static int possible_irqs[] = {5, 9, 10, 11, 7, -1};
 970#else
 971        static int possible_irqs[] = {9, 10, 11, 7, -1};
 972#endif  /* OPTi93X */
 973        static int possible_mpu_irqs[] = {5, 9, 10, 7, -1};
 974        static int possible_dma1s[] = {3, 1, 0, -1};
 975#if defined(CS4231) || defined(OPTi93X)
 976        static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
 977#endif  /* CS4231 || OPTi93X */
 978
 979        if (mpu_port == SNDRV_AUTO_PORT) {
 980                if ((mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
 981                        snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
 982                        return -EBUSY;
 983                }
 984        }
 985        if (irq == SNDRV_AUTO_IRQ) {
 986                if ((irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
 987                        snd_printk(KERN_ERR "unable to find a free IRQ\n");
 988                        return -EBUSY;
 989                }
 990        }
 991        if (mpu_irq == SNDRV_AUTO_IRQ) {
 992                if ((mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
 993                        snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n");
 994                        return -EBUSY;
 995                }
 996        }
 997        if (dma1 == SNDRV_AUTO_DMA) {
 998                if ((dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
 999                        snd_printk(KERN_ERR "unable to find a free DMA1\n");
1000                        return -EBUSY;
1001                }
1002        }
1003#if defined(CS4231) || defined(OPTi93X)
1004        if (dma2 == SNDRV_AUTO_DMA) {
1005                if ((dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4])) < 0) {
1006                        snd_printk(KERN_ERR "unable to find a free DMA2\n");
1007                        return -EBUSY;
1008                }
1009        }
1010#endif
1011
1012        error = snd_opti9xx_card_new(devptr, &card);
1013        if (error < 0)
1014                return error;
1015
1016        if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) {
1017                snd_card_free(card);
1018                return error;
1019        }
1020        if ((error = snd_opti9xx_probe(card)) < 0) {
1021                snd_card_free(card);
1022                return error;
1023        }
1024        dev_set_drvdata(devptr, card);
1025        return 0;
1026}
1027
1028static int snd_opti9xx_isa_remove(struct device *devptr,
1029                                  unsigned int dev)
1030{
1031        snd_card_free(dev_get_drvdata(devptr));
1032        return 0;
1033}
1034
1035#ifdef CONFIG_PM
1036static int snd_opti9xx_suspend(struct snd_card *card)
1037{
1038        struct snd_opti9xx *chip = card->private_data;
1039
1040        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
1041        chip->codec->suspend(chip->codec);
1042        return 0;
1043}
1044
1045static int snd_opti9xx_resume(struct snd_card *card)
1046{
1047        struct snd_opti9xx *chip = card->private_data;
1048        int error, xdma2;
1049#if defined(CS4231) || defined(OPTi93X)
1050        xdma2 = dma2;
1051#else
1052        xdma2 = -1;
1053#endif
1054
1055        error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2,
1056                                      mpu_port, mpu_irq);
1057        if (error)
1058                return error;
1059        chip->codec->resume(chip->codec);
1060        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
1061        return 0;
1062}
1063
1064static int snd_opti9xx_isa_suspend(struct device *dev, unsigned int n,
1065                                   pm_message_t state)
1066{
1067        return snd_opti9xx_suspend(dev_get_drvdata(dev));
1068}
1069
1070static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n)
1071{
1072        return snd_opti9xx_resume(dev_get_drvdata(dev));
1073}
1074#endif
1075
1076static struct isa_driver snd_opti9xx_driver = {
1077        .match          = snd_opti9xx_isa_match,
1078        .probe          = snd_opti9xx_isa_probe,
1079        .remove         = snd_opti9xx_isa_remove,
1080#ifdef CONFIG_PM
1081        .suspend        = snd_opti9xx_isa_suspend,
1082        .resume         = snd_opti9xx_isa_resume,
1083#endif
1084        .driver         = {
1085                .name   = DEV_NAME
1086        },
1087};
1088
1089#ifdef CONFIG_PNP
1090static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
1091                                 const struct pnp_card_device_id *pid)
1092{
1093        struct snd_card *card;
1094        int error, hw;
1095        struct snd_opti9xx *chip;
1096
1097        if (snd_opti9xx_pnp_is_probed)
1098                return -EBUSY;
1099        if (! isapnp)
1100                return -ENODEV;
1101        error = snd_opti9xx_card_new(&pcard->card->dev, &card);
1102        if (error < 0)
1103                return error;
1104        chip = card->private_data;
1105
1106        hw = snd_card_opti9xx_pnp(chip, pcard, pid);
1107        switch (hw) {
1108        case 0x0924:
1109                hw = OPTi9XX_HW_82C924;
1110                break;
1111        case 0x0925:
1112                hw = OPTi9XX_HW_82C925;
1113                break;
1114        case 0x0931:
1115                hw = OPTi9XX_HW_82C931;
1116                break;
1117        default:
1118                snd_card_free(card);
1119                return -ENODEV;
1120        }
1121
1122        if ((error = snd_opti9xx_init(chip, hw))) {
1123                snd_card_free(card);
1124                return error;
1125        }
1126        error = snd_opti9xx_read_check(chip);
1127        if (error) {
1128                snd_printk(KERN_ERR "OPTI chip not found\n");
1129                snd_card_free(card);
1130                return error;
1131        }
1132        if ((error = snd_opti9xx_probe(card)) < 0) {
1133                snd_card_free(card);
1134                return error;
1135        }
1136        pnp_set_card_drvdata(pcard, card);
1137        snd_opti9xx_pnp_is_probed = 1;
1138        return 0;
1139}
1140
1141static void snd_opti9xx_pnp_remove(struct pnp_card_link *pcard)
1142{
1143        snd_card_free(pnp_get_card_drvdata(pcard));
1144        pnp_set_card_drvdata(pcard, NULL);
1145        snd_opti9xx_pnp_is_probed = 0;
1146}
1147
1148#ifdef CONFIG_PM
1149static int snd_opti9xx_pnp_suspend(struct pnp_card_link *pcard,
1150                                   pm_message_t state)
1151{
1152        return snd_opti9xx_suspend(pnp_get_card_drvdata(pcard));
1153}
1154
1155static int snd_opti9xx_pnp_resume(struct pnp_card_link *pcard)
1156{
1157        return snd_opti9xx_resume(pnp_get_card_drvdata(pcard));
1158}
1159#endif
1160
1161static struct pnp_card_driver opti9xx_pnpc_driver = {
1162        .flags          = PNP_DRIVER_RES_DISABLE,
1163        .name           = DEV_NAME,
1164        .id_table       = snd_opti9xx_pnpids,
1165        .probe          = snd_opti9xx_pnp_probe,
1166        .remove         = snd_opti9xx_pnp_remove,
1167#ifdef CONFIG_PM
1168        .suspend        = snd_opti9xx_pnp_suspend,
1169        .resume         = snd_opti9xx_pnp_resume,
1170#endif
1171};
1172#endif
1173
1174#ifdef OPTi93X
1175#define CHIP_NAME       "82C93x"
1176#else
1177#define CHIP_NAME       "82C92x"
1178#endif
1179
1180static int __init alsa_card_opti9xx_init(void)
1181{
1182#ifdef CONFIG_PNP
1183        pnp_register_card_driver(&opti9xx_pnpc_driver);
1184        if (snd_opti9xx_pnp_is_probed)
1185                return 0;
1186        pnp_unregister_card_driver(&opti9xx_pnpc_driver);
1187#endif
1188        return isa_register_driver(&snd_opti9xx_driver, 1);
1189}
1190
1191static void __exit alsa_card_opti9xx_exit(void)
1192{
1193        if (!snd_opti9xx_pnp_is_probed) {
1194                isa_unregister_driver(&snd_opti9xx_driver);
1195                return;
1196        }
1197#ifdef CONFIG_PNP
1198        pnp_unregister_card_driver(&opti9xx_pnpc_driver);
1199#endif
1200}
1201
1202module_init(alsa_card_opti9xx_init)
1203module_exit(alsa_card_opti9xx_exit)
1204