Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);