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/slab.h>
  31#include <linux/pnp.h>
  32#include <linux/moduleparam.h>
  33#include <asm/io.h>
  34#include <asm/dma.h>
  35#include <sound/core.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_IRQ
  43#define SNDRV_LEGACY_FIND_FREE_DMA
  44#include <sound/initval.h>
  45
  46MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
  47MODULE_LICENSE("GPL");
  48#ifdef OPTi93X
  49MODULE_DESCRIPTION("OPTi93X");
  50MODULE_SUPPORTED_DEVICE("{{OPTi,82C931/3}}");
  51#else   /* OPTi93X */
  52#ifdef CS4231
  53MODULE_DESCRIPTION("OPTi92X - CS4231");
  54MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (CS4231)},"
  55                "{OPTi,82C925 (CS4231)}}");
  56#else   /* CS4231 */
  57MODULE_DESCRIPTION("OPTi92X - AD1848");
  58MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)},"
  59                "{OPTi,82C925 (AD1848)},"
  60                "{OAK,Mozart}}");
  61#endif  /* CS4231 */
  62#endif  /* OPTi93X */
  63
  64static int index = SNDRV_DEFAULT_IDX1;  /* Index 0-MAX */
  65static char *id = SNDRV_DEFAULT_STR1;           /* ID for this card */
  66//static int enable = SNDRV_DEFAULT_ENABLE1;    /* Enable this card */
  67#ifdef CONFIG_PNP
  68static int isapnp = 1;                  /* Enable ISA PnP detection */
  69#endif
  70static long port = SNDRV_DEFAULT_PORT1;         /* 0x530,0xe80,0xf40,0x604 */
  71static long mpu_port = SNDRV_DEFAULT_PORT1;     /* 0x300,0x310,0x320,0x330 */
  72static long fm_port = SNDRV_DEFAULT_PORT1;      /* 0x388 */
  73static int irq = SNDRV_DEFAULT_IRQ1;            /* 5,7,9,10,11 */
  74static int mpu_irq = SNDRV_DEFAULT_IRQ1;        /* 5,7,9,10 */
  75static int dma1 = SNDRV_DEFAULT_DMA1;           /* 0,1,3 */
  76#if defined(CS4231) || defined(OPTi93X)
  77static int dma2 = SNDRV_DEFAULT_DMA1;           /* 0,1,3 */
  78#endif  /* CS4231 || OPTi93X */
  79
  80module_param(index, int, 0444);
  81MODULE_PARM_DESC(index, "Index value for opti9xx based soundcard.");
  82module_param(id, charp, 0444);
  83MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard.");
  84//module_param(enable, bool, 0444);
  85//MODULE_PARM_DESC(enable, "Enable opti9xx soundcard.");
  86#ifdef CONFIG_PNP
  87module_param(isapnp, bool, 0444);
  88MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
  89#endif
  90module_param(port, long, 0444);
  91MODULE_PARM_DESC(port, "WSS port # for opti9xx driver.");
  92module_param(mpu_port, long, 0444);
  93MODULE_PARM_DESC(mpu_port, "MPU-401 port # for opti9xx driver.");
  94module_param(fm_port, long, 0444);
  95MODULE_PARM_DESC(fm_port, "FM port # for opti9xx driver.");
  96module_param(irq, int, 0444);
  97MODULE_PARM_DESC(irq, "WSS irq # for opti9xx driver.");
  98module_param(mpu_irq, int, 0444);
  99MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for opti9xx driver.");
 100module_param(dma1, int, 0444);
 101MODULE_PARM_DESC(dma1, "1st dma # for opti9xx driver.");
 102#if defined(CS4231) || defined(OPTi93X)
 103module_param(dma2, int, 0444);
 104MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
 105#endif  /* CS4231 || OPTi93X */
 106
 107#define OPTi9XX_HW_82C928       1
 108#define OPTi9XX_HW_82C929       2
 109#define OPTi9XX_HW_82C924       3
 110#define OPTi9XX_HW_82C925       4
 111#define OPTi9XX_HW_82C930       5
 112#define OPTi9XX_HW_82C931       6
 113#define OPTi9XX_HW_82C933       7
 114#define OPTi9XX_HW_LAST         OPTi9XX_HW_82C933
 115
 116#define OPTi9XX_MC_REG(n)       n
 117
 118#ifdef OPTi93X
 119
 120#define OPTi93X_STATUS                  0x02
 121#define OPTi93X_PORT(chip, r)           ((chip)->port + OPTi93X_##r)
 122
 123#define OPTi93X_IRQ_PLAYBACK            0x04
 124#define OPTi93X_IRQ_CAPTURE             0x08
 125
 126#endif /* OPTi93X */
 127
 128struct snd_opti9xx {
 129        unsigned short hardware;
 130        unsigned char password;
 131        char name[7];
 132
 133        unsigned long mc_base;
 134        struct resource *res_mc_base;
 135        unsigned long mc_base_size;
 136#ifdef OPTi93X
 137        unsigned long mc_indir_index;
 138        struct snd_wss *codec;
 139#endif  /* OPTi93X */
 140        unsigned long pwd_reg;
 141
 142        spinlock_t lock;
 143
 144        long wss_base;
 145        int irq;
 146        int dma1;
 147        int dma2;
 148
 149        long fm_port;
 150
 151        long mpu_port;
 152        int mpu_irq;
 153
 154#ifdef CONFIG_PNP
 155        struct pnp_dev *dev;
 156        struct pnp_dev *devmpu;
 157#endif  /* CONFIG_PNP */
 158};
 159
 160static int snd_opti9xx_pnp_is_probed;
 161
 162#ifdef CONFIG_PNP
 163
 164static struct pnp_card_device_id snd_opti9xx_pnpids[] = {
 165#ifndef OPTi93X
 166        /* OPTi 82C924 */
 167        { .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 },
 168        /* OPTi 82C925 */
 169        { .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 },
 170#else
 171        /* OPTi 82C931/3 */
 172        { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 },
 173#endif  /* OPTi93X */
 174        { .id = "" }
 175};
 176
 177MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);
 178
 179#endif  /* CONFIG_PNP */
 180
 181#ifdef OPTi93X
 182#define DEV_NAME "opti93x"
 183#else
 184#define DEV_NAME "opti92x"
 185#endif
 186
 187static char * snd_opti9xx_names[] = {
 188        "unkown",
 189        "82C928",       "82C929",
 190        "82C924",       "82C925",
 191        "82C930",       "82C931",       "82C933"
 192};
 193
 194
 195static long __devinit snd_legacy_find_free_ioport(long *port_table, long size)
 196{
 197        while (*port_table != -1) {
 198                if (request_region(*port_table, size, "ALSA test")) {
 199                        release_region(*port_table, size);
 200                        return *port_table;
 201                }
 202                port_table++;
 203        }
 204        return -1;
 205}
 206
 207static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
 208                                      unsigned short hardware)
 209{
 210        static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
 211
 212        chip->hardware = hardware;
 213        strcpy(chip->name, snd_opti9xx_names[hardware]);
 214
 215        chip->mc_base_size = opti9xx_mc_size[hardware];  
 216
 217        spin_lock_init(&chip->lock);
 218
 219        chip->wss_base = -1;
 220        chip->irq = -1;
 221        chip->dma1 = -1;
 222        chip->dma2 = -1;
 223        chip->fm_port = -1;
 224        chip->mpu_port = -1;
 225        chip->mpu_irq = -1;
 226
 227        switch (hardware) {
 228#ifndef OPTi93X
 229        case OPTi9XX_HW_82C928:
 230        case OPTi9XX_HW_82C929:
 231                chip->mc_base = 0xf8c;
 232                chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3;
 233                chip->pwd_reg = 3;
 234                break;
 235
 236        case OPTi9XX_HW_82C924:
 237        case OPTi9XX_HW_82C925:
 238                chip->mc_base = 0xf8c;
 239                chip->password = 0xe5;
 240                chip->pwd_reg = 3;
 241                break;
 242#else   /* OPTi93X */
 243
 244        case OPTi9XX_HW_82C930:
 245        case OPTi9XX_HW_82C931:
 246        case OPTi9XX_HW_82C933:
 247                chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d;
 248                chip->mc_indir_index = 0xe0e;
 249                chip->password = 0xe4;
 250                chip->pwd_reg = 0;
 251                break;
 252#endif  /* OPTi93X */
 253
 254        default:
 255                snd_printk(KERN_ERR "chip %d not supported\n", hardware);
 256                return -ENODEV;
 257        }
 258        return 0;
 259}
 260
 261static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip,
 262                                      unsigned char reg)
 263{
 264        unsigned long flags;
 265        unsigned char retval = 0xff;
 266
 267        spin_lock_irqsave(&chip->lock, flags);
 268        outb(chip->password, chip->mc_base + chip->pwd_reg);
 269
 270        switch (chip->hardware) {
 271#ifndef OPTi93X
 272        case OPTi9XX_HW_82C924:
 273        case OPTi9XX_HW_82C925:
 274                if (reg > 7) {
 275                        outb(reg, chip->mc_base + 8);
 276                        outb(chip->password, chip->mc_base + chip->pwd_reg);
 277                        retval = inb(chip->mc_base + 9);
 278                        break;
 279                }
 280
 281        case OPTi9XX_HW_82C928:
 282        case OPTi9XX_HW_82C929:
 283                retval = inb(chip->mc_base + reg);
 284                break;
 285#else   /* OPTi93X */
 286
 287        case OPTi9XX_HW_82C930:
 288        case OPTi9XX_HW_82C931:
 289        case OPTi9XX_HW_82C933:
 290                outb(reg, chip->mc_indir_index);
 291                outb(chip->password, chip->mc_base + chip->pwd_reg);
 292                retval = inb(chip->mc_indir_index + 1);
 293                break;
 294#endif  /* OPTi93X */
 295
 296        default:
 297                snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
 298        }
 299
 300        spin_unlock_irqrestore(&chip->lock, flags);
 301        return retval;
 302}
 303        
 304static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
 305                              unsigned char value)
 306{
 307        unsigned long flags;
 308
 309        spin_lock_irqsave(&chip->lock, flags);
 310        outb(chip->password, chip->mc_base + chip->pwd_reg);
 311
 312        switch (chip->hardware) {
 313#ifndef OPTi93X
 314        case OPTi9XX_HW_82C924:
 315        case OPTi9XX_HW_82C925:
 316                if (reg > 7) {
 317                        outb(reg, chip->mc_base + 8);
 318                        outb(chip->password, chip->mc_base + chip->pwd_reg);
 319                        outb(value, chip->mc_base + 9);
 320                        break;
 321                }
 322
 323        case OPTi9XX_HW_82C928:
 324        case OPTi9XX_HW_82C929:
 325                outb(value, chip->mc_base + reg);
 326                break;
 327#else   /* OPTi93X */
 328
 329        case OPTi9XX_HW_82C930:
 330        case OPTi9XX_HW_82C931:
 331        case OPTi9XX_HW_82C933:
 332                outb(reg, chip->mc_indir_index);
 333                outb(chip->password, chip->mc_base + chip->pwd_reg);
 334                outb(value, chip->mc_indir_index + 1);
 335                break;
 336#endif  /* OPTi93X */
 337
 338        default:
 339                snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
 340        }
 341
 342        spin_unlock_irqrestore(&chip->lock, flags);
 343}
 344
 345
 346#define snd_opti9xx_write_mask(chip, reg, value, mask)  \
 347        snd_opti9xx_write(chip, reg,                    \
 348                (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask)))
 349
 350
 351static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
 352{
 353        unsigned char wss_base_bits;
 354        unsigned char irq_bits;
 355        unsigned char dma_bits;
 356        unsigned char mpu_port_bits = 0;
 357        unsigned char mpu_irq_bits;
 358
 359        switch (chip->hardware) {
 360#ifndef OPTi93X
 361        case OPTi9XX_HW_82C924:
 362                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc);
 363                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
 364
 365        case OPTi9XX_HW_82C925:
 366                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
 367                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
 368                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
 369#ifdef CS4231
 370                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
 371#else
 372                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
 373#endif  /* CS4231 */
 374                break;
 375
 376        case OPTi9XX_HW_82C928:
 377        case OPTi9XX_HW_82C929:
 378                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
 379                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
 380                /*
 381                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xa2, 0xae);
 382                */
 383                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);
 384#ifdef CS4231
 385                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
 386#else
 387                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
 388#endif  /* CS4231 */
 389                break;
 390
 391#else   /* OPTi93X */
 392        case OPTi9XX_HW_82C931:
 393        case OPTi9XX_HW_82C933:
 394                /*
 395                 * The BTC 1817DW has QS1000 wavetable which is connected
 396                 * to the serial digital input of the OPTI931.
 397                 */
 398                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(21), 0x82, 0xff);
 399                /* 
 400                 * This bit sets OPTI931 to automaticaly select FM
 401                 * or digital input signal.
 402                 */
 403                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01);
 404        case OPTi9XX_HW_82C930: /* FALL THROUGH */
 405                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03);
 406                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff);
 407                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 |
 408                        (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04),
 409                        0x34);
 410                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf);
 411                break;
 412#endif  /* OPTi93X */
 413
 414        default:
 415                snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
 416                return -EINVAL;
 417        }
 418
 419        switch (chip->wss_base) {
 420        case 0x530:
 421                wss_base_bits = 0x00;
 422                break;
 423        case 0x604:
 424                wss_base_bits = 0x03;
 425                break;
 426        case 0xe80:
 427                wss_base_bits = 0x01;
 428                break;
 429        case 0xf40:
 430                wss_base_bits = 0x02;
 431                break;
 432        default:
 433                snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n",
 434                           chip->wss_base);
 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 (chip->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", chip->irq);
 460                goto __skip_resources;
 461        }
 462
 463        switch (chip->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",
 475                           chip->dma1);
 476                goto __skip_resources;
 477        }
 478
 479#if defined(CS4231) || defined(OPTi93X)
 480        if (chip->dma1 == chip->dma2) {
 481                snd_printk(KERN_ERR "don't want to share dmas\n");
 482                return -EBUSY;
 483        }
 484
 485        switch (chip->dma2) {
 486        case 0:
 487        case 1:
 488                break;
 489        default:
 490                snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n",
 491                           chip->dma2);
 492                goto __skip_resources;
 493        }
 494        dma_bits |= 0x04;
 495#endif  /* CS4231 || OPTi93X */
 496
 497#ifndef OPTi93X
 498         outb(irq_bits << 3 | dma_bits, chip->wss_base);
 499#else /* OPTi93X */
 500        snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
 501#endif /* OPTi93X */
 502
 503__skip_resources:
 504        if (chip->hardware > OPTi9XX_HW_82C928) {
 505                switch (chip->mpu_port) {
 506                case 0:
 507                case -1:
 508                        break;
 509                case 0x300:
 510                        mpu_port_bits = 0x03;
 511                        break;
 512                case 0x310:
 513                        mpu_port_bits = 0x02;
 514                        break;
 515                case 0x320:
 516                        mpu_port_bits = 0x01;
 517                        break;
 518                case 0x330:
 519                        mpu_port_bits = 0x00;
 520                        break;
 521                default:
 522                        snd_printk(KERN_WARNING
 523                                   "MPU-401 port 0x%lx not valid\n",
 524                                chip->mpu_port);
 525                        goto __skip_mpu;
 526                }
 527
 528                switch (chip->mpu_irq) {
 529                case 5:
 530                        mpu_irq_bits = 0x02;
 531                        break;
 532                case 7:
 533                        mpu_irq_bits = 0x03;
 534                        break;
 535                case 9:
 536                        mpu_irq_bits = 0x00;
 537                        break;
 538                case 10:
 539                        mpu_irq_bits = 0x01;
 540                        break;
 541                default:
 542                        snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n",
 543                                chip->mpu_irq);
 544                        goto __skip_mpu;
 545                }
 546
 547                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6),
 548                        (chip->mpu_port <= 0) ? 0x00 :
 549                                0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
 550                        0xf8);
 551        }
 552__skip_mpu:
 553
 554        return 0;
 555}
 556
 557#ifdef OPTi93X
 558
 559static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
 560{
 561        struct snd_wss *codec = dev_id;
 562        struct snd_opti9xx *chip = codec->card->private_data;
 563        unsigned char status;
 564
 565        status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11));
 566        if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
 567                snd_pcm_period_elapsed(codec->playback_substream);
 568        if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) {
 569                snd_wss_overrange(codec);
 570                snd_pcm_period_elapsed(codec->capture_substream);
 571        }
 572        outb(0x00, OPTi93X_PORT(codec, STATUS));
 573        return IRQ_HANDLED;
 574}
 575
 576#endif /* OPTi93X */
 577
 578static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
 579                                             struct snd_opti9xx *chip)
 580{
 581        int i, err;
 582
 583#ifndef OPTi93X
 584        for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) {
 585                unsigned char value;
 586
 587                if ((err = snd_opti9xx_init(chip, i)) < 0)
 588                        return err;
 589
 590                if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
 591                        continue;
 592
 593                value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1));
 594                if ((value != 0xff) && (value != inb(chip->mc_base + 1)))
 595                        if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)))
 596                                return 1;
 597
 598                release_and_free_resource(chip->res_mc_base);
 599                chip->res_mc_base = NULL;
 600
 601        }
 602#else   /* OPTi93X */
 603        for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) {
 604                unsigned long flags;
 605                unsigned char value;
 606
 607                if ((err = snd_opti9xx_init(chip, i)) < 0)
 608                        return err;
 609
 610                if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
 611                        continue;
 612
 613                spin_lock_irqsave(&chip->lock, flags);
 614                outb(chip->password, chip->mc_base + chip->pwd_reg);
 615                outb(((chip->mc_indir_index & (1 << 8)) >> 4) |
 616                        ((chip->mc_indir_index & 0xf0) >> 4), chip->mc_base);
 617                spin_unlock_irqrestore(&chip->lock, flags);
 618
 619                value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7));
 620                snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value);
 621                if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value)
 622                        return 1;
 623
 624                release_and_free_resource(chip->res_mc_base);
 625                chip->res_mc_base = NULL;
 626        }
 627#endif  /* OPTi93X */
 628
 629        return -ENODEV;
 630}
 631
 632#ifdef CONFIG_PNP
 633static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
 634                                          struct pnp_card_link *card,
 635                                          const struct pnp_card_device_id *pid)
 636{
 637        struct pnp_dev *pdev;
 638        int err;
 639
 640        chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL);
 641        if (chip->dev == NULL)
 642                return -EBUSY;
 643
 644        chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
 645
 646        pdev = chip->dev;
 647
 648        err = pnp_activate_dev(pdev);
 649        if (err < 0) {
 650                snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);
 651                return err;
 652        }
 653
 654#ifdef OPTi93X
 655        port = pnp_port_start(pdev, 0) - 4;
 656        fm_port = pnp_port_start(pdev, 1) + 8;
 657#else
 658        if (pid->driver_data != 0x0924)
 659                port = pnp_port_start(pdev, 1);
 660        fm_port = pnp_port_start(pdev, 2) + 8;
 661#endif  /* OPTi93X */
 662        irq = pnp_irq(pdev, 0);
 663        dma1 = pnp_dma(pdev, 0);
 664#if defined(CS4231) || defined(OPTi93X)
 665        dma2 = pnp_dma(pdev, 1);
 666#endif  /* CS4231 || OPTi93X */
 667
 668        pdev = chip->devmpu;
 669        if (pdev && mpu_port > 0) {
 670                err = pnp_activate_dev(pdev);
 671                if (err < 0) {
 672                        snd_printk(KERN_ERR "AUDIO pnp configure failure\n");
 673                        mpu_port = -1;
 674                        chip->devmpu = NULL;
 675                } else {
 676                        mpu_port = pnp_port_start(pdev, 0);
 677                        mpu_irq = pnp_irq(pdev, 0);
 678                }
 679        }
 680        return pid->driver_data;
 681}
 682#endif  /* CONFIG_PNP */
 683
 684static void snd_card_opti9xx_free(struct snd_card *card)
 685{
 686        struct snd_opti9xx *chip = card->private_data;
 687        
 688        if (chip) {
 689#ifdef OPTi93X
 690                struct snd_wss *codec = chip->codec;
 691                if (codec && codec->irq > 0) {
 692                        disable_irq(codec->irq);
 693                        free_irq(codec->irq, codec);
 694                }
 695#endif
 696                release_and_free_resource(chip->res_mc_base);
 697        }
 698}
 699
 700static int __devinit snd_opti9xx_probe(struct snd_card *card)
 701{
 702        static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
 703        int error;
 704        struct snd_opti9xx *chip = card->private_data;
 705        struct snd_wss *codec;
 706#ifdef CS4231
 707        struct snd_timer *timer;
 708#endif
 709        struct snd_pcm *pcm;
 710        struct snd_rawmidi *rmidi;
 711        struct snd_hwdep *synth;
 712
 713        if (! chip->res_mc_base &&
 714            (chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
 715                                                "OPTi9xx MC")) == NULL)
 716                return -ENOMEM;
 717
 718        chip->wss_base = port;
 719        chip->fm_port = fm_port;
 720        chip->mpu_port = mpu_port;
 721        chip->irq = irq;
 722        chip->mpu_irq = mpu_irq;
 723        chip->dma1 = dma1;
 724#if defined(CS4231) || defined(OPTi93X)
 725        chip->dma2 = dma2;
 726#else
 727        chip->dma2 = -1;
 728#endif
 729
 730        if (chip->wss_base == SNDRV_AUTO_PORT) {
 731                chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4);
 732                if (chip->wss_base < 0) {
 733                        snd_printk(KERN_ERR "unable to find a free WSS port\n");
 734                        return -EBUSY;
 735                }
 736        }
 737        error = snd_opti9xx_configure(chip);
 738        if (error)
 739                return error;
 740
 741        error = snd_wss_create(card, chip->wss_base + 4, -1,
 742                               chip->irq, chip->dma1, chip->dma2,
 743#ifdef OPTi93X
 744                               WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
 745#else
 746                               WSS_HW_DETECT, 0,
 747#endif
 748                               &codec);
 749        if (error < 0)
 750                return error;
 751#ifdef OPTi93X
 752        chip->codec = codec;
 753#endif
 754        error = snd_wss_pcm(codec, 0, &pcm);
 755        if (error < 0)
 756                return error;
 757        error = snd_wss_mixer(codec);
 758        if (error < 0)
 759                return error;
 760#ifdef CS4231
 761        error = snd_wss_timer(codec, 0, &timer);
 762        if (error < 0)
 763                return error;
 764#endif
 765#ifdef OPTi93X
 766        error = request_irq(chip->irq, snd_opti93x_interrupt,
 767                            IRQF_DISABLED, DEV_NAME" - WSS", codec);
 768        if (error < 0) {
 769                snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
 770                return error;
 771        }
 772#endif
 773        strcpy(card->driver, chip->name);
 774        sprintf(card->shortname, "OPTi %s", card->driver);
 775#if defined(CS4231) || defined(OPTi93X)
 776        sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d",
 777                card->shortname, pcm->name, chip->wss_base + 4,
 778                chip->irq, chip->dma1, chip->dma2);
 779#else
 780        sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d",
 781                card->shortname, pcm->name, chip->wss_base + 4,
 782                chip->irq, chip->dma1);
 783#endif  /* CS4231 || OPTi93X */
 784
 785        if (chip->mpu_port <= 0 || chip->mpu_port == SNDRV_AUTO_PORT)
 786                rmidi = NULL;
 787        else
 788                if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
 789                                chip->mpu_port, 0, chip->mpu_irq, IRQF_DISABLED,
 790                                &rmidi)))
 791                        snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
 792                                   chip->mpu_port);
 793
 794        if (chip->fm_port > 0 && chip->fm_port != SNDRV_AUTO_PORT) {
 795                struct snd_opl3 *opl3 = NULL;
 796#ifndef OPTi93X
 797                if (chip->hardware == OPTi9XX_HW_82C928 ||
 798                    chip->hardware == OPTi9XX_HW_82C929 ||
 799                    chip->hardware == OPTi9XX_HW_82C924) {
 800                        struct snd_opl4 *opl4;
 801                        /* assume we have an OPL4 */
 802                        snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
 803                                               0x20, 0x20);
 804                        if (snd_opl4_create(card,
 805                                            chip->fm_port,
 806                                            chip->fm_port - 8,
 807                                            2, &opl3, &opl4) < 0) {
 808                                /* no luck, use OPL3 instead */
 809                                snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
 810                                                       0x00, 0x20);
 811                        }
 812                }
 813#endif  /* !OPTi93X */
 814                if (!opl3 && snd_opl3_create(card,
 815                                             chip->fm_port,
 816                                             chip->fm_port + 2,
 817                                             OPL3_HW_AUTO, 0, &opl3) < 0) {
 818                        snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n",
 819                                   chip->fm_port, chip->fm_port + 4 - 1);
 820                }
 821                if (opl3) {
 822                        error = snd_opl3_hwdep_new(opl3, 0, 1, &synth);
 823                        if (error < 0)
 824                                return error;
 825                }
 826        }
 827
 828        return snd_card_register(card);
 829}
 830
 831static int snd_opti9xx_card_new(struct snd_card **cardp)
 832{
 833        struct snd_card *card;
 834        int err;
 835
 836        err = snd_card_create(index, id, THIS_MODULE,
 837                              sizeof(struct snd_opti9xx), &card);
 838        if (err < 0)
 839                return err;
 840        card->private_free = snd_card_opti9xx_free;
 841        *cardp = card;
 842        return 0;
 843}
 844
 845static int __devinit snd_opti9xx_isa_match(struct device *devptr,
 846                                           unsigned int dev)
 847{
 848#ifdef CONFIG_PNP
 849        if (snd_opti9xx_pnp_is_probed)
 850                return 0;
 851        if (isapnp)
 852                return 0;
 853#endif
 854        return 1;
 855}
 856
 857static int __devinit snd_opti9xx_isa_probe(struct device *devptr,
 858                                           unsigned int dev)
 859{
 860        struct snd_card *card;
 861        int error;
 862        static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
 863#ifdef OPTi93X
 864        static int possible_irqs[] = {5, 9, 10, 11, 7, -1};
 865#else
 866        static int possible_irqs[] = {9, 10, 11, 7, -1};
 867#endif  /* OPTi93X */
 868        static int possible_mpu_irqs[] = {5, 9, 10, 7, -1};
 869        static int possible_dma1s[] = {3, 1, 0, -1};
 870#if defined(CS4231) || defined(OPTi93X)
 871        static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
 872#endif  /* CS4231 || OPTi93X */
 873
 874        if (mpu_port == SNDRV_AUTO_PORT) {
 875                if ((mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
 876                        snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
 877                        return -EBUSY;
 878                }
 879        }
 880        if (irq == SNDRV_AUTO_IRQ) {
 881                if ((irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
 882                        snd_printk(KERN_ERR "unable to find a free IRQ\n");
 883                        return -EBUSY;
 884                }
 885        }
 886        if (mpu_irq == SNDRV_AUTO_IRQ) {
 887                if ((mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
 888                        snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n");
 889                        return -EBUSY;
 890                }
 891        }
 892        if (dma1 == SNDRV_AUTO_DMA) {
 893                if ((dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
 894                        snd_printk(KERN_ERR "unable to find a free DMA1\n");
 895                        return -EBUSY;
 896                }
 897        }
 898#if defined(CS4231) || defined(OPTi93X)
 899        if (dma2 == SNDRV_AUTO_DMA) {
 900                if ((dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4])) < 0) {
 901                        snd_printk(KERN_ERR "unable to find a free DMA2\n");
 902                        return -EBUSY;
 903                }
 904        }
 905#endif
 906
 907        error = snd_opti9xx_card_new(&card);
 908        if (error < 0)
 909                return error;
 910
 911        if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) {
 912                snd_card_free(card);
 913                return error;
 914        }
 915        snd_card_set_dev(card, devptr);
 916        if ((error = snd_opti9xx_probe(card)) < 0) {
 917                snd_card_free(card);
 918                return error;
 919        }
 920        dev_set_drvdata(devptr, card);
 921        return 0;
 922}
 923
 924static int __devexit snd_opti9xx_isa_remove(struct device *devptr,
 925                                            unsigned int dev)
 926{
 927        snd_card_free(dev_get_drvdata(devptr));
 928        dev_set_drvdata(devptr, NULL);
 929        return 0;
 930}
 931
 932static struct isa_driver snd_opti9xx_driver = {
 933        .match          = snd_opti9xx_isa_match,
 934        .probe          = snd_opti9xx_isa_probe,
 935        .remove         = __devexit_p(snd_opti9xx_isa_remove),
 936        /* FIXME: suspend/resume */
 937        .driver         = {
 938                .name   = DEV_NAME
 939        },
 940};
 941
 942#ifdef CONFIG_PNP
 943static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
 944                                           const struct pnp_card_device_id *pid)
 945{
 946        struct snd_card *card;
 947        int error, hw;
 948        struct snd_opti9xx *chip;
 949
 950        if (snd_opti9xx_pnp_is_probed)
 951                return -EBUSY;
 952        if (! isapnp)
 953                return -ENODEV;
 954        error = snd_opti9xx_card_new(&card);
 955        if (error < 0)
 956                return error;
 957        chip = card->private_data;
 958
 959        hw = snd_card_opti9xx_pnp(chip, pcard, pid);
 960        switch (hw) {
 961        case 0x0924:
 962                hw = OPTi9XX_HW_82C924;
 963                break;
 964        case 0x0925:
 965                hw = OPTi9XX_HW_82C925;
 966                break;
 967        case 0x0931:
 968                hw = OPTi9XX_HW_82C931;
 969                break;
 970        default:
 971                snd_card_free(card);
 972                return -ENODEV;
 973        }
 974
 975        if ((error = snd_opti9xx_init(chip, hw))) {
 976                snd_card_free(card);
 977                return error;
 978        }
 979        if (hw <= OPTi9XX_HW_82C930)
 980                chip->mc_base -= 0x80;
 981        snd_card_set_dev(card, &pcard->card->dev);
 982        if ((error = snd_opti9xx_probe(card)) < 0) {
 983                snd_card_free(card);
 984                return error;
 985        }
 986        pnp_set_card_drvdata(pcard, card);
 987        snd_opti9xx_pnp_is_probed = 1;
 988        return 0;
 989}
 990
 991static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard)
 992{
 993        snd_card_free(pnp_get_card_drvdata(pcard));
 994        pnp_set_card_drvdata(pcard, NULL);
 995        snd_opti9xx_pnp_is_probed = 0;
 996}
 997
 998static struct pnp_card_driver opti9xx_pnpc_driver = {
 999        .flags          = PNP_DRIVER_RES_DISABLE,
1000        .name           = "opti9xx",
1001        .id_table       = snd_opti9xx_pnpids,
1002        .probe          = snd_opti9xx_pnp_probe,
1003        .remove         = __devexit_p(snd_opti9xx_pnp_remove),
1004};
1005#endif
1006
1007#ifdef OPTi93X
1008#define CHIP_NAME       "82C93x"
1009#else
1010#define CHIP_NAME       "82C92x"
1011#endif
1012
1013static int __init alsa_card_opti9xx_init(void)
1014{
1015#ifdef CONFIG_PNP
1016        pnp_register_card_driver(&opti9xx_pnpc_driver);
1017        if (snd_opti9xx_pnp_is_probed)
1018                return 0;
1019        pnp_unregister_card_driver(&opti9xx_pnpc_driver);
1020#endif
1021        return isa_register_driver(&snd_opti9xx_driver, 1);
1022}
1023
1024static void __exit alsa_card_opti9xx_exit(void)
1025{
1026        if (!snd_opti9xx_pnp_is_probed) {
1027                isa_unregister_driver(&snd_opti9xx_driver);
1028                return;
1029        }
1030#ifdef CONFIG_PNP
1031        pnp_unregister_card_driver(&opti9xx_pnpc_driver);
1032#endif
1033}
1034
1035module_init(alsa_card_opti9xx_init)
1036module_exit(alsa_card_opti9xx_exit)
1037
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.