linux/sound/oss/pss.c
<<
>>
Prefs
   1/*
   2 * sound/oss/pss.c
   3 *
   4 * The low level driver for the Personal Sound System (ECHO ESC614).
   5 *
   6 *
   7 * Copyright (C) by Hannu Savolainen 1993-1997
   8 *
   9 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
  10 * Version 2 (June 1991). See the "COPYING" file distributed with this software
  11 * for more info.
  12 *
  13 *
  14 * Thomas Sailer        ioctl code reworked (vmalloc/vfree removed)
  15 * Alan Cox             modularisation, clean up.
  16 *
  17 * 98-02-21: Vladimir Michl <vladimir.michl@upol.cz>
  18 *          Added mixer device for Beethoven ADSP-16 (master volume,
  19 *          bass, treble, synth), only for speakers.
  20 *          Fixed bug in pss_write (exchange parameters)
  21 *          Fixed config port of SB
  22 *          Requested two regions for PSS (PSS mixer, PSS config)
  23 *          Modified pss_download_boot
  24 *          To probe_pss_mss added test for initialize AD1848
  25 * 98-05-28: Vladimir Michl <vladimir.michl@upol.cz>
  26 *          Fixed computation of mixer volumes
  27 * 04-05-1999: Anthony Barbachan <barbcode@xmen.cis.fordham.edu>
  28 *          Added code that allows the user to enable his cdrom and/or 
  29 *          joystick through the module parameters pss_cdrom_port and 
  30 *          pss_enable_joystick.  pss_cdrom_port takes a port address as its
  31 *          argument.  pss_enable_joystick takes either a 0 or a non-0 as its
  32 *          argument.
  33 * 04-06-1999: Anthony Barbachan <barbcode@xmen.cis.fordham.edu>
  34 *          Separated some code into new functions for easier reuse.  
  35 *          Cleaned up and streamlined new code.  Added code to allow a user 
  36 *          to only use this driver for enabling non-sound components 
  37 *          through the new module parameter pss_no_sound (flag).  Added 
  38 *          code that would allow a user to decide whether the driver should 
  39 *          reset the configured hardware settings for the PSS board through 
  40 *          the module parameter pss_keep_settings (flag).   This flag will 
  41 *          allow a user to free up resources in use by this card if needbe, 
  42 *          furthermore it allows him to use this driver to just enable the 
  43 *          emulations and then be unloaded as it is no longer needed.  Both 
  44 *          new settings are only available to this driver if compiled as a 
  45 *          module.  The default settings of all new parameters are set to 
  46 *          load the driver as it did in previous versions.
  47 * 04-07-1999: Anthony Barbachan <barbcode@xmen.cis.fordham.edu>
  48 *          Added module parameter pss_firmware to allow the user to tell 
  49 *          the driver where the firmware file is located.  The default 
  50 *          setting is the previous hardcoded setting "/etc/sound/pss_synth".
  51 * 00-03-03: Christoph Hellwig <chhellwig@infradead.org>
  52 *          Adapted to module_init/module_exit
  53 * 11-10-2000: Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
  54 *          Added __init to probe_pss(), attach_pss() and probe_pss_mpu()
  55 * 02-Jan-2001: Chris Rankin
  56 *          Specify that this module owns the coprocessor
  57 */
  58
  59
  60#include <linux/init.h>
  61#include <linux/module.h>
  62#include <linux/spinlock.h>
  63
  64#include "sound_config.h"
  65#include "sound_firmware.h"
  66
  67#include "ad1848.h"
  68#include "mpu401.h"
  69
  70/*
  71 * PSS registers.
  72 */
  73#define REG(x)  (devc->base+x)
  74#define PSS_DATA        0
  75#define PSS_STATUS      2
  76#define PSS_CONTROL     2
  77#define PSS_ID          4
  78#define PSS_IRQACK      4
  79#define PSS_PIO         0x1a
  80
  81/*
  82 * Config registers
  83 */
  84#define CONF_PSS        0x10
  85#define CONF_WSS        0x12
  86#define CONF_SB         0x14
  87#define CONF_CDROM      0x16
  88#define CONF_MIDI       0x18
  89
  90/*
  91 * Status bits.
  92 */
  93#define PSS_FLAG3     0x0800
  94#define PSS_FLAG2     0x0400
  95#define PSS_FLAG1     0x1000
  96#define PSS_FLAG0     0x0800
  97#define PSS_WRITE_EMPTY  0x8000
  98#define PSS_READ_FULL    0x4000
  99
 100/*
 101 * WSS registers
 102 */
 103#define WSS_INDEX 4
 104#define WSS_DATA 5
 105
 106/*
 107 * WSS status bits
 108 */
 109#define WSS_INITIALIZING 0x80
 110#define WSS_AUTOCALIBRATION 0x20
 111
 112#define NO_WSS_MIXER    -1
 113
 114#include "coproc.h"
 115
 116#include "pss_boot.h"
 117
 118/* If compiled into kernel, it enable or disable pss mixer */
 119#ifdef CONFIG_PSS_MIXER
 120static bool pss_mixer = 1;
 121#else
 122static bool pss_mixer;
 123#endif
 124
 125
 126typedef struct pss_mixerdata {
 127        unsigned int volume_l;
 128        unsigned int volume_r;
 129        unsigned int bass;
 130        unsigned int treble;
 131        unsigned int synth;
 132} pss_mixerdata;
 133
 134typedef struct pss_confdata {
 135        int             base;
 136        int             irq;
 137        int             dma;
 138        int            *osp;
 139        pss_mixerdata   mixer;
 140        int             ad_mixer_dev;
 141} pss_confdata;
 142  
 143static pss_confdata pss_data;
 144static pss_confdata *devc = &pss_data;
 145static DEFINE_SPINLOCK(lock);
 146
 147static int      pss_initialized;
 148static int      nonstandard_microcode;
 149static int      pss_cdrom_port = -1;    /* Parameter for the PSS cdrom port */
 150static bool     pss_enable_joystick;    /* Parameter for enabling the joystick */
 151static coproc_operations pss_coproc_operations;
 152
 153static void pss_write(pss_confdata *devc, int data)
 154{
 155        unsigned long i, limit;
 156
 157        limit = jiffies + HZ/10;        /* The timeout is 0.1 seconds */
 158        /*
 159         * Note! the i<5000000 is an emergency exit. The dsp_command() is sometimes
 160         * called while interrupts are disabled. This means that the timer is
 161         * disabled also. However the timeout situation is a abnormal condition.
 162         * Normally the DSP should be ready to accept commands after just couple of
 163         * loops.
 164         */
 165
 166        for (i = 0; i < 5000000 && time_before(jiffies, limit); i++)
 167        {
 168                if (inw(REG(PSS_STATUS)) & PSS_WRITE_EMPTY)
 169                {
 170                        outw(data, REG(PSS_DATA));
 171                        return;
 172                }
 173        }
 174        printk(KERN_WARNING "PSS: DSP Command (%04x) Timeout.\n", data);
 175}
 176
 177static int __init probe_pss(struct address_info *hw_config)
 178{
 179        unsigned short id;
 180        int irq, dma;
 181
 182        devc->base = hw_config->io_base;
 183        irq = devc->irq = hw_config->irq;
 184        dma = devc->dma = hw_config->dma;
 185        devc->osp = hw_config->osp;
 186
 187        if (devc->base != 0x220 && devc->base != 0x240)
 188                if (devc->base != 0x230 && devc->base != 0x250)         /* Some cards use these */
 189                        return 0;
 190
 191        if (!request_region(devc->base, 0x10, "PSS mixer, SB emulation")) {
 192                printk(KERN_ERR "PSS: I/O port conflict\n");
 193                return 0;
 194        }
 195        id = inw(REG(PSS_ID));
 196        if ((id >> 8) != 'E') {
 197                printk(KERN_ERR "No PSS signature detected at 0x%x (0x%x)\n",  devc->base,  id); 
 198                release_region(devc->base, 0x10);
 199                return 0;
 200        }
 201        if (!request_region(devc->base + 0x10, 0x9, "PSS config")) {
 202                printk(KERN_ERR "PSS: I/O port conflict\n");
 203                release_region(devc->base, 0x10);
 204                return 0;
 205        }
 206        return 1;
 207}
 208
 209static int set_irq(pss_confdata * devc, int dev, int irq)
 210{
 211        static unsigned short irq_bits[16] =
 212        {
 213                0x0000, 0x0000, 0x0000, 0x0008,
 214                0x0000, 0x0010, 0x0000, 0x0018,
 215                0x0000, 0x0020, 0x0028, 0x0030,
 216                0x0038, 0x0000, 0x0000, 0x0000
 217        };
 218
 219        unsigned short  tmp, bits;
 220
 221        if (irq < 0 || irq > 15)
 222                return 0;
 223
 224        tmp = inw(REG(dev)) & ~0x38;    /* Load confreg, mask IRQ bits out */
 225
 226        if ((bits = irq_bits[irq]) == 0 && irq != 0)
 227        {
 228                printk(KERN_ERR "PSS: Invalid IRQ %d\n", irq);
 229                return 0;
 230        }
 231        outw(tmp | bits, REG(dev));
 232        return 1;
 233}
 234
 235static void set_io_base(pss_confdata * devc, int dev, int base)
 236{
 237        unsigned short  tmp = inw(REG(dev)) & 0x003f;
 238        unsigned short  bits = (base & 0x0ffc) << 4;
 239
 240        outw(bits | tmp, REG(dev));
 241}
 242
 243static int set_dma(pss_confdata * devc, int dev, int dma)
 244{
 245        static unsigned short dma_bits[8] =
 246        {
 247                0x0001, 0x0002, 0x0000, 0x0003,
 248                0x0000, 0x0005, 0x0006, 0x0007
 249        };
 250
 251        unsigned short  tmp, bits;
 252
 253        if (dma < 0 || dma > 7)
 254                return 0;
 255
 256        tmp = inw(REG(dev)) & ~0x07;    /* Load confreg, mask DMA bits out */
 257
 258        if ((bits = dma_bits[dma]) == 0 && dma != 4)
 259        {
 260                  printk(KERN_ERR "PSS: Invalid DMA %d\n", dma);
 261                  return 0;
 262        }
 263        outw(tmp | bits, REG(dev));
 264        return 1;
 265}
 266
 267static int pss_reset_dsp(pss_confdata * devc)
 268{
 269        unsigned long   i, limit = jiffies + HZ/10;
 270
 271        outw(0x2000, REG(PSS_CONTROL));
 272        for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
 273                inw(REG(PSS_CONTROL));
 274        outw(0x0000, REG(PSS_CONTROL));
 275        return 1;
 276}
 277
 278static int pss_put_dspword(pss_confdata * devc, unsigned short word)
 279{
 280        int i, val;
 281
 282        for (i = 0; i < 327680; i++)
 283        {
 284                val = inw(REG(PSS_STATUS));
 285                if (val & PSS_WRITE_EMPTY)
 286                {
 287                        outw(word, REG(PSS_DATA));
 288                        return 1;
 289                }
 290        }
 291        return 0;
 292}
 293
 294static int pss_get_dspword(pss_confdata * devc, unsigned short *word)
 295{
 296        int i, val;
 297
 298        for (i = 0; i < 327680; i++)
 299        {
 300                val = inw(REG(PSS_STATUS));
 301                if (val & PSS_READ_FULL)
 302                {
 303                        *word = inw(REG(PSS_DATA));
 304                        return 1;
 305                }
 306        }
 307        return 0;
 308}
 309
 310static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags)
 311{
 312        int i, val, count;
 313        unsigned long limit;
 314
 315        if (flags & CPF_FIRST)
 316        {
 317/*_____ Warn DSP software that a boot is coming */
 318                outw(0x00fe, REG(PSS_DATA));
 319
 320                limit = jiffies + HZ/10;
 321                for (i = 0; i < 32768 && time_before(jiffies, limit); i++)
 322                        if (inw(REG(PSS_DATA)) == 0x5500)
 323                                break;
 324
 325                outw(*block++, REG(PSS_DATA));
 326                pss_reset_dsp(devc);
 327        }
 328        count = 1;
 329        while ((flags&CPF_LAST) || count<size )
 330        {
 331                int j;
 332
 333                for (j = 0; j < 327670; j++)
 334                {
 335/*_____ Wait for BG to appear */
 336                        if (inw(REG(PSS_STATUS)) & PSS_FLAG3)
 337                                break;
 338                }
 339
 340                if (j == 327670)
 341                {
 342                        /* It's ok we timed out when the file was empty */
 343                        if (count >= size && flags & CPF_LAST)
 344                                break;
 345                        else
 346                        {
 347                                printk("\n");
 348                                printk(KERN_ERR "PSS: Download timeout problems, byte %d=%d\n", count, size);
 349                                return 0;
 350                        }
 351                }
 352/*_____ Send the next byte */
 353                if (count >= size) 
 354                {
 355                        /* If not data in block send 0xffff */
 356                        outw (0xffff, REG (PSS_DATA));
 357                }
 358                else
 359                {
 360                        /*_____ Send the next byte */
 361                        outw (*block++, REG (PSS_DATA));
 362                }
 363                count++;
 364        }
 365
 366        if (flags & CPF_LAST)
 367        {
 368/*_____ Why */
 369                outw(0, REG(PSS_DATA));
 370
 371                limit = jiffies + HZ/10;
 372                for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
 373                        val = inw(REG(PSS_STATUS));
 374
 375                limit = jiffies + HZ/10;
 376                for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++)
 377                {
 378                        val = inw(REG(PSS_STATUS));
 379                        if (val & 0x4000)
 380                                break;
 381                }
 382
 383                /* now read the version */
 384                for (i = 0; i < 32000; i++)
 385                {
 386                        val = inw(REG(PSS_STATUS));
 387                        if (val & PSS_READ_FULL)
 388                                break;
 389                }
 390                if (i == 32000)
 391                        return 0;
 392
 393                val = inw(REG(PSS_DATA));
 394                /* printk( "<PSS: microcode version %d.%d loaded>",  val/16,  val % 16); */
 395        }
 396        return 1;
 397}
 398
 399/* Mixer */
 400static void set_master_volume(pss_confdata *devc, int left, int right)
 401{
 402        static unsigned char log_scale[101] =  {
 403                0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee,
 404                0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
 405                0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7,
 406                0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
 407                0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb,
 408                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
 409                0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
 410                0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
 411                0xfe, 0xfe, 0xff, 0xff, 0xff
 412        };
 413        pss_write(devc, 0x0010);
 414        pss_write(devc, log_scale[left] | 0x0000);
 415        pss_write(devc, 0x0010);
 416        pss_write(devc, log_scale[right] | 0x0100);
 417}
 418
 419static void set_synth_volume(pss_confdata *devc, int volume)
 420{
 421        int vol = ((0x8000*volume)/100L);
 422        pss_write(devc, 0x0080);
 423        pss_write(devc, vol);
 424        pss_write(devc, 0x0081);
 425        pss_write(devc, vol);
 426}
 427
 428static void set_bass(pss_confdata *devc, int level)
 429{
 430        int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0;
 431        pss_write(devc, 0x0010);
 432        pss_write(devc, vol | 0x0200);
 433};
 434
 435static void set_treble(pss_confdata *devc, int level)
 436{       
 437        int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0;
 438        pss_write(devc, 0x0010);
 439        pss_write(devc, vol | 0x0300);
 440};
 441
 442static void pss_mixer_reset(pss_confdata *devc)
 443{
 444        set_master_volume(devc, 33, 33);
 445        set_bass(devc, 50);
 446        set_treble(devc, 50);
 447        set_synth_volume(devc, 30);
 448        pss_write (devc, 0x0010);
 449        pss_write (devc, 0x0800 | 0xce);        /* Stereo */
 450        
 451        if(pss_mixer)
 452        {
 453                devc->mixer.volume_l = devc->mixer.volume_r = 33;
 454                devc->mixer.bass = 50;
 455                devc->mixer.treble = 50;
 456                devc->mixer.synth = 30;
 457        }
 458}
 459
 460static int set_volume_mono(unsigned __user *p, unsigned int *aleft)
 461{
 462        unsigned int left, volume;
 463        if (get_user(volume, p))
 464                return -EFAULT;
 465        
 466        left = volume & 0xff;
 467        if (left > 100)
 468                left = 100;
 469        *aleft = left;
 470        return 0;
 471}
 472
 473static int set_volume_stereo(unsigned __user *p,
 474                             unsigned int *aleft,
 475                             unsigned int *aright)
 476{
 477        unsigned int left, right, volume;
 478        if (get_user(volume, p))
 479                return -EFAULT;
 480
 481        left = volume & 0xff;
 482        if (left > 100)
 483                left = 100;
 484        right = (volume >> 8) & 0xff;
 485        if (right > 100)
 486                right = 100;
 487        *aleft = left;
 488        *aright = right;
 489        return 0;
 490}
 491
 492static int ret_vol_mono(int left)
 493{
 494        return ((left << 8) | left);
 495}
 496
 497static int ret_vol_stereo(int left, int right)
 498{
 499        return ((right << 8) | left);
 500}
 501
 502static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg)
 503{
 504        if (devc->ad_mixer_dev != NO_WSS_MIXER) 
 505                return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg);
 506        else 
 507                return -EINVAL;
 508}
 509
 510static int pss_mixer_ioctl (int dev, unsigned int cmd, void __user *arg)
 511{
 512        pss_confdata *devc = mixer_devs[dev]->devc;
 513        int cmdf = cmd & 0xff;
 514        
 515        if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) &&
 516                (cmdf != SOUND_MIXER_TREBLE) && (cmdf != SOUND_MIXER_SYNTH) &&
 517                (cmdf != SOUND_MIXER_DEVMASK) && (cmdf != SOUND_MIXER_STEREODEVS) &&
 518                (cmdf != SOUND_MIXER_RECMASK) && (cmdf != SOUND_MIXER_CAPS) &&
 519                (cmdf != SOUND_MIXER_RECSRC)) 
 520        {
 521                return call_ad_mixer(devc, cmd, arg);
 522        }
 523        
 524        if (((cmd >> 8) & 0xff) != 'M') 
 525                return -EINVAL;
 526                
 527        if (_SIOC_DIR (cmd) & _SIOC_WRITE)
 528        {
 529                switch (cmdf)   
 530                {
 531                        case SOUND_MIXER_RECSRC:
 532                                if (devc->ad_mixer_dev != NO_WSS_MIXER)
 533                                        return call_ad_mixer(devc, cmd, arg);
 534                                else
 535                                {
 536                                        int v;
 537                                        if (get_user(v, (int __user *)arg))
 538                                                return -EFAULT;
 539                                        if (v != 0)
 540                                                return -EINVAL;
 541                                        return 0;
 542                                }
 543                        case SOUND_MIXER_VOLUME:
 544                                if (set_volume_stereo(arg,
 545                                        &devc->mixer.volume_l,
 546                                        &devc->mixer.volume_r))
 547                                        return -EFAULT;
 548                                set_master_volume(devc, devc->mixer.volume_l,
 549                                        devc->mixer.volume_r);
 550                                return ret_vol_stereo(devc->mixer.volume_l,
 551                                        devc->mixer.volume_r);
 552                  
 553                        case SOUND_MIXER_BASS:
 554                                if (set_volume_mono(arg, &devc->mixer.bass))
 555                                        return -EFAULT;
 556                                set_bass(devc, devc->mixer.bass);
 557                                return ret_vol_mono(devc->mixer.bass);
 558                  
 559                        case SOUND_MIXER_TREBLE:
 560                                if (set_volume_mono(arg, &devc->mixer.treble))
 561                                        return -EFAULT;
 562                                set_treble(devc, devc->mixer.treble);
 563                                return ret_vol_mono(devc->mixer.treble);
 564                  
 565                        case SOUND_MIXER_SYNTH:
 566                                if (set_volume_mono(arg, &devc->mixer.synth))
 567                                        return -EFAULT;
 568                                set_synth_volume(devc, devc->mixer.synth);
 569                                return ret_vol_mono(devc->mixer.synth);
 570                  
 571                        default:
 572                                return -EINVAL;
 573                }
 574        }
 575        else                    
 576        {
 577                int val, and_mask = 0, or_mask = 0;
 578                /*
 579                 * Return parameters
 580                 */
 581                switch (cmdf)
 582                {
 583                        case SOUND_MIXER_DEVMASK:
 584                                if (call_ad_mixer(devc, cmd, arg) == -EINVAL)
 585                                        break;
 586                                and_mask = ~0;
 587                                or_mask = SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH;
 588                                break;
 589                  
 590                        case SOUND_MIXER_STEREODEVS:
 591                                if (call_ad_mixer(devc, cmd, arg) == -EINVAL)
 592                                        break;
 593                                and_mask = ~0;
 594                                or_mask = SOUND_MASK_VOLUME;
 595                                break;
 596                  
 597                        case SOUND_MIXER_RECMASK:
 598                                if (devc->ad_mixer_dev != NO_WSS_MIXER)
 599                                        return call_ad_mixer(devc, cmd, arg);
 600                                break;
 601
 602                        case SOUND_MIXER_CAPS:
 603                                if (devc->ad_mixer_dev != NO_WSS_MIXER)
 604                                        return call_ad_mixer(devc, cmd, arg);
 605                                or_mask = SOUND_CAP_EXCL_INPUT;
 606                                break;
 607
 608                        case SOUND_MIXER_RECSRC:
 609                                if (devc->ad_mixer_dev != NO_WSS_MIXER)
 610                                        return call_ad_mixer(devc, cmd, arg);
 611                                break;
 612
 613                        case SOUND_MIXER_VOLUME:
 614                                or_mask =  ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r);
 615                                break;
 616                          
 617                        case SOUND_MIXER_BASS:
 618                                or_mask =  ret_vol_mono(devc->mixer.bass);
 619                                break;
 620                          
 621                        case SOUND_MIXER_TREBLE:
 622                                or_mask = ret_vol_mono(devc->mixer.treble);
 623                                break;
 624                          
 625                        case SOUND_MIXER_SYNTH:
 626                                or_mask = ret_vol_mono(devc->mixer.synth);
 627                                break;
 628                        default:
 629                                return -EINVAL;
 630                }
 631                if (get_user(val, (int __user *)arg))
 632                        return -EFAULT;
 633                val &= and_mask;
 634                val |= or_mask;
 635                if (put_user(val, (int __user *)arg))
 636                        return -EFAULT;
 637                return val;
 638        }
 639}
 640
 641static struct mixer_operations pss_mixer_operations =
 642{
 643        .owner  = THIS_MODULE,
 644        .id     = "SOUNDPORT",
 645        .name   = "PSS-AD1848",
 646        .ioctl  = pss_mixer_ioctl
 647};
 648
 649static void disable_all_emulations(void)
 650{
 651        outw(0x0000, REG(CONF_PSS));    /* 0x0400 enables joystick */
 652        outw(0x0000, REG(CONF_WSS));
 653        outw(0x0000, REG(CONF_SB));
 654        outw(0x0000, REG(CONF_MIDI));
 655        outw(0x0000, REG(CONF_CDROM));
 656}
 657
 658static void configure_nonsound_components(void)
 659{
 660        /* Configure Joystick port */
 661
 662        if(pss_enable_joystick)
 663        {
 664                outw(0x0400, REG(CONF_PSS));    /* 0x0400 enables joystick */
 665                printk(KERN_INFO "PSS: joystick enabled.\n");
 666        }
 667        else
 668        {
 669                printk(KERN_INFO "PSS: joystick port not enabled.\n");
 670        }
 671
 672        /* Configure CDROM port */
 673
 674        if (pss_cdrom_port == -1) {     /* If cdrom port enablation wasn't requested */
 675                printk(KERN_INFO "PSS: CDROM port not enabled.\n");
 676        } else if (!request_region(pss_cdrom_port, 2, "PSS CDROM")) {
 677                pss_cdrom_port = -1;
 678                printk(KERN_ERR "PSS: CDROM I/O port conflict.\n");
 679        } else {
 680                set_io_base(devc, CONF_CDROM, pss_cdrom_port);
 681                printk(KERN_INFO "PSS: CDROM I/O port set to 0x%x.\n", pss_cdrom_port);
 682        }
 683}
 684
 685static int __init attach_pss(struct address_info *hw_config)
 686{
 687        unsigned short  id;
 688        char tmp[100];
 689
 690        devc->base = hw_config->io_base;
 691        devc->irq = hw_config->irq;
 692        devc->dma = hw_config->dma;
 693        devc->osp = hw_config->osp;
 694        devc->ad_mixer_dev = NO_WSS_MIXER;
 695
 696        if (!probe_pss(hw_config))
 697                return 0;
 698
 699        id = inw(REG(PSS_ID)) & 0x00ff;
 700
 701        /*
 702         * Disable all emulations. Will be enabled later (if required).
 703         */
 704         
 705        disable_all_emulations();
 706
 707#ifdef YOU_REALLY_WANT_TO_ALLOCATE_THESE_RESOURCES
 708        if (sound_alloc_dma(hw_config->dma, "PSS"))
 709        {
 710                printk("pss.c: Can't allocate DMA channel.\n");
 711                release_region(hw_config->io_base, 0x10);
 712                release_region(hw_config->io_base+0x10, 0x9);
 713                return 0;
 714        }
 715        if (!set_irq(devc, CONF_PSS, devc->irq))
 716        {
 717                printk("PSS: IRQ allocation error.\n");
 718                release_region(hw_config->io_base, 0x10);
 719                release_region(hw_config->io_base+0x10, 0x9);
 720                return 0;
 721        }
 722        if (!set_dma(devc, CONF_PSS, devc->dma))
 723        {
 724                printk(KERN_ERR "PSS: DMA allocation error\n");
 725                release_region(hw_config->io_base, 0x10);
 726                release_region(hw_config->io_base+0x10, 0x9);
 727                return 0;
 728        }
 729#endif
 730
 731        configure_nonsound_components();
 732        pss_initialized = 1;
 733        sprintf(tmp, "ECHO-PSS  Rev. %d", id);
 734        conf_printf(tmp, hw_config);
 735        return 1;
 736}
 737
 738static int __init probe_pss_mpu(struct address_info *hw_config)
 739{
 740        struct resource *ports;
 741        int timeout;
 742
 743        if (!pss_initialized)
 744                return 0;
 745
 746        ports = request_region(hw_config->io_base, 2, "mpu401");
 747
 748        if (!ports) {
 749                printk(KERN_ERR "PSS: MPU I/O port conflict\n");
 750                return 0;
 751        }
 752        set_io_base(devc, CONF_MIDI, hw_config->io_base);
 753        if (!set_irq(devc, CONF_MIDI, hw_config->irq)) {
 754                printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n");
 755                goto fail;
 756        }
 757        if (!pss_synthLen) {
 758                printk(KERN_ERR "PSS: Can't enable MPU. MIDI synth microcode not available.\n");
 759                goto fail;
 760        }
 761        if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
 762                printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
 763                goto fail;
 764        }
 765
 766        /*
 767         * Finally wait until the DSP algorithm has initialized itself and
 768         * deactivates receive interrupt.
 769         */
 770
 771        for (timeout = 900000; timeout > 0; timeout--)
 772        {
 773                if ((inb(hw_config->io_base + 1) & 0x80) == 0)  /* Input data avail */
 774                        inb(hw_config->io_base);        /* Discard it */
 775                else
 776                        break;  /* No more input */
 777        }
 778
 779        if (!probe_mpu401(hw_config, ports))
 780                goto fail;
 781
 782        attach_mpu401(hw_config, THIS_MODULE);  /* Slot 1 */
 783        if (hw_config->slots[1] != -1)  /* The MPU driver installed itself */
 784                midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations;
 785        return 1;
 786fail:
 787        release_region(hw_config->io_base, 2);
 788        return 0;
 789}
 790
 791static int pss_coproc_open(void *dev_info, int sub_device)
 792{
 793        switch (sub_device)
 794        {
 795                case COPR_MIDI:
 796                        if (pss_synthLen == 0)
 797                        {
 798                                printk(KERN_ERR "PSS: MIDI synth microcode not available.\n");
 799                                return -EIO;
 800                        }
 801                        if (nonstandard_microcode)
 802                                if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 803                        {
 804                                printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
 805                                return -EIO;
 806                        }
 807                        nonstandard_microcode = 0;
 808                        break;
 809
 810                default:
 811                        break;
 812        }
 813        return 0;
 814}
 815
 816static void pss_coproc_close(void *dev_info, int sub_device)
 817{
 818        return;
 819}
 820
 821static void pss_coproc_reset(void *dev_info)
 822{
 823        if (pss_synthLen)
 824                if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
 825                {
 826                        printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
 827                }
 828        nonstandard_microcode = 0;
 829}
 830
 831static int download_boot_block(void *dev_info, copr_buffer * buf)
 832{
 833        if (buf->len <= 0 || buf->len > sizeof(buf->data))
 834                return -EINVAL;
 835
 836        if (!pss_download_boot(devc, buf->data, buf->len, buf->flags))
 837        {
 838                printk(KERN_ERR "PSS: Unable to load microcode block to DSP.\n");
 839                return -EIO;
 840        }
 841        nonstandard_microcode = 1;      /* The MIDI microcode has been overwritten */
 842        return 0;
 843}
 844
 845static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, int local)
 846{
 847        copr_buffer *buf;
 848        copr_msg *mbuf;
 849        copr_debug_buf dbuf;
 850        unsigned short tmp;
 851        unsigned long flags;
 852        unsigned short *data;
 853        int i, err;
 854        /* printk( "PSS coproc ioctl %x %x %d\n",  cmd,  arg,  local); */
 855        
 856        switch (cmd) 
 857        {
 858                case SNDCTL_COPR_RESET:
 859                        pss_coproc_reset(dev_info);
 860                        return 0;
 861
 862                case SNDCTL_COPR_LOAD:
 863                        buf = vmalloc(sizeof(copr_buffer));
 864                        if (buf == NULL)
 865                                return -ENOSPC;
 866                        if (copy_from_user(buf, arg, sizeof(copr_buffer))) {
 867                                vfree(buf);
 868                                return -EFAULT;
 869                        }
 870                        err = download_boot_block(dev_info, buf);
 871                        vfree(buf);
 872                        return err;
 873                
 874                case SNDCTL_COPR_SENDMSG:
 875                        mbuf = vmalloc(sizeof(copr_msg));
 876                        if (mbuf == NULL)
 877                                return -ENOSPC;
 878                        if (copy_from_user(mbuf, arg, sizeof(copr_msg))) {
 879                                vfree(mbuf);
 880                                return -EFAULT;
 881                        }
 882                        data = (unsigned short *)(mbuf->data);
 883                        spin_lock_irqsave(&lock, flags);
 884                        for (i = 0; i < mbuf->len; i++) {
 885                                if (!pss_put_dspword(devc, *data++)) {
 886                                        spin_unlock_irqrestore(&lock,flags);
 887                                        mbuf->len = i;  /* feed back number of WORDs sent */
 888                                        err = copy_to_user(arg, mbuf, sizeof(copr_msg));
 889                                        vfree(mbuf);
 890                                        return err ? -EFAULT : -EIO;
 891                                }
 892                        }
 893                        spin_unlock_irqrestore(&lock,flags);
 894                        vfree(mbuf);
 895                        return 0;
 896
 897                case SNDCTL_COPR_RCVMSG:
 898                        err = 0;
 899                        mbuf = vmalloc(sizeof(copr_msg));
 900                        if (mbuf == NULL)
 901                                return -ENOSPC;
 902                        data = (unsigned short *)mbuf->data;
 903                        spin_lock_irqsave(&lock, flags);
 904                        for (i = 0; i < sizeof(mbuf->data)/sizeof(unsigned short); i++) {
 905                                mbuf->len = i;  /* feed back number of WORDs read */
 906                                if (!pss_get_dspword(devc, data++)) {
 907                                        if (i == 0)
 908                                                err = -EIO;
 909                                        break;
 910                                }
 911                        }
 912                        spin_unlock_irqrestore(&lock,flags);
 913                        if (copy_to_user(arg, mbuf, sizeof(copr_msg)))
 914                                err = -EFAULT;
 915                        vfree(mbuf);
 916                        return err;
 917                
 918                case SNDCTL_COPR_RDATA:
 919                        if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 920                                return -EFAULT;
 921                        spin_lock_irqsave(&lock, flags);
 922                        if (!pss_put_dspword(devc, 0x00d0)) {
 923                                spin_unlock_irqrestore(&lock,flags);
 924                                return -EIO;
 925                        }
 926                        if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) {
 927                                spin_unlock_irqrestore(&lock,flags);
 928                                return -EIO;
 929                        }
 930                        if (!pss_get_dspword(devc, &tmp)) {
 931                                spin_unlock_irqrestore(&lock,flags);
 932                                return -EIO;
 933                        }
 934                        dbuf.parm1 = tmp;
 935                        spin_unlock_irqrestore(&lock,flags);
 936                        if (copy_to_user(arg, &dbuf, sizeof(dbuf)))
 937                                return -EFAULT;
 938                        return 0;
 939                
 940                case SNDCTL_COPR_WDATA:
 941                        if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 942                                return -EFAULT;
 943                        spin_lock_irqsave(&lock, flags);
 944                        if (!pss_put_dspword(devc, 0x00d1)) {
 945                                spin_unlock_irqrestore(&lock,flags);
 946                                return -EIO;
 947                        }
 948                        if (!pss_put_dspword(devc, (unsigned short) (dbuf.parm1 & 0xffff))) {
 949                                spin_unlock_irqrestore(&lock,flags);
 950                                return -EIO;
 951                        }
 952                        tmp = (unsigned int)dbuf.parm2 & 0xffff;
 953                        if (!pss_put_dspword(devc, tmp)) {
 954                                spin_unlock_irqrestore(&lock,flags);
 955                                return -EIO;
 956                        }
 957                        spin_unlock_irqrestore(&lock,flags);
 958                        return 0;
 959                
 960                case SNDCTL_COPR_WCODE:
 961                        if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 962                                return -EFAULT;
 963                        spin_lock_irqsave(&lock, flags);
 964                        if (!pss_put_dspword(devc, 0x00d3)) {
 965                                spin_unlock_irqrestore(&lock,flags);
 966                                return -EIO;
 967                        }
 968                        if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) {
 969                                spin_unlock_irqrestore(&lock,flags);
 970                                return -EIO;
 971                        }
 972                        tmp = (unsigned int)dbuf.parm2 & 0x00ff;
 973                        if (!pss_put_dspword(devc, tmp)) {
 974                                spin_unlock_irqrestore(&lock,flags);
 975                                return -EIO;
 976                        }
 977                        tmp = ((unsigned int)dbuf.parm2 >> 8) & 0xffff;
 978                        if (!pss_put_dspword(devc, tmp)) {
 979                                spin_unlock_irqrestore(&lock,flags);
 980                                return -EIO;
 981                        }
 982                        spin_unlock_irqrestore(&lock,flags);
 983                        return 0;
 984                
 985                case SNDCTL_COPR_RCODE:
 986                        if (copy_from_user(&dbuf, arg, sizeof(dbuf)))
 987                                return -EFAULT;
 988                        spin_lock_irqsave(&lock, flags);
 989                        if (!pss_put_dspword(devc, 0x00d2)) {
 990                                spin_unlock_irqrestore(&lock,flags);
 991                                return -EIO;
 992                        }
 993                        if (!pss_put_dspword(devc, (unsigned short)(dbuf.parm1 & 0xffff))) {
 994                                spin_unlock_irqrestore(&lock,flags);
 995                                return -EIO;
 996                        }
 997                        if (!pss_get_dspword(devc, &tmp)) { /* Read MSB */
 998                                spin_unlock_irqrestore(&lock,flags);
 999                                return -EIO;
1000                        }
1001                        dbuf.parm1 = tmp << 8;
1002                        if (!pss_get_dspword(devc, &tmp)) { /* Read LSB */
1003                                spin_unlock_irqrestore(&lock,flags);
1004                                return -EIO;
1005                        }
1006                        dbuf.parm1 |= tmp & 0x00ff;
1007                        spin_unlock_irqrestore(&lock,flags);
1008                        if (copy_to_user(arg, &dbuf, sizeof(dbuf)))
1009                                return -EFAULT;
1010                        return 0;
1011
1012                default:
1013                        return -EINVAL;
1014        }
1015        return -EINVAL;
1016}
1017
1018static coproc_operations pss_coproc_operations =
1019{
1020        "ADSP-2115",
1021        THIS_MODULE,
1022        pss_coproc_open,
1023        pss_coproc_close,
1024        pss_coproc_ioctl,
1025        pss_coproc_reset,
1026        &pss_data
1027};
1028
1029static int __init probe_pss_mss(struct address_info *hw_config)
1030{
1031        volatile int timeout;
1032        struct resource *ports;
1033        int        my_mix = -999;       /* gcc shut up */
1034
1035        if (!pss_initialized)
1036                return 0;
1037
1038        if (!request_region(hw_config->io_base, 4, "WSS config")) {
1039                printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
1040                return 0;
1041        }
1042        ports = request_region(hw_config->io_base + 4, 4, "ad1848");
1043        if (!ports) {
1044                printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
1045                release_region(hw_config->io_base, 4);
1046                return 0;
1047        }
1048        set_io_base(devc, CONF_WSS, hw_config->io_base);
1049        if (!set_irq(devc, CONF_WSS, hw_config->irq)) {
1050                printk("PSS: WSS IRQ allocation error.\n");
1051                goto fail;
1052        }
1053        if (!set_dma(devc, CONF_WSS, hw_config->dma)) {
1054                printk(KERN_ERR "PSS: WSS DMA allocation error\n");
1055                goto fail;
1056        }
1057        /*
1058         * For some reason the card returns 0xff in the WSS status register
1059         * immediately after boot. Probably MIDI+SB emulation algorithm
1060         * downloaded to the ADSP2115 spends some time initializing the card.
1061         * Let's try to wait until it finishes this task.
1062         */
1063        for (timeout = 0; timeout < 100000 && (inb(hw_config->io_base + WSS_INDEX) &
1064          WSS_INITIALIZING); timeout++)
1065                ;
1066
1067        outb((0x0b), hw_config->io_base + WSS_INDEX);   /* Required by some cards */
1068
1069        for (timeout = 0; (inb(hw_config->io_base + WSS_DATA) & WSS_AUTOCALIBRATION) &&
1070          (timeout < 100000); timeout++)
1071                ;
1072
1073        if (!probe_ms_sound(hw_config, ports))
1074                goto fail;
1075
1076        devc->ad_mixer_dev = NO_WSS_MIXER;
1077        if (pss_mixer) 
1078        {
1079                if ((my_mix = sound_install_mixer (MIXER_DRIVER_VERSION,
1080                        "PSS-SPEAKERS and AD1848 (through MSS audio codec)",
1081                        &pss_mixer_operations,
1082                        sizeof (struct mixer_operations),
1083                        devc)) < 0) 
1084                {
1085                        printk(KERN_ERR "Could not install PSS mixer\n");
1086                        goto fail;
1087                }
1088        }
1089        pss_mixer_reset(devc);
1090        attach_ms_sound(hw_config, ports, THIS_MODULE); /* Slot 0 */
1091
1092        if (hw_config->slots[0] != -1)
1093        {
1094                /* The MSS driver installed itself */
1095                audio_devs[hw_config->slots[0]]->coproc = &pss_coproc_operations;
1096                if (pss_mixer && (num_mixers == (my_mix + 2)))
1097                {
1098                        /* The MSS mixer installed */
1099                        devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev;
1100                }
1101        }
1102        return 1;
1103fail:
1104        release_region(hw_config->io_base + 4, 4);
1105        release_region(hw_config->io_base, 4);
1106        return 0;
1107}
1108
1109static inline void __exit unload_pss(struct address_info *hw_config)
1110{
1111        release_region(hw_config->io_base, 0x10);
1112        release_region(hw_config->io_base+0x10, 0x9);
1113}
1114
1115static inline void __exit unload_pss_mpu(struct address_info *hw_config)
1116{
1117        unload_mpu401(hw_config);
1118}
1119
1120static inline void __exit unload_pss_mss(struct address_info *hw_config)
1121{
1122        unload_ms_sound(hw_config);
1123}
1124
1125
1126static struct address_info cfg;
1127static struct address_info cfg2;
1128static struct address_info cfg_mpu;
1129
1130static int pss_io __initdata    = -1;
1131static int mss_io __initdata    = -1;
1132static int mss_irq __initdata   = -1;
1133static int mss_dma __initdata   = -1;
1134static int mpu_io __initdata    = -1;
1135static int mpu_irq __initdata   = -1;
1136static bool pss_no_sound = 0;   /* Just configure non-sound components */
1137static bool pss_keep_settings  = 1;     /* Keep hardware settings at module exit */
1138static char *pss_firmware = "/etc/sound/pss_synth";
1139
1140module_param(pss_io, int, 0);
1141MODULE_PARM_DESC(pss_io, "Set i/o base of PSS card (probably 0x220 or 0x240)");
1142module_param(mss_io, int, 0);
1143MODULE_PARM_DESC(mss_io, "Set WSS (audio) i/o base (0x530, 0x604, 0xE80, 0xF40, or other. Address must end in 0 or 4 and must be from 0x100 to 0xFF4)");
1144module_param(mss_irq, int, 0);
1145MODULE_PARM_DESC(mss_irq, "Set WSS (audio) IRQ (3, 5, 7, 9, 10, 11, 12)");
1146module_param(mss_dma, int, 0);
1147MODULE_PARM_DESC(mss_dma, "Set WSS (audio) DMA (0, 1, 3)");
1148module_param(mpu_io, int, 0);
1149MODULE_PARM_DESC(mpu_io, "Set MIDI i/o base (0x330 or other. Address must be on 4 location boundaries and must be from 0x100 to 0xFFC)");
1150module_param(mpu_irq, int, 0);
1151MODULE_PARM_DESC(mpu_irq, "Set MIDI IRQ (3, 5, 7, 9, 10, 11, 12)");
1152module_param(pss_cdrom_port, int, 0);
1153MODULE_PARM_DESC(pss_cdrom_port, "Set the PSS CDROM port i/o base (0x340 or other)");
1154module_param(pss_enable_joystick, bool, 0);
1155MODULE_PARM_DESC(pss_enable_joystick, "Enables the PSS joystick port (1 to enable, 0 to disable)");
1156module_param(pss_no_sound, bool, 0);
1157MODULE_PARM_DESC(pss_no_sound, "Configure sound compoents (0 - no, 1 - yes)");
1158module_param(pss_keep_settings, bool, 0);
1159MODULE_PARM_DESC(pss_keep_settings, "Keep hardware setting at driver unloading (0 - no, 1 - yes)");
1160module_param(pss_firmware, charp, 0);
1161MODULE_PARM_DESC(pss_firmware, "Location of the firmware file (default - /etc/sound/pss_synth)");
1162module_param(pss_mixer, bool, 0);
1163MODULE_PARM_DESC(pss_mixer, "Enable (1) or disable (0) PSS mixer (controlling of output volume, bass, treble, synth volume). The mixer is not available on all PSS cards.");
1164MODULE_AUTHOR("Hannu Savolainen, Vladimir Michl");
1165MODULE_DESCRIPTION("Module for PSS sound cards (based on AD1848, ADSP-2115 and ESC614). This module includes control of output amplifier and synth volume of the Beethoven ADSP-16 card (this may work with other PSS cards).");
1166MODULE_LICENSE("GPL");
1167
1168
1169static int fw_load = 0;
1170static int pssmpu = 0, pssmss = 0;
1171
1172/*
1173 *    Load a PSS sound card module
1174 */
1175
1176static int __init init_pss(void)
1177{
1178
1179        if(pss_no_sound)                /* If configuring only nonsound components */
1180        {
1181                cfg.io_base = pss_io;
1182                if(!probe_pss(&cfg))
1183                        return -ENODEV;
1184                printk(KERN_INFO "ECHO-PSS  Rev. %d\n", inw(REG(PSS_ID)) & 0x00ff);
1185                printk(KERN_INFO "PSS: loading in no sound mode.\n");
1186                disable_all_emulations();
1187                configure_nonsound_components();
1188                release_region(pss_io, 0x10);
1189                release_region(pss_io + 0x10, 0x9);
1190                return 0;
1191        }
1192
1193        cfg.io_base = pss_io;
1194
1195        cfg2.io_base = mss_io;
1196        cfg2.irq = mss_irq;
1197        cfg2.dma = mss_dma;
1198
1199        cfg_mpu.io_base = mpu_io;
1200        cfg_mpu.irq = mpu_irq;
1201
1202        if (cfg.io_base == -1 || cfg2.io_base == -1 || cfg2.irq == -1 || cfg.dma == -1) {
1203                printk(KERN_INFO "pss: mss_io, mss_dma, mss_irq and pss_io must be set.\n");
1204                return -EINVAL;
1205        }
1206
1207        if (!pss_synth) {
1208                fw_load = 1;
1209                pss_synthLen = mod_firmware_load(pss_firmware, (void *) &pss_synth);
1210        }
1211        if (!attach_pss(&cfg))
1212                return -ENODEV;
1213        /*
1214         *    Attach stuff
1215         */
1216        if (probe_pss_mpu(&cfg_mpu))
1217                pssmpu = 1;
1218
1219        if (probe_pss_mss(&cfg2))
1220                pssmss = 1;
1221
1222        return 0;
1223}
1224
1225static void __exit cleanup_pss(void)
1226{
1227        if(!pss_no_sound)
1228        {
1229                if(fw_load && pss_synth)
1230                        vfree(pss_synth);
1231                if(pssmss)
1232                        unload_pss_mss(&cfg2);
1233                if(pssmpu)
1234                        unload_pss_mpu(&cfg_mpu);
1235                unload_pss(&cfg);
1236        } else if (pss_cdrom_port != -1)
1237                release_region(pss_cdrom_port, 2);
1238
1239        if(!pss_keep_settings)  /* Keep hardware settings if asked */
1240        {
1241                disable_all_emulations();
1242                printk(KERN_INFO "Resetting PSS sound card configurations.\n");
1243        }
1244}
1245
1246module_init(init_pss);
1247module_exit(cleanup_pss);
1248
1249#ifndef MODULE
1250static int __init setup_pss(char *str)
1251{
1252        /* io, mss_io, mss_irq, mss_dma, mpu_io, mpu_irq */
1253        int ints[7];
1254        
1255        str = get_options(str, ARRAY_SIZE(ints), ints);
1256
1257        pss_io  = ints[1];
1258        mss_io  = ints[2];
1259        mss_irq = ints[3];
1260        mss_dma = ints[4];
1261        mpu_io  = ints[5];
1262        mpu_irq = ints[6];
1263
1264        return 1;
1265}
1266
1267__setup("pss=", setup_pss);
1268#endif
1269
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.