static int __devinit jazz16_detect_board(unsigned long port, unsigned long mpu_port) { int err; int val; struct snd_sb chip; if (!request_region(port, 0x10, "jazz16")) { snd_printk(KERN_ERR "I/O port region is already in use.\n"); return -EBUSY; } /* just to call snd_sbdsp_command/reset/get_byte() */ chip.port = port; err = snd_sbdsp_reset(&chip); if (err < 0) for (val = 0; val < 4; val++) { err = jazz16_configure_ports(port, mpu_port, val); if (err < 0) break; err = snd_sbdsp_reset(&chip); if (!err) break; } if (err < 0) { err = -ENODEV; goto err_unmap; } if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_BRD_REV)) { err = -EBUSY; goto err_unmap; } val = snd_sbdsp_get_byte(&chip); if (val >= 0x30) snd_sbdsp_get_byte(&chip); if ((val & 0xf0) != 0x10) { err = -ENODEV; goto err_unmap; } if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_MODEL)) { err = -EBUSY; goto err_unmap; } snd_sbdsp_get_byte(&chip); err = snd_sbdsp_get_byte(&chip); snd_printd("Media Vision Jazz16 board detected: rev 0x%x, model 0x%x\n", val, err); err = 0; err_unmap: release_region(port, 0x10); return err; }
static int snd_sb8dsp_midi_output_open(struct snd_rawmidi_substream *substream) { unsigned long flags; struct snd_sb *chip; unsigned int valid_open_flags; chip = substream->rmidi->private_data; valid_open_flags = chip->hardware >= SB_HW_20 ? SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER : 0; spin_lock_irqsave(&chip->open_lock, flags); if (chip->open & ~valid_open_flags) { spin_unlock_irqrestore(&chip->open_lock, flags); return -EAGAIN; } chip->open |= SB_OPEN_MIDI_OUTPUT; chip->midi_substream_output = substream; if (!(chip->open & SB_OPEN_MIDI_INPUT)) { spin_unlock_irqrestore(&chip->open_lock, flags); snd_sbdsp_reset(chip); /* reset DSP */ if (chip->hardware >= SB_HW_20) snd_sbdsp_command(chip, SB_DSP_MIDI_UART_IRQ); } else { spin_unlock_irqrestore(&chip->open_lock, flags); } return 0; }
static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream, int cmd) { unsigned long flags; struct snd_sb *chip = snd_pcm_substream_chip(substream); unsigned int count; spin_lock_irqsave(&chip->reg_lock, flags); switch (cmd) { case SNDRV_PCM_TRIGGER_START: snd_sbdsp_command(chip, chip->playback_format); if (chip->playback_format == SB_DSP_OUTPUT) { count = chip->p_period_size - 1; snd_sbdsp_command(chip, count & 0xff); snd_sbdsp_command(chip, count >> 8); } break; case SNDRV_PCM_TRIGGER_STOP: if (chip->playback_format == SB_DSP_HI_OUTPUT_AUTO) { struct snd_pcm_runtime *runtime = substream->runtime; snd_sbdsp_reset(chip); if (runtime->channels > 1) { spin_lock(&chip->mixer_lock); /* restore output filter and set hardware to mono mode */ snd_sbmixer_write(chip, SB_DSP_STEREO_SW, chip->force_mode16 & ~0x02); spin_unlock(&chip->mixer_lock); } } else { snd_sbdsp_command(chip, SB_DSP_DMA8_OFF); } snd_sbdsp_command(chip, SB_DSP_SPEAKER_OFF); }
static int snd_jazz16_resume(struct device *pdev, unsigned int n) { struct snd_card *card = dev_get_drvdata(pdev); struct snd_card_jazz16 *acard = card->private_data; struct snd_sb *chip = acard->chip; snd_sbdsp_reset(chip); snd_sbmixer_resume(chip); snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; }
static int snd_sb8_resume(struct platform_device *dev) { struct snd_card *card = platform_get_drvdata(dev); struct snd_sb8 *acard = card->private_data; struct snd_sb *chip = acard->chip; snd_sbdsp_reset(chip); snd_sbmixer_resume(chip); snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; }
static int snd_sb8dsp_midi_output_close(struct snd_rawmidi_substream *substream) { unsigned long flags; struct snd_sb *chip; chip = substream->rmidi->private_data; spin_lock_irqsave(&chip->open_lock, flags); chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER); chip->midi_substream_output = NULL; if (!(chip->open & SB_OPEN_MIDI_INPUT)) { spin_unlock_irqrestore(&chip->open_lock, flags); snd_sbdsp_reset(chip); /* reset DSP */ } else { spin_unlock_irqrestore(&chip->open_lock, flags); } return 0; }
static int snd_sbdsp_probe(struct snd_sb * chip) { int version; int major, minor; char *str; unsigned long flags; /* * initialization sequence */ spin_lock_irqsave(&chip->reg_lock, flags); if (snd_sbdsp_reset(chip) < 0) { spin_unlock_irqrestore(&chip->reg_lock, flags); return -ENODEV; } version = snd_sbdsp_version(chip); if (version < 0) { spin_unlock_irqrestore(&chip->reg_lock, flags); return -ENODEV; } spin_unlock_irqrestore(&chip->reg_lock, flags); major = version >> 8; minor = version & 0xff; snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n", chip->port, major, minor); switch (chip->hardware) { case SB_HW_AUTO: switch (major) { case 1: chip->hardware = SB_HW_10; str = "1.0"; break; case 2: if (minor) { chip->hardware = SB_HW_201; str = "2.01+"; } else { chip->hardware = SB_HW_20; str = "2.0"; } break; case 3: chip->hardware = SB_HW_PRO; str = "Pro"; break; case 4: chip->hardware = SB_HW_16; str = "16"; break; default: snd_printk(KERN_INFO "SB [0x%lx]: unknown DSP chip version %i.%i\n", chip->port, major, minor); return -ENODEV; } break; case SB_HW_ALS100: str = "16 (ALS-100)"; break; case SB_HW_ALS4000: str = "16 (ALS-4000)"; break; case SB_HW_DT019X: str = "(DT019X/ALS007)"; break; default: return -ENODEV; } sprintf(chip->name, "Sound Blaster %s", str); chip->version = (major << 8) | minor; return 0; }