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)  *  Universal interface for Audio Codec '97
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *  For more details look to AC '97 component specification revision 2.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *  by Intel Corporation (http://developer.intel.com) and to datasheets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *  for specific codecs.
^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) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <sound/ac97_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <sound/asoundef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include "ac97_id.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include "ac97_local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *  PCM support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) static const unsigned char rate_reg_tables[2][4][9] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)   /* standard rates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)   	/* 3&4 front, 7&8 rear, 6&9 center/lfe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	0xff,				/* slot 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	AC97_PCM_LFE_DAC_RATE,		/* slot 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	AC97_PCM_SURR_DAC_RATE,		/* slot 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	AC97_PCM_SURR_DAC_RATE,		/* slot 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	AC97_PCM_LFE_DAC_RATE,		/* slot 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	0xff,				/* slot 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	0xff,				/* slot 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)   },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)   	/* 7&8 front, 6&9 rear, 10&11 center/lfe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	0xff,				/* slot 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	0xff,				/* slot 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	0xff,				/* slot 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	AC97_PCM_SURR_DAC_RATE,		/* slot 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	AC97_PCM_SURR_DAC_RATE,		/* slot 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	AC97_PCM_LFE_DAC_RATE,		/* slot 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	AC97_PCM_LFE_DAC_RATE,		/* slot 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)   },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)   	/* 6&9 front, 10&11 rear, 3&4 center/lfe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	AC97_PCM_LFE_DAC_RATE,		/* slot 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	AC97_PCM_LFE_DAC_RATE,		/* slot 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	0xff,				/* slot 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	0xff,				/* slot 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	0xff,				/* slot 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	AC97_PCM_SURR_DAC_RATE,		/* slot 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	AC97_PCM_SURR_DAC_RATE,		/* slot 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)   },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)   	/* 10&11 front, 3&4 rear, 7&8 center/lfe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	AC97_PCM_SURR_DAC_RATE,		/* slot 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	AC97_PCM_SURR_DAC_RATE,		/* slot 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	0xff,				/* slot 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	0xff,				/* slot 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	AC97_PCM_LFE_DAC_RATE,		/* slot 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	AC97_PCM_LFE_DAC_RATE,		/* slot 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	0xff,				/* slot 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)   },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)   /* double rates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)   	/* 3&4 front, 7&8 front (t+1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	0xff,				/* slot 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	0xff,				/* slot 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	AC97_PCM_FRONT_DAC_RATE,	/* slot 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	0xff,				/* slot 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	0xff,				/* slot 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	0xff,				/* slot 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)   },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	/* not specified in the specification */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	0xff,				/* slot 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	0xff,				/* slot 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	0xff,				/* slot 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	0xff,				/* slot 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	0xff,				/* slot 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	0xff,				/* slot 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	0xff,				/* slot 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	0xff,				/* slot 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	0xff,				/* slot 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)   },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	0xff,				/* slot 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	0xff,				/* slot 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	0xff,				/* slot 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	0xff,				/* slot 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	0xff,				/* slot 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	0xff,				/* slot 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	0xff,				/* slot 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	0xff,				/* slot 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	0xff,				/* slot 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)   },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)   {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	0xff,				/* slot 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	0xff,				/* slot 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	0xff,				/* slot 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	0xff,				/* slot 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	0xff,				/* slot 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	0xff,				/* slot 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	0xff,				/* slot 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	0xff,				/* slot 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	0xff,				/* slot 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)   }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* FIXME: more various mappings for ADC? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static const unsigned char rate_cregs[9] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	AC97_PCM_LR_ADC_RATE,	/* 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	AC97_PCM_LR_ADC_RATE,	/* 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	0xff,			/* 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	AC97_PCM_MIC_ADC_RATE,	/* 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	0xff,			/* 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	0xff,			/* 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	0xff,			/* 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	0xff,			/* 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	0xff,			/* 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static unsigned char get_slot_reg(struct ac97_pcm *pcm, unsigned short cidx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 				  unsigned short slot, int dbl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (slot < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		return 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	if (slot > 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		return 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	if (pcm->spdif)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		return AC97_SPDIF; /* pseudo register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		return rate_reg_tables[dbl][pcm->r[dbl].rate_table[cidx]][slot - 3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		return rate_cregs[slot - 3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	unsigned short old, bits, reg, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	unsigned int sbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	if (! (ac97->ext_id & AC97_EI_SPDIF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	/* TODO: double rate support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	if (ac97->flags & AC97_CS_SPDIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		case 48000: bits = 0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		case 44100: bits = 1 << AC97_SC_SPSR_SHIFT; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		default: /* invalid - disable output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		reg = AC97_CSR_SPDIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		mask = 1 << AC97_SC_SPSR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		if (ac97->id == AC97_ID_CM9739 && rate != 48000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 			snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		case 44100: bits = AC97_SC_SPSR_44K; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		case 48000: bits = AC97_SC_SPSR_48K; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		case 32000: bits = AC97_SC_SPSR_32K; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		default: /* invalid - disable output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 			snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		reg = AC97_SPDIF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		mask = AC97_SC_SPSR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	mutex_lock(&ac97->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	old = snd_ac97_read(ac97, reg) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	if (old != bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		snd_ac97_update_bits_nolock(ac97, reg, mask, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		/* update the internal spdif bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		sbits = ac97->spdif_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		if (sbits & IEC958_AES0_PROFESSIONAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			sbits &= ~IEC958_AES0_PRO_FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			case 44100: sbits |= IEC958_AES0_PRO_FS_44100; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 			case 48000: sbits |= IEC958_AES0_PRO_FS_48000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 			case 32000: sbits |= IEC958_AES0_PRO_FS_32000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 			sbits &= ~(IEC958_AES3_CON_FS << 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 			switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 			case 44100: sbits |= IEC958_AES3_CON_FS_44100<<24; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 			case 48000: sbits |= IEC958_AES3_CON_FS_48000<<24; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 			case 32000: sbits |= IEC958_AES3_CON_FS_32000<<24; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		ac97->spdif_status = sbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	snd_ac97_update_bits_nolock(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, AC97_EA_SPDIF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	mutex_unlock(&ac97->reg_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  * snd_ac97_set_rate - change the rate of the given input/output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  * @ac97: the ac97 instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  * @reg: the register to change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  * @rate: the sample rate to set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)  * Changes the rate of the given input/output on the codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)  * If the codec doesn't support VAR, the rate must be 48000 (except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)  * for SPDIF).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)  * The valid registers are AC97_PMC_MIC_ADC_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)  * AC97_PCM_FRONT_DAC_RATE, AC97_PCM_LR_ADC_RATE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)  * AC97_PCM_SURR_DAC_RATE and AC97_PCM_LFE_DAC_RATE are accepted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)  * if the codec supports them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  * AC97_SPDIF is accepted as a pseudo register to modify the SPDIF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  * status bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)  * Return: Zero if successful, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	int dbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	dbl = rate > 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	if (dbl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		if (!(ac97->flags & AC97_DOUBLE_RATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		if (reg != AC97_PCM_FRONT_DAC_RATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	snd_ac97_update_power(ac97, reg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	case AC97_PCM_MIC_ADC_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRM) == 0)	/* MIC VRA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 			if (rate != 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	case AC97_PCM_FRONT_DAC_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	case AC97_PCM_LR_ADC_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRA) == 0)	/* VRA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			if (rate != 48000 && rate != 96000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	case AC97_PCM_SURR_DAC_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		if (! (ac97->scaps & AC97_SCAP_SURROUND_DAC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	case AC97_PCM_LFE_DAC_RATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		if (! (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	case AC97_SPDIF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		/* special case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		return set_spdif_rate(ac97, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (dbl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		rate /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	tmp = (rate * ac97->bus->clock) / 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (tmp > 65535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 				     AC97_EA_DRA, dbl ? AC97_EA_DRA : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	snd_ac97_update(ac97, reg, tmp & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	snd_ac97_read(ac97, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		/* Intel controllers require double rate data to be put in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		 * slots 7+8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 				     AC97_GP_DRSS_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 				     dbl ? AC97_GP_DRSS_78 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		snd_ac97_read(ac97, AC97_GENERAL_PURPOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) EXPORT_SYMBOL(snd_ac97_set_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static unsigned short get_pslots(struct snd_ac97 *ac97, unsigned char *rate_table, unsigned short *spdif_slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	if (!ac97_is_audio(ac97))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	if (ac97_is_rev22(ac97) || ac97_can_amap(ac97)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		unsigned short slots = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		if (ac97_is_rev22(ac97)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 			/* Note: it's simply emulation of AMAP behaviour */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 			u16 es;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 			es = ac97->regs[AC97_EXTENDED_ID] &= ~AC97_EI_DACS_SLOT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 			switch (ac97->addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 			case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 			case 2: es |= (1<<AC97_EI_DACS_SLOT_SHIFT); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 			case 3: es |= (2<<AC97_EI_DACS_SLOT_SHIFT); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 			snd_ac97_write_cache(ac97, AC97_EXTENDED_ID, es);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		switch (ac97->addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 			slots |= (1<<AC97_SLOT_PCM_LEFT)|(1<<AC97_SLOT_PCM_RIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 			if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 				slots |= (1<<AC97_SLOT_PCM_SLEFT)|(1<<AC97_SLOT_PCM_SRIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 			if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 				slots |= (1<<AC97_SLOT_PCM_CENTER)|(1<<AC97_SLOT_LFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 			if (ac97->ext_id & AC97_EI_SPDIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 				if (!(ac97->scaps & AC97_SCAP_SURROUND_DAC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 					*spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT)|(1<<AC97_SLOT_SPDIF_RIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 				else if (!(ac97->scaps & AC97_SCAP_CENTER_LFE_DAC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 					*spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT1)|(1<<AC97_SLOT_SPDIF_RIGHT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 				else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 					*spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT2)|(1<<AC97_SLOT_SPDIF_RIGHT2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			*rate_table = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 			slots |= (1<<AC97_SLOT_PCM_SLEFT)|(1<<AC97_SLOT_PCM_SRIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 			if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 				slots |= (1<<AC97_SLOT_PCM_CENTER)|(1<<AC97_SLOT_LFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 			if (ac97->ext_id & AC97_EI_SPDIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 				if (!(ac97->scaps & AC97_SCAP_SURROUND_DAC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 					*spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT1)|(1<<AC97_SLOT_SPDIF_RIGHT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 				else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 					*spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT2)|(1<<AC97_SLOT_SPDIF_RIGHT2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 			*rate_table = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 			slots |= (1<<AC97_SLOT_PCM_CENTER)|(1<<AC97_SLOT_LFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 			if (ac97->ext_id & AC97_EI_SPDIF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 				*spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT2)|(1<<AC97_SLOT_SPDIF_RIGHT2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			*rate_table = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		return slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		unsigned short slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		slots = (1<<AC97_SLOT_PCM_LEFT)|(1<<AC97_SLOT_PCM_RIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 			slots |= (1<<AC97_SLOT_PCM_SLEFT)|(1<<AC97_SLOT_PCM_SRIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 			slots |= (1<<AC97_SLOT_PCM_CENTER)|(1<<AC97_SLOT_LFE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		if (ac97->ext_id & AC97_EI_SPDIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			if (!(ac97->scaps & AC97_SCAP_SURROUND_DAC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 				*spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT)|(1<<AC97_SLOT_SPDIF_RIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 			else if (!(ac97->scaps & AC97_SCAP_CENTER_LFE_DAC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 				*spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT1)|(1<<AC97_SLOT_SPDIF_RIGHT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 				*spdif_slots = (1<<AC97_SLOT_SPDIF_LEFT2)|(1<<AC97_SLOT_SPDIF_RIGHT2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		*rate_table = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		return slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static unsigned short get_cslots(struct snd_ac97 *ac97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	unsigned short slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	if (!ac97_is_audio(ac97))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	slots = (1<<AC97_SLOT_PCM_LEFT)|(1<<AC97_SLOT_PCM_RIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	slots |= (1<<AC97_SLOT_MIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	return slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static unsigned int get_rates(struct ac97_pcm *pcm, unsigned int cidx, unsigned short slots, int dbl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	int i, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	unsigned int rates = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	unsigned char reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	for (i = 3; i < 12; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		if (!(slots & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		reg = get_slot_reg(pcm, cidx, i, dbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		case AC97_PCM_FRONT_DAC_RATE:	idx = AC97_RATES_FRONT_DAC; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		case AC97_PCM_SURR_DAC_RATE:	idx = AC97_RATES_SURR_DAC; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		case AC97_PCM_LFE_DAC_RATE:	idx = AC97_RATES_LFE_DAC; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		case AC97_PCM_LR_ADC_RATE:	idx = AC97_RATES_ADC; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		case AC97_PCM_MIC_ADC_RATE:	idx = AC97_RATES_MIC_ADC; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		default:			idx = AC97_RATES_SPDIF; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		rates &= pcm->r[dbl].codec[cidx]->rates[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	if (!dbl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		rates &= ~(SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 			   SNDRV_PCM_RATE_96000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	return rates;
^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)  * snd_ac97_pcm_assign - assign AC97 slots to given PCM streams
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)  * @bus: the ac97 bus instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)  * @pcms_count: count of PCMs to be assigned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)  * @pcms: PCMs to be assigned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)  * It assigns available AC97 slots for given PCMs. If none or only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)  * some slots are available, pcm->xxx.slots and pcm->xxx.rslots[] members
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)  * are reduced and might be zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)  * Return: Zero if successful, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int snd_ac97_pcm_assign(struct snd_ac97_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 			unsigned short pcms_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 			const struct ac97_pcm *pcms)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	int i, j, k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	const struct ac97_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	struct ac97_pcm *rpcms, *rpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	unsigned short avail_slots[2][4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	unsigned char rate_table[2][4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	unsigned short tmp, slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	unsigned short spdif_slots[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	unsigned int rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	struct snd_ac97 *codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	rpcms = kcalloc(pcms_count, sizeof(struct ac97_pcm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	if (rpcms == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	memset(avail_slots, 0, sizeof(avail_slots));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	memset(rate_table, 0, sizeof(rate_table));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	memset(spdif_slots, 0, sizeof(spdif_slots));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		codec = bus->codec[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		if (!codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		avail_slots[0][i] = get_pslots(codec, &rate_table[0][i], &spdif_slots[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		avail_slots[1][i] = get_cslots(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		if (!(codec->scaps & AC97_SCAP_INDEP_SDIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 			for (j = 0; j < i; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 				if (bus->codec[j])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 					avail_slots[1][i] &= ~avail_slots[1][j];
^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) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	/* first step - exclusive devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	for (i = 0; i < pcms_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		pcm = &pcms[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		rpcm = &rpcms[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		/* low-level driver thinks that it's more clever */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		if (pcm->copy_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 			*rpcm = *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		rpcm->stream = pcm->stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		rpcm->exclusive = pcm->exclusive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		rpcm->spdif = pcm->spdif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 		rpcm->private_value = pcm->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 		rpcm->bus = bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		rpcm->rates = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		slots = pcm->r[0].slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		for (j = 0; j < 4 && slots; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 			if (!bus->codec[j])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 			rates = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 			if (pcm->spdif && pcm->stream == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 				tmp = spdif_slots[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 				tmp = avail_slots[pcm->stream][j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 			if (pcm->exclusive) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 				/* exclusive access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 				tmp &= slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 				for (k = 0; k < i; k++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 					if (rpcm->stream == rpcms[k].stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 						tmp &= ~rpcms[k].r[0].rslots[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 				/* non-exclusive access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 				tmp &= pcm->r[0].slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 			if (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 				rpcm->r[0].rslots[j] = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 				rpcm->r[0].codec[j] = bus->codec[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 				rpcm->r[0].rate_table[j] = rate_table[pcm->stream][j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 				if (bus->no_vra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 					rates = SNDRV_PCM_RATE_48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 				else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 					rates = get_rates(rpcm, j, tmp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 				if (pcm->exclusive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 					avail_slots[pcm->stream][j] &= ~tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 			slots &= ~tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 			rpcm->r[0].slots |= tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 			rpcm->rates &= rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		/* for double rate, we check the first codec only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		    bus->codec[0] && (bus->codec[0]->flags & AC97_DOUBLE_RATE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		    rate_table[pcm->stream][0] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 			tmp = (1<<AC97_SLOT_PCM_LEFT) | (1<<AC97_SLOT_PCM_RIGHT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 			      (1<<AC97_SLOT_PCM_LEFT_0) | (1<<AC97_SLOT_PCM_RIGHT_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 			if ((tmp & pcm->r[1].slots) == tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 				rpcm->r[1].slots = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 				rpcm->r[1].rslots[0] = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 				rpcm->r[1].rate_table[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 				rpcm->r[1].codec[0] = bus->codec[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 				if (pcm->exclusive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 					avail_slots[pcm->stream][0] &= ~tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 				if (bus->no_vra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 					rates = SNDRV_PCM_RATE_96000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 				else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 					rates = get_rates(rpcm, 0, tmp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 				rpcm->rates |= rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		if (rpcm->rates == ~0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 			rpcm->rates = 0; /* not used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	bus->pcms_count = pcms_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	bus->pcms = rpcms;
^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) EXPORT_SYMBOL(snd_ac97_pcm_assign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)  * snd_ac97_pcm_open - opens the given AC97 pcm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)  * @pcm: the ac97 pcm instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)  * @rate: rate in Hz, if codec does not support VRA, this value must be 48000Hz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)  * @cfg: output stream characteristics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)  * @slots: a subset of allocated slots (snd_ac97_pcm_assign) for this pcm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)  * It locks the specified slots and sets the given rate to AC97 registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)  * Return: Zero if successful, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		      enum ac97_pcm_cfg cfg, unsigned short slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	struct snd_ac97_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	int i, cidx, r, ok_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	unsigned int reg_ok[4] = {0,0,0,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	unsigned char reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	r = rate > 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	bus = pcm->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	if (cfg == AC97_PCM_CFG_SPDIF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		for (cidx = 0; cidx < 4; cidx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 			if (bus->codec[cidx] && (bus->codec[cidx]->ext_id & AC97_EI_SPDIF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 				err = set_spdif_rate(bus->codec[cidx], rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 				if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 					return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	spin_lock_irq(&pcm->bus->bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	for (i = 3; i < 12; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		if (!(slots & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		ok_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		for (cidx = 0; cidx < 4; cidx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 			if (bus->used_slots[pcm->stream][cidx] & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 				spin_unlock_irq(&pcm->bus->bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 				err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 				goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 			if (pcm->r[r].rslots[cidx] & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 				bus->used_slots[pcm->stream][cidx] |= (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 				ok_flag++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 		if (!ok_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 			spin_unlock_irq(&pcm->bus->bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 			dev_err(bus->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 				"cannot find configuration for AC97 slot %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 				i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 			err = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 			goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	pcm->cur_dbl = r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	spin_unlock_irq(&pcm->bus->bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	for (i = 3; i < 12; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		if (!(slots & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 		for (cidx = 0; cidx < 4; cidx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 			if (pcm->r[r].rslots[cidx] & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 				reg = get_slot_reg(pcm, cidx, i, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 				if (reg == 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 					dev_err(bus->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 						"invalid AC97 slot %i?\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 				if (reg_ok[cidx] & (1 << (reg - AC97_PCM_FRONT_DAC_RATE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 				dev_dbg(bus->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 					"setting ac97 reg 0x%x to rate %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 					reg, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 				err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 				if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 					dev_err(bus->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 						"error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 						cidx, reg, rate, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 				else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 					reg_ok[cidx] |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	pcm->aslots = slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)  error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	pcm->aslots = slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	snd_ac97_pcm_close(pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) EXPORT_SYMBOL(snd_ac97_pcm_open);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)  * snd_ac97_pcm_close - closes the given AC97 pcm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)  * @pcm: the ac97 pcm instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)  * It frees the locked AC97 slots.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)  * Return: Zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) int snd_ac97_pcm_close(struct ac97_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	struct snd_ac97_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	unsigned short slots = pcm->aslots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	int i, cidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) #ifdef CONFIG_SND_AC97_POWER_SAVE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	int r = pcm->cur_dbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	for (i = 3; i < 12; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 		if (!(slots & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 		for (cidx = 0; cidx < 4; cidx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 			if (pcm->r[r].rslots[cidx] & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 				int reg = get_slot_reg(pcm, cidx, i, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 				snd_ac97_update_power(pcm->r[r].codec[cidx],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 						      reg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	bus = pcm->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	spin_lock_irq(&pcm->bus->bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	for (i = 3; i < 12; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 		if (!(slots & (1 << i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 		for (cidx = 0; cidx < 4; cidx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 			bus->used_slots[pcm->stream][cidx] &= ~(1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	pcm->aslots = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	pcm->cur_dbl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	spin_unlock_irq(&pcm->bus->bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) EXPORT_SYMBOL(snd_ac97_pcm_close);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) static int double_rate_hw_constraint_rate(struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 					  struct snd_pcm_hw_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 	struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	if (channels->min > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 		static const struct snd_interval single_rates = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 			.min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 			.max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 		};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 		struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 		return snd_interval_refine(rate, &single_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static int double_rate_hw_constraint_channels(struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 					      struct snd_pcm_hw_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	if (rate->min > 48000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 		static const struct snd_interval double_rate_channels = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 			.min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 			.max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 		};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 		struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 		return snd_interval_refine(channels, &double_rate_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)  * snd_ac97_pcm_double_rate_rules - set double rate constraints
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)  * @runtime: the runtime of the ac97 front playback pcm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)  * Installs the hardware constraint rules to prevent using double rates and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)  * more than two channels at the same time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)  * Return: Zero if successful, or a negative error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 				  double_rate_hw_constraint_rate, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 				  double_rate_hw_constraint_channels, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 				  SNDRV_PCM_HW_PARAM_RATE, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules);