^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);