linux/sound/isa/sb/sb8_main.c
<<
>>
Prefs
   1/*
   2 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   3 *                   Uros Bizjak <uros@kss-loka.si>
   4 *
   5 *  Routines for control of 8-bit SoundBlaster cards and clones
   6 *  Please note: I don't have access to old SB8 soundcards.
   7 *
   8 *
   9 *   This program is free software; you can redistribute it and/or modify
  10 *   it under the terms of the GNU General Public License as published by
  11 *   the Free Software Foundation; either version 2 of the License, or
  12 *   (at your option) any later version.
  13 *
  14 *   This program is distributed in the hope that it will be useful,
  15 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 *   GNU General Public License for more details.
  18 *
  19 *   You should have received a copy of the GNU General Public License
  20 *   along with this program; if not, write to the Free Software
  21 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  22 *
  23 * --
  24 *
  25 * Thu Apr 29 20:36:17 BST 1999 George David Morrison <gdm@gedamo.demon.co.uk>
  26 *   DSP can't respond to commands whilst in "high speed" mode. Caused 
  27 *   glitching during playback. Fixed.
  28 *
  29 * Wed Jul 12 22:02:55 CEST 2000 Uros Bizjak <uros@kss-loka.si>
  30 *   Cleaned up and rewrote lowlevel routines.
  31 */
  32
  33#include <asm/io.h>
  34#include <asm/dma.h>
  35#include <linux/init.h>
  36#include <linux/time.h>
  37#include <sound/core.h>
  38#include <sound/sb.h>
  39
  40MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Uros Bizjak <uros@kss-loka.si>");
  41MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones");
  42MODULE_LICENSE("GPL");
  43
  44#define SB8_CLOCK       1000000
  45#define SB8_DEN(v)      ((SB8_CLOCK + (v) / 2) / (v))
  46#define SB8_RATE(v)     (SB8_CLOCK / SB8_DEN(v))
  47
  48static struct snd_ratnum clock = {
  49        .num = SB8_CLOCK,
  50        .den_min = 1,
  51        .den_max = 256,
  52        .den_step = 1,
  53};
  54
  55static struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = {
  56        .nrats = 1,
  57        .rats = &clock,
  58};
  59
  60static struct snd_ratnum stereo_clocks[] = {
  61        {
  62                .num = SB8_CLOCK,
  63                .den_min = SB8_DEN(22050),
  64                .den_max = SB8_DEN(22050),
  65                .den_step = 1,
  66        },
  67        {
  68                .num = SB8_CLOCK,
  69                .den_min = SB8_DEN(11025),
  70                .den_max = SB8_DEN(11025),
  71                .den_step = 1,
  72        }
  73};
  74
  75static int snd_sb8_hw_constraint_rate_channels(struct snd_pcm_hw_params *params,
  76                                               struct snd_pcm_hw_rule *rule)
  77{
  78        struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
  79        if (c->min > 1) {
  80                unsigned int num = 0, den = 0;
  81                int err = snd_interval_ratnum(hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE),
  82                                          2, stereo_clocks, &num, &den);
  83                if (err >= 0 && den) {
  84                        params->rate_num = num;
  85                        params->rate_den = den;
  86                }
  87                return err;
  88        }
  89        return 0;
  90}
  91
  92static int snd_sb8_hw_constraint_channels_rate(struct snd_pcm_hw_params *params,
  93                                               struct snd_pcm_hw_rule *rule)
  94{
  95        struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
  96        if (r->min > SB8_RATE(22050) || r->max <= SB8_RATE(11025)) {
  97                struct snd_interval t = { .min = 1, .max = 1 };
  98                return snd_interval_refine(hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS), &t);
  99        }
 100        return 0;
 101}
 102
 103static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream)
 104{
 105        unsigned long flags;
 106        struct snd_sb *chip = snd_pcm_substream_chip(substream);
 107        struct snd_pcm_runtime *runtime = substream->runtime;
 108        unsigned int mixreg, rate, size, count;
 109
 110        rate = runtime->rate;
 111        switch (chip->hardware) {
 112        case SB_HW_PRO:
 113                if (runtime->channels > 1) {
 114                        if (snd_BUG_ON(rate != SB8_RATE(11025) &&
 115                                       rate != SB8_RATE(22050)))
 116                                return -EINVAL;
 117                        chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
 118                        break;
 119                }
 120                /* fallthru */
 121        case SB_HW_201:
 122                if (rate > 23000) {
 123                        chip->playback_format = SB_DSP_HI_OUTPUT_AUTO;
 124                        break;
 125                }
 126                /* fallthru */
 127        case SB_HW_20:
 128                chip->playback_format = SB_DSP_LO_OUTPUT_AUTO;
 129                break;
 130        case SB_HW_10:
 131                chip->playback_format = SB_DSP_OUTPUT;
 132                break;
 133        default:
 134                return -EINVAL;
 135        }
 136        size = chip->p_dma_size = snd_pcm_lib_buffer_bytes(substream);
 137        count = chip->p_period_size = snd_pcm_lib_period_bytes(substream);
 138        spin_lock_irqsave(&chip->reg_lock, flags);
 139        snd_sbdsp_command(chip, SB_DSP_SPEAKER_ON);
 140        if (runtime->channels > 1) {
 141                /* set playback stereo mode */
 142                spin_lock(&chip->mixer_lock);
 143                mixreg = snd_sbmixer_read(chip, SB_DSP_STEREO_SW);
 144                snd_sbmixer_write(chip, SB_DSP_STEREO_SW, mixreg | 0x02);
 145                spin_unlock(&chip->mixer_lock);
 146
 147                /* Soundblaster hardware programming reference guide, 3-23 */
 148                snd_sbdsp_command(chip, SB_DSP_DMA8_EXIT);
 149                runtime->dma_area[0] = 0x80;
 150                snd_dma_program(chip->dma8, runtime->dma_addr, 1, DMA_MODE_WRITE);
 151                /* force interrupt */
 152                chip->mode = SB_MODE_HALT;
 153                snd_sbdsp_command(chip, SB_DSP_OUTPUT);
 154                snd_sbdsp_command(chip, 0);
 155                snd_sbdsp_command(chip, 0);
 156        }
 157        snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
 158        if (runtime->channels > 1) {
 159                snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
 160                spin_lock(&chip->mixer_lock);
 161                /* save output filter status and turn it off */
 162                mixreg = snd_sbmixer_read(chip, SB_DSP_PLAYBACK_FILT);
 163                snd_sbmixer_write(chip, SB_DSP_PLAYBACK_FILT, mixreg | 0x20);
 164                spin_unlock(&chip->mixer_lock);
 165                /* just use force_mode16 for temporary storate... */
 166                chip->force_mode16 = mixreg;
 167        } else {
 168                snd_sbdsp_command(chip, 256 - runtime->rate_den);
 169        }
 170        if (chip->playback_format != SB_DSP_OUTPUT) {
 171                count--;
 172                snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
 173                snd_sbdsp_command(chip, count & 0xff);
 174                snd_sbdsp_command(chip, count >> 8);
 175        }
 176        spin_unlock_irqrestore(&chip->reg_lock, flags);
 177        snd_dma_program(chip->dma8, runtime->dma_addr,
 178                        size, DMA_MODE_WRITE | DMA_AUTOINIT);
 179        return 0;
 180}
 181
 182static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream,
 183                                    int cmd)
 184{
 185        unsigned long flags;
 186        struct snd_sb *chip = snd_pcm_substream_chip(substream);
 187        unsigned int count;
 188
 189        spin_lock_irqsave(&chip->reg_lock, flags);
 190        switch (cmd) {
 191        case SNDRV_PCM_TRIGGER_START:
 192                snd_sbdsp_command(chip, chip->playback_format);
 193                if (chip->playback_format == SB_DSP_OUTPUT) {
 194                        count = chip->p_period_size - 1;
 195                        snd_sbdsp_command(chip, count & 0xff);
 196                        snd_sbdsp_command(chip, count >> 8);
 197                }
 198                break;
 199        case SNDRV_PCM_TRIGGER_STOP:
 200                if (chip->playback_format == SB_DSP_HI_OUTPUT_AUTO) {
 201                        struct snd_pcm_runtime *runtime = substream->runtime;
 202                        snd_sbdsp_reset(chip);
 203                        if (runtime->channels > 1) {
 204                                spin_lock(&chip->mixer_lock);
 205                                /* restore output filter and set hardware to mono mode */ 
 206                                snd_sbmixer_write(chip, SB_DSP_STEREO_SW, chip->force_mode16 & ~0x02);
 207                                spin_unlock(&chip->mixer_lock);
 208                        }
 209                } else {
 210                        snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
 211                }
 212                snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
 213        }
 214        spin_unlock_irqrestore(&chip->reg_lock, flags);
 215        chip->mode = (cmd == SNDRV_PCM_TRIGGER_START) ? SB_MODE_PLAYBACK_8 : SB_MODE_HALT;
 216        return 0;
 217}
 218
 219static int snd_sb8_hw_params(struct snd_pcm_substream *substream,
 220                             struct snd_pcm_hw_params *hw_params)
 221{
 222        return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 223}
 224
 225static int snd_sb8_hw_free(struct snd_pcm_substream *substream)
 226{
 227        snd_pcm_lib_free_pages(substream);
 228        return 0;
 229}
 230
 231static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
 232{
 233        unsigned long flags;
 234        struct snd_sb *chip = snd_pcm_substream_chip(substream);
 235        struct snd_pcm_runtime *runtime = substream->runtime;
 236        unsigned int mixreg, rate, size, count;
 237
 238        rate = runtime->rate;
 239        switch (chip->hardware) {
 240        case SB_HW_PRO:
 241                if (runtime->channels > 1) {
 242                        if (snd_BUG_ON(rate != SB8_RATE(11025) &&
 243                                       rate != SB8_RATE(22050)))
 244                                return -EINVAL;
 245                        chip->capture_format = SB_DSP_HI_INPUT_AUTO;
 246                        break;
 247                }
 248                chip->capture_format = (rate > 23000) ? SB_DSP_HI_INPUT_AUTO : SB_DSP_LO_INPUT_AUTO;
 249                break;
 250        case SB_HW_201:
 251                if (rate > 13000) {
 252                        chip->capture_format = SB_DSP_HI_INPUT_AUTO;
 253                        break;
 254                }
 255                /* fallthru */
 256        case SB_HW_20:
 257                chip->capture_format = SB_DSP_LO_INPUT_AUTO;
 258                break;
 259        case SB_HW_10:
 260                chip->capture_format = SB_DSP_INPUT;
 261                break;
 262        default:
 263                return -EINVAL;
 264        }
 265        size = chip->c_dma_size = snd_pcm_lib_buffer_bytes(substream);
 266        count = chip->c_period_size = snd_pcm_lib_period_bytes(substream);
 267        spin_lock_irqsave(&chip->reg_lock, flags);
 268        snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
 269        if (runtime->channels > 1)
 270                snd_sbdsp_command(chip, SB_DSP_STEREO_8BIT);
 271        snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE);
 272        if (runtime->channels > 1) {
 273                snd_sbdsp_command(chip, 256 - runtime->rate_den / 2);
 274                spin_lock(&chip->mixer_lock);
 275                /* save input filter status and turn it off */
 276                mixreg = snd_sbmixer_read(chip, SB_DSP_CAPTURE_FILT);
 277                snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, mixreg | 0x20);
 278                spin_unlock(&chip->mixer_lock);
 279                /* just use force_mode16 for temporary storate... */
 280                chip->force_mode16 = mixreg;
 281        } else {
 282                snd_sbdsp_command(chip, 256 - runtime->rate_den);
 283        }
 284        if (chip->capture_format != SB_DSP_INPUT) {
 285                count--;
 286                snd_sbdsp_command(chip, SB_DSP_BLOCK_SIZE);
 287                snd_sbdsp_command(chip, count & 0xff);
 288                snd_sbdsp_command(chip, count >> 8);
 289        }
 290        spin_unlock_irqrestore(&chip->reg_lock, flags);
 291        snd_dma_program(chip->dma8, runtime->dma_addr,
 292                        size, DMA_MODE_READ | DMA_AUTOINIT);
 293        return 0;
 294}
 295
 296static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream,
 297                                   int cmd)
 298{
 299        unsigned long flags;
 300        struct snd_sb *chip = snd_pcm_substream_chip(substream);
 301        unsigned int count;
 302
 303        spin_lock_irqsave(&chip->reg_lock, flags);
 304        switch (cmd) {
 305        case SNDRV_PCM_TRIGGER_START:
 306                snd_sbdsp_command(chip, chip->capture_format);
 307                if (chip->capture_format == SB_DSP_INPUT) {
 308                        count = chip->c_period_size - 1;
 309                        snd_sbdsp_command(chip, count & 0xff);
 310                        snd_sbdsp_command(chip, count >> 8);
 311                }
 312                break;
 313        case SNDRV_PCM_TRIGGER_STOP:
 314                if (chip->capture_format == SB_DSP_HI_INPUT_AUTO) {
 315                        struct snd_pcm_runtime *runtime = substream->runtime;
 316                        snd_sbdsp_reset(chip);
 317                        if (runtime->channels > 1) {
 318                                /* restore input filter status */
 319                                spin_lock(&chip->mixer_lock);
 320                                snd_sbmixer_write(chip, SB_DSP_CAPTURE_FILT, chip->force_mode16);
 321                                spin_unlock(&chip->mixer_lock);
 322                                /* set hardware to mono mode */
 323                                snd_sbdsp_command(chip, SB_DSP_MONO_8BIT);
 324                        }
 325                } else {
 326                        snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
 327                }
 328                snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF);
 329        }
 330        spin_unlock_irqrestore(&chip->reg_lock, flags);
 331        chip->mode = (cmd == SNDRV_PCM_TRIGGER_START) ? SB_MODE_CAPTURE_8 : SB_MODE_HALT;
 332        return 0;
 333}
 334
 335irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip)
 336{
 337        struct snd_pcm_substream *substream;
 338        struct snd_pcm_runtime *runtime;
 339
 340        snd_sb_ack_8bit(chip);
 341        switch (chip->mode) {
 342        case SB_MODE_PLAYBACK_8:        /* ok.. playback is active */
 343                substream = chip->playback_substream;
 344                runtime = substream->runtime;
 345                if (chip->playback_format == SB_DSP_OUTPUT)
 346                        snd_sb8_playback_trigger(substream, SNDRV_PCM_TRIGGER_START);
 347                snd_pcm_period_elapsed(substream);
 348                break;
 349        case SB_MODE_CAPTURE_8:
 350                substream = chip->capture_substream;
 351                runtime = substream->runtime;
 352                if (chip->capture_format == SB_DSP_INPUT)
 353                        snd_sb8_capture_trigger(substream, SNDRV_PCM_TRIGGER_START);
 354                snd_pcm_period_elapsed(substream);
 355                break;
 356        }
 357        return IRQ_HANDLED;
 358}
 359
 360static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *substream)
 361{
 362        struct snd_sb *chip = snd_pcm_substream_chip(substream);
 363        size_t ptr;
 364
 365        if (chip->mode != SB_MODE_PLAYBACK_8)
 366                return 0;
 367        ptr = snd_dma_pointer(chip->dma8, chip->p_dma_size);
 368        return bytes_to_frames(substream->runtime, ptr);
 369}
 370
 371static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *substream)
 372{
 373        struct snd_sb *chip = snd_pcm_substream_chip(substream);
 374        size_t ptr;
 375
 376        if (chip->mode != SB_MODE_CAPTURE_8)
 377                return 0;
 378        ptr = snd_dma_pointer(chip->dma8, chip->c_dma_size);
 379        return bytes_to_frames(substream->runtime, ptr);
 380}
 381
 382/*
 383
 384 */
 385
 386static struct snd_pcm_hardware snd_sb8_playback =
 387{
 388        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 389                                 SNDRV_PCM_INFO_MMAP_VALID),
 390        .formats =               SNDRV_PCM_FMTBIT_U8,
 391        .rates =                (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
 392                                 SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_22050),
 393        .rate_min =             4000,
 394        .rate_max =             23000,
 395        .channels_min =         1,
 396        .channels_max =         1,
 397        .buffer_bytes_max =     65536,
 398        .period_bytes_min =     64,
 399        .period_bytes_max =     65536,
 400        .periods_min =          1,
 401        .periods_max =          1024,
 402        .fifo_size =            0,
 403};
 404
 405static struct snd_pcm_hardware snd_sb8_capture =
 406{
 407        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 408                                 SNDRV_PCM_INFO_MMAP_VALID),
 409        .formats =              SNDRV_PCM_FMTBIT_U8,
 410        .rates =                (SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000 |
 411                                 SNDRV_PCM_RATE_11025),
 412        .rate_min =             4000,
 413        .rate_max =             13000,
 414        .channels_min =         1,
 415        .channels_max =         1,
 416        .buffer_bytes_max =     65536,
 417        .period_bytes_min =     64,
 418        .period_bytes_max =     65536,
 419        .periods_min =          1,
 420        .periods_max =          1024,
 421        .fifo_size =            0,
 422};
 423
 424/*
 425 *
 426 */
 427 
 428static int snd_sb8_open(struct snd_pcm_substream *substream)
 429{
 430        struct snd_sb *chip = snd_pcm_substream_chip(substream);
 431        struct snd_pcm_runtime *runtime = substream->runtime;
 432        unsigned long flags;
 433
 434        spin_lock_irqsave(&chip->open_lock, flags);
 435        if (chip->open) {
 436                spin_unlock_irqrestore(&chip->open_lock, flags);
 437                return -EAGAIN;
 438        }
 439        chip->open |= SB_OPEN_PCM;
 440        spin_unlock_irqrestore(&chip->open_lock, flags);
 441        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 442                chip->playback_substream = substream;
 443                runtime->hw = snd_sb8_playback;
 444        } else {
 445                chip->capture_substream = substream;
 446                runtime->hw = snd_sb8_capture;
 447        }
 448        switch (chip->hardware) {
 449        case SB_HW_PRO:
 450                runtime->hw.rate_max = 44100;
 451                runtime->hw.channels_max = 2;
 452                snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 453                                    snd_sb8_hw_constraint_rate_channels, NULL,
 454                                    SNDRV_PCM_HW_PARAM_CHANNELS,
 455                                    SNDRV_PCM_HW_PARAM_RATE, -1);
 456                snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 457                                     snd_sb8_hw_constraint_channels_rate, NULL,
 458                                     SNDRV_PCM_HW_PARAM_RATE, -1);
 459                break;
 460        case SB_HW_201:
 461                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 462                        runtime->hw.rate_max = 44100;
 463                } else {
 464                        runtime->hw.rate_max = 15000;
 465                }
 466        default:
 467                break;
 468        }
 469        snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 470                                      &hw_constraints_clock);
 471        return 0;       
 472}
 473
 474static int snd_sb8_close(struct snd_pcm_substream *substream)
 475{
 476        unsigned long flags;
 477        struct snd_sb *chip = snd_pcm_substream_chip(substream);
 478
 479        chip->playback_substream = NULL;
 480        chip->capture_substream = NULL;
 481        spin_lock_irqsave(&chip->open_lock, flags);
 482        chip->open &= ~SB_OPEN_PCM;
 483        spin_unlock_irqrestore(&chip->open_lock, flags);
 484        return 0;
 485}
 486
 487/*
 488 *  Initialization part
 489 */
 490 
 491static struct snd_pcm_ops snd_sb8_playback_ops = {
 492        .open =                 snd_sb8_open,
 493        .close =                snd_sb8_close,
 494        .ioctl =                snd_pcm_lib_ioctl,
 495        .hw_params =            snd_sb8_hw_params,
 496        .hw_free =              snd_sb8_hw_free,
 497        .prepare =              snd_sb8_playback_prepare,
 498        .trigger =              snd_sb8_playback_trigger,
 499        .pointer =              snd_sb8_playback_pointer,
 500};
 501
 502static struct snd_pcm_ops snd_sb8_capture_ops = {
 503        .open =                 snd_sb8_open,
 504        .close =                snd_sb8_close,
 505        .ioctl =                snd_pcm_lib_ioctl,
 506        .hw_params =            snd_sb8_hw_params,
 507        .hw_free =              snd_sb8_hw_free,
 508        .prepare =              snd_sb8_capture_prepare,
 509        .trigger =              snd_sb8_capture_trigger,
 510        .pointer =              snd_sb8_capture_pointer,
 511};
 512
 513int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm)
 514{
 515        struct snd_card *card = chip->card;
 516        struct snd_pcm *pcm;
 517        int err;
 518
 519        if (rpcm)
 520                *rpcm = NULL;
 521        if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0)
 522                return err;
 523        sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
 524        pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
 525        pcm->private_data = chip;
 526
 527        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops);
 528        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops);
 529
 530        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 531                                              snd_dma_isa_data(),
 532                                              64*1024, 64*1024);
 533
 534        if (rpcm)
 535                *rpcm = pcm;
 536        return 0;
 537}
 538
 539EXPORT_SYMBOL(snd_sb8dsp_pcm);
 540EXPORT_SYMBOL(snd_sb8dsp_interrupt);
 541  /* sb8_midi.c */
 542EXPORT_SYMBOL(snd_sb8dsp_midi_interrupt);
 543EXPORT_SYMBOL(snd_sb8dsp_midi);
 544
 545/*
 546 *  INIT part
 547 */
 548
 549static int __init alsa_sb8_init(void)
 550{
 551        return 0;
 552}
 553
 554static void __exit alsa_sb8_exit(void)
 555{
 556}
 557
 558module_init(alsa_sb8_init)
 559module_exit(alsa_sb8_exit)
 560
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.