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