void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file) { if ((file ? file->f_mode : chip->mode) & FMODE_READ) { clear_bit(F_READING, &chip->flags); snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); snd_msnd_disable_irq(chip); if (file) { snd_printd(KERN_INFO LOGNAME ": Stopping read for %p\n", file); chip->mode &= ~FMODE_READ; } clear_bit(F_AUDIO_READ_INUSE, &chip->flags); } if ((file ? file->f_mode : chip->mode) & FMODE_WRITE) { if (test_bit(F_WRITING, &chip->flags)) { snd_msnd_dsp_write_flush(chip); snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); } snd_msnd_disable_irq(chip); if (file) { snd_printd(KERN_INFO LOGNAME ": Stopping write for %p\n", file); chip->mode &= ~FMODE_WRITE; } clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags); } }
static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd) { if (snd_msnd_send_dsp_cmd(chip, cmd) == 0) return 0; snd_msnd_dsp_full_reset(chip->card); return snd_msnd_send_dsp_cmd(chip, cmd); }
static int snd_msndmix_set_mux(struct snd_msnd *chip, int val) { unsigned newrecsrc; int change; unsigned char msndbyte; switch (val) { case 0: newrecsrc = MSND_MASK_IMIX; msndbyte = HDEXAR_SET_ANA_IN; break; case 1: newrecsrc = MSND_MASK_SYNTH; msndbyte = HDEXAR_SET_SYNTH_IN; break; case 2: newrecsrc = MSND_MASK_DIGITAL; msndbyte = HDEXAR_SET_DAT_IN; break; default: return -EINVAL; } change = newrecsrc != chip->recsrc; if (change) { change = 0; if (!snd_msnd_send_word(chip, 0, 0, msndbyte)) if (!snd_msnd_send_dsp_cmd(chip, HDEX_AUX_REQ)) { chip->recsrc = newrecsrc; change = 1; } } return change; }
int snd_msnd_DAPQ(struct snd_msnd *chip, int start) { u16 DAPQ_tail; int protect = start, nbanks = 0; void *DAQD; static int play_banks_submitted; /* unsigned long flags; spin_lock_irqsave(&chip->lock, flags); not necessary */ DAPQ_tail = readw(chip->DAPQ + JQS_wTail); while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) { int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size); if (start) { start = 0; play_banks_submitted = 0; } /* Get our digital audio queue struct */ DAQD = bank_num * DAQDS__size + chip->mappedbase + DAPQ_DATA_BUFF; /* Write size of this bank */ writew(chip->play_period_bytes, DAQD + DAQDS_wSize); if (play_banks_submitted < 3) ++play_banks_submitted; else if (chip->playPeriods == 2) { unsigned short offset = chip->play_period_bytes; if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0)) offset = 0; writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart); } ++nbanks; /* Then advance the tail */ /* if (protect) snd_printd(KERN_INFO "B %X %lX\n", bank_num, xtime.tv_usec); */ DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size); writew(DAPQ_tail, chip->DAPQ + JQS_wTail); /* Tell the DSP to play the bank */ snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START); if (protect) if (2 == bank_num) break; } /* if (protect) snd_printd(KERN_INFO "%lX\n", xtime.tv_usec); */ /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */ return nbanks; }
static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_msnd *chip = snd_pcm_substream_chip(substream); if (cmd == SNDRV_PCM_TRIGGER_START) { chip->last_recbank = -1; set_bit(F_READING, &chip->flags); if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0) return 0; clear_bit(F_READING, &chip->flags); } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { clear_bit(F_READING, &chip->flags); snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP); return 0; } return -EINVAL; }
static int snd_msndmidi_input_close(struct snd_rawmidi_substream *substream) { struct snd_msndmidi *mpu; mpu = substream->rmidi->private_data; snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_STOP); clear_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode); mpu->substream_input = NULL; snd_msnd_disable_irq(mpu->dev); return 0; }
/* * input/output open/close - protected by open_mutex in rawmidi.c */ static int snd_msndmidi_input_open(struct snd_rawmidi_substream *substream) { struct snd_msndmidi *mpu; snd_printdd("snd_msndmidi_input_open()\n"); mpu = substream->rmidi->private_data; mpu->substream_input = substream; snd_msnd_enable_irq(mpu->dev); snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_START); set_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode); return 0; }
static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_msnd *chip = snd_pcm_substream_chip(substream); int result = 0; if (cmd == SNDRV_PCM_TRIGGER_START) { snd_printdd("snd_msnd_playback_trigger(START)\n"); chip->banksPlayed = 0; set_bit(F_WRITING, &chip->flags); snd_msnd_DAPQ(chip, 1); } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { snd_printdd("snd_msnd_playback_trigger(STop)\n"); /* interrupt diagnostic, comment this out later */ clear_bit(F_WRITING, &chip->flags); snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP); } else { snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n"); result = -EINVAL; } snd_printdd("snd_msnd_playback_trigger() ENDE\n"); return result; }
static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu) { snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_STOP); snd_msnd_disable_irq(mpu->private_data); }
/* * ALSA callback function, called when attempting to open the MIDI device. */ static int snd_msnd_mpu401_open(struct snd_mpu401 *mpu) { snd_msnd_enable_irq(mpu->private_data); snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_START); return 0; }
static int snd_msndmix_set(struct snd_msnd *dev, int d, int left, int right) { int bLeft, bRight; int wLeft, wRight; int updatemaster = 0; if (d >= LEVEL_ENTRIES) return -EINVAL; bLeft = left * 0xff / 100; wLeft = left * 0xffff / 100; bRight = right * 0xff / 100; wRight = right * 0xffff / 100; dev->left_levels[d] = wLeft; dev->right_levels[d] = wRight; switch (d) { /* master volume unscaled controls */ case MSND_MIXER_LINE: /* line pot control */ /* scaled by IMIX in digital mix */ writeb(bLeft, dev->SMA + SMA_bInPotPosLeft); writeb(bRight, dev->SMA + SMA_bInPotPosRight); if (snd_msnd_send_word(dev, 0, 0, HDEXAR_IN_SET_POTS) == 0) snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); break; case MSND_MIXER_MIC: /* mic pot control */ if (dev->type == msndClassic) return -EINVAL; /* scaled by IMIX in digital mix */ writeb(bLeft, dev->SMA + SMA_bMicPotPosLeft); writeb(bRight, dev->SMA + SMA_bMicPotPosRight); if (snd_msnd_send_word(dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0) snd_msnd_send_dsp_cmd(dev, HDEX_AUX_REQ); break; case MSND_MIXER_VOLUME: /* master volume */ writew(wLeft, dev->SMA + SMA_wCurrMastVolLeft); writew(wRight, dev->SMA + SMA_wCurrMastVolRight); /* fall through */ case MSND_MIXER_AUX: /* aux pot control */ /* scaled by master volume */ /* fall through */ /* digital controls */ case MSND_MIXER_SYNTH: /* synth vol (dsp mix) */ case MSND_MIXER_PCM: /* pcm vol (dsp mix) */ case MSND_MIXER_IMIX: /* input monitor (dsp mix) */ /* scaled by master volume */ updatemaster = 1; break; default: return -EINVAL; } if (updatemaster) { /* update master volume scaled controls */ update_volm(MSND_MIXER_PCM, wCurrPlayVol); update_volm(MSND_MIXER_IMIX, wCurrInVol); if (dev->type == msndPinnacle) update_volm(MSND_MIXER_SYNTH, wCurrMHdrVol); update_potm(MSND_MIXER_AUX, bAuxPotPos, HDEXAR_AUX_SET_POTS); } return 0; }