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