^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) * Abramo Bagnara <abramo@alsa-project.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Cirrus Logic, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Routines for control of Cirrus Logic CS461x chips
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * KNOWN BUGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * - Sometimes the SPDIF input DSP tasks get's unsynchronized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * and the SPDIF get somewhat "distorcionated", or/and left right channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * are swapped. To get around this problem when it happens, mute and unmute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * the SPDIF input mixer control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * - On the Hercules Game Theater XP the amplifier are sometimes turned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * off on inadecuate moments which causes distorcions on sound.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * - Secondary CODEC on some soundcards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * - SPDIF input support for other sample rates then 48khz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * - Posibility to mix the SPDIF output with analog sources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * - PCM channels for Center and LFE on secondary codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * NOTE: with CONFIG_SND_CS46XX_NEW_DSP unset uses old DSP image (which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * is default configuration), no SPDIF, no secondary codec, no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * multi channel PCM. But known to work.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * FINALLY: A credit to the developers Tom and Jordan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * at Cirrus for have helping me out with the DSP, however we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * still don't have sufficient documentation and technical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * references to be able to implement all fancy feutures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * supported by the cs46xx DSP's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Benny <benny@hostmobility.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/gameport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <sound/info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include "cs46xx.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include "cs46xx_lib.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include "dsp_spos.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static void amp_voyetra(struct snd_cs46xx *chip, int change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static const struct snd_pcm_ops snd_cs46xx_playback_rear_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static const struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static const struct snd_pcm_ops snd_cs46xx_playback_clfe_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static const struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static const struct snd_pcm_ops snd_cs46xx_playback_iec958_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static const struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const struct snd_pcm_ops snd_cs46xx_playback_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static const struct snd_pcm_ops snd_cs46xx_playback_indirect_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static const struct snd_pcm_ops snd_cs46xx_capture_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static const struct snd_pcm_ops snd_cs46xx_capture_indirect_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int codec_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned short result,tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u32 offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) codec_index != CS46XX_SECONDARY_CODEC_INDEX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) chip->active_ctrl(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (codec_index == CS46XX_SECONDARY_CODEC_INDEX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) offset = CS46XX_SECONDARY_CODEC_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * 3. Write ACCTL = Control Register = 460h for initiating the write7---55
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * 5. if DCV not cleared, break and return error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * 6. Read ACSTS = Status Register = 464h, check VSTS bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if ((tmp & ACCTL_VFRM) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) dev_warn(chip->card->dev, "ACCTL_VFRM not set 0x%x\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) msleep(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, tmp | ACCTL_ESYN | ACCTL_VFRM );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * Setup the AC97 control registers on the CS461x to send the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * appropriate command to the AC97 to perform the read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * ACCAD = Command Address Register = 46Ch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * ACCDA = Command Data Register = 470h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * ACCTL = Control Register = 460h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * set DCV - will clear when process completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * set CRW - Read command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * set VFRM - valid frame enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * set ESYN - ASYNC generation enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * set RSTN - ARST# inactive, AC97 codec not reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) snd_cs46xx_pokeBA0(chip, BA0_ACCAD, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) snd_cs46xx_pokeBA0(chip, BA0_ACCDA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) snd_cs46xx_pokeBA0(chip, BA0_ACCTL,/* clear ACCTL_DCV */ ACCTL_CRW |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ACCTL_VFRM | ACCTL_ESYN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ACCTL_VFRM | ACCTL_ESYN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * Wait for the read to occur.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) for (count = 0; count < 1000; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * First, we want to wait for a short time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * Now, check to see if the read has completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * ACCTL = 460h, DCV should be reset by now and 460h = 17h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) goto ok1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) "AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) result = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ok1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * Wait for the valid status bit to go active.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) for (count = 0; count < 100; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * Read the AC97 status register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * ACSTS = Status Register = 464h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * VSTS - Valid Status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (snd_cs46xx_peekBA0(chip, BA0_ACSTS + offset) & ACSTS_VSTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) goto ok2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) "AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) codec_index, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) result = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ok2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * Read the data returned from the AC97 register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * ACSDA = Status Data Register = 474h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) "e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) snd_cs46xx_peekBA0(chip, BA0_ACSDA),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) snd_cs46xx_peekBA0(chip, BA0_ACCAD));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) //snd_cs46xx_peekBA0(chip, BA0_ACCAD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) chip->active_ctrl(chip, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static unsigned short snd_cs46xx_ac97_read(struct snd_ac97 * ac97,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct snd_cs46xx *chip = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int codec_index = ac97->num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) codec_index != CS46XX_SECONDARY_CODEC_INDEX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) val = snd_cs46xx_codec_read(chip, reg, codec_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return val;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static void snd_cs46xx_codec_write(struct snd_cs46xx *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned short val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int codec_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) codec_index != CS46XX_SECONDARY_CODEC_INDEX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) chip->active_ctrl(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * 2. Write ACCDA = Command Data Register = 470h for data to write to AC97
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * 3. Write ACCTL = Control Register = 460h for initiating the write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * 5. if DCV not cleared, break and return error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * Setup the AC97 control registers on the CS461x to send the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * appropriate command to the AC97 to perform the read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * ACCAD = Command Address Register = 46Ch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * ACCDA = Command Data Register = 470h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * ACCTL = Control Register = 460h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * set DCV - will clear when process completed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * reset CRW - Write command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * set VFRM - valid frame enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * set ESYN - ASYNC generation enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * set RSTN - ARST# inactive, AC97 codec not reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) snd_cs46xx_pokeBA0(chip, BA0_ACCAD , reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) snd_cs46xx_pokeBA0(chip, BA0_ACCDA , val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) snd_cs46xx_peekBA0(chip, BA0_ACCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, /* clear ACCTL_DCV */ ACCTL_VFRM |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ACCTL_ESYN | ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ACCTL_ESYN | ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) for (count = 0; count < 4000; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * First, we want to wait for a short time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * Now, check to see if the write has completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * ACCTL = 460h, DCV should be reset by now and 460h = 07h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) "AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) codec_index, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) chip->active_ctrl(chip, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static void snd_cs46xx_ac97_write(struct snd_ac97 *ac97,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct snd_cs46xx *chip = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) int codec_index = ac97->num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) codec_index != CS46XX_SECONDARY_CODEC_INDEX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) snd_cs46xx_codec_write(chip, reg, val, codec_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * Chip initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int snd_cs46xx_download(struct snd_cs46xx *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) u32 *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unsigned long offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) unsigned long len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) void __iomem *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) unsigned int bank = offset >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) offset = offset & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (snd_BUG_ON((offset & 3) || (len & 3)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) dst = chip->region.idx[bank+1].remap_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) len /= sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* writel already converts 32-bit value to right endianess */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) while (len-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) writel(*src++, dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) dst += sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static inline void memcpy_le32(void *dst, const void *src, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) #ifdef __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) memcpy(dst, src, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) u32 *_dst = dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) const __le32 *_src = src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) len /= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) while (len-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) *_dst++ = le32_to_cpu(*_src++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static const char *module_names[CS46XX_DSP_MODULES] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) "cwc4630", "cwcasync", "cwcsnoop", "cwcbinhack", "cwcdma"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) MODULE_FIRMWARE("cs46xx/cwc4630");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MODULE_FIRMWARE("cs46xx/cwcasync");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) MODULE_FIRMWARE("cs46xx/cwcsnoop");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) MODULE_FIRMWARE("cs46xx/cwcbinhack");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) MODULE_FIRMWARE("cs46xx/cwcdma");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static void free_module_desc(struct dsp_module_desc *module)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (!module)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) kfree(module->module_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) kfree(module->symbol_table.symbols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (module->segments) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) for (i = 0; i < module->nsegments; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) kfree(module->segments[i].data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) kfree(module->segments);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) kfree(module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* firmware binary format:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * le32 nsymbols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * le32 address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * char symbol_name[DSP_MAX_SYMBOL_NAME];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * le32 symbol_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * } symbols[nsymbols];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * le32 nsegments;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * le32 segment_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * le32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * le32 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * le32 data[size];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * } segments[nsegments];
^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 int load_firmware(struct snd_cs46xx *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct dsp_module_desc **module_ret,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) const char *fw_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) unsigned int nums, fwlen, fwsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) const __le32 *fwdat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct dsp_module_desc *module = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) char fw_path[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) sprintf(fw_path, "cs46xx/%s", fw_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) err = request_firmware(&fw, fw_path, &chip->pci->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) fwsize = fw->size / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (fwsize < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) module = kzalloc(sizeof(*module), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (!module)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) module->module_name = kstrdup(fw_name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (!module->module_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) fwlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) fwdat = (const __le32 *)fw->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) nums = module->symbol_table.nsymbols = le32_to_cpu(fwdat[fwlen++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (nums >= 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) goto error_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) module->symbol_table.symbols =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) kcalloc(nums, sizeof(struct dsp_symbol_entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (!module->symbol_table.symbols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) for (i = 0; i < nums; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) struct dsp_symbol_entry *entry =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) &module->symbol_table.symbols[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (fwlen + 2 + DSP_MAX_SYMBOL_NAME / 4 > fwsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) goto error_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) entry->address = le32_to_cpu(fwdat[fwlen++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) memcpy(entry->symbol_name, &fwdat[fwlen], DSP_MAX_SYMBOL_NAME - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) fwlen += DSP_MAX_SYMBOL_NAME / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) entry->symbol_type = le32_to_cpu(fwdat[fwlen++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (fwlen >= fwsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) goto error_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) nums = module->nsegments = le32_to_cpu(fwdat[fwlen++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (nums > 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) goto error_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) module->segments =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) kcalloc(nums, sizeof(struct dsp_segment_desc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (!module->segments)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) for (i = 0; i < nums; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) struct dsp_segment_desc *entry = &module->segments[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (fwlen + 3 > fwsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) goto error_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) entry->segment_type = le32_to_cpu(fwdat[fwlen++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) entry->offset = le32_to_cpu(fwdat[fwlen++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) entry->size = le32_to_cpu(fwdat[fwlen++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (fwlen + entry->size > fwsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) goto error_inval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) entry->data = kmalloc_array(entry->size, 4, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (!entry->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) memcpy_le32(entry->data, &fwdat[fwlen], entry->size * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) fwlen += entry->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) *module_ret = module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) error_inval:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) free_module_desc(module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) unsigned long offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) unsigned long len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) void __iomem *dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) unsigned int bank = offset >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) offset = offset & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (snd_BUG_ON((offset & 3) || (len & 3)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) dst = chip->region.idx[bank+1].remap_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) len /= sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /* writel already converts 32-bit value to right endianess */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) while (len-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) writel(0, dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) dst += sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) #else /* old DSP image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct ba1_struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) u32 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) } memory[BA1_MEMORY_COUNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) u32 map[BA1_DWORD_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) MODULE_FIRMWARE("cs46xx/ba1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) static int load_firmware(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) const struct firmware *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int i, size, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) err = request_firmware(&fw, "cs46xx/ba1", &chip->pci->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (fw->size != sizeof(*chip->ba1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) chip->ba1 = vmalloc(sizeof(*chip->ba1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (!chip->ba1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) memcpy_le32(chip->ba1, fw->data, sizeof(*chip->ba1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) for (i = 0; i < BA1_MEMORY_COUNT; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) size += chip->ba1->memory[i].size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (size > BA1_DWORD_SIZE * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) release_firmware(fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return err;
^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) int snd_cs46xx_download_image(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int idx, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) unsigned int offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct ba1_struct *ba1 = chip->ba1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) err = snd_cs46xx_download(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) &ba1->map[offset],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ba1->memory[idx].offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ba1->memory[idx].size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) offset += ba1->memory[idx].size >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) #endif /* CONFIG_SND_CS46XX_NEW_DSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * Chip reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static void snd_cs46xx_reset(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * Write the reset bit of the SP control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RSTSP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * Write the control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) snd_cs46xx_poke(chip, BA1_SPCR, SPCR_DRQEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * Clear the trap registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) for (idx = 0; idx < 8; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) snd_cs46xx_poke(chip, BA1_DREG, DREG_REGID_TRAP_SELECT + idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) snd_cs46xx_poke(chip, BA1_TWPR, 0xFFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) snd_cs46xx_poke(chip, BA1_DREG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * Set the frame timer to reflect the number of cycles per frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static int cs46xx_wait_for_fifo(struct snd_cs46xx * chip,int retry_timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) u32 i, status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * Make sure the previous FIFO write operation has completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) for(i = 0; i < 50; i++){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) status = snd_cs46xx_peekBA0(chip, BA0_SERBST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if( !(status & SERBST_WBSY) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) mdelay(retry_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if(status & SERBST_WBSY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) "failure waiting for FIFO command to complete\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static void snd_cs46xx_clear_serial_FIFOs(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) int idx, powerdown = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * See if the devices are powered down. If so, we must power them up first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * or they will not respond.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (!(tmp & CLKCR1_SWCE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) powerdown = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^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) * We want to clear out the serial port FIFOs so we don't end up playing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * whatever random garbage happens to be in them. We fill the sample FIFOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * with zero (silence).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * Fill all 256 sample FIFO locations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) for (idx = 0; idx < 0xFF; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * Make sure the previous FIFO write operation has completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (cs46xx_wait_for_fifo(chip,1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) "failed waiting for FIFO at addr (%02X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (powerdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * Write the serial port FIFO index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * Tell the serial port to load the new value into the FIFO location.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * Now, if we powered up the devices, then power them back down again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * This is kinda ugly, but should never happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (powerdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) static void snd_cs46xx_proc_start(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) int cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * Set the frame timer to reflect the number of cycles per frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * Turn on the run, run at frame, and DMA enable bits in the local copy of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * the SP control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * Wait until the run at frame bit resets itself in the SP control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) for (cnt = 0; cnt < 25; cnt++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (!(snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) dev_err(chip->card->dev, "SPCR_RUNFR never reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) static void snd_cs46xx_proc_stop(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * Turn off the run, run at frame, and DMA enable bits in the local copy of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * the SP control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) snd_cs46xx_poke(chip, BA1_SPCR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * Sample rate routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) #define GOF_PER_SEC 200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) static void snd_cs46xx_set_play_sample_rate(struct snd_cs46xx *chip, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) unsigned int tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) unsigned int phiIncr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) unsigned int correctionPerGOF, correctionPerSec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * Compute the values used to drive the actual sample rate conversion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * The following formulas are being computed, using inline assembly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * since we need to use 64 bit arithmetic to compute the values:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * phiIncr = floor((Fs,in * 2^26) / Fs,out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * GOF_PER_SEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) * GOF_PER_SEC * correctionPerGOF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) * phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) * correctionPerGOF:correctionPerSec =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) * dividend:remainder(ulOther / GOF_PER_SEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) tmp1 = rate << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) phiIncr = tmp1 / 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) tmp1 -= phiIncr * 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) tmp1 <<= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) phiIncr <<= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) tmp2 = tmp1 / 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) phiIncr += tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) tmp1 -= tmp2 * 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) correctionPerGOF = tmp1 / GOF_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) tmp1 -= correctionPerGOF * GOF_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) correctionPerSec = tmp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * Fill in the SampleRateConverter control block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) snd_cs46xx_poke(chip, BA1_PSRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) snd_cs46xx_poke(chip, BA1_PPI, phiIncr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) unsigned int phiIncr, coeffIncr, tmp1, tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) unsigned int correctionPerGOF, correctionPerSec, initialDelay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) unsigned int frameGroupLength, cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * We can only decimate by up to a factor of 1/9th the hardware rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) * Correct the value if an attempt is made to stray outside that limit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if ((rate * 9) < 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) rate = 48000 / 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * We can not capture at a rate greater than the Input Rate (48000).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * Return an error if an attempt is made to stray outside that limit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (rate > 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) rate = 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) * Compute the values used to drive the actual sample rate conversion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) * The following formulas are being computed, using inline assembly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) * since we need to use 64 bit arithmetic to compute the values:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) * coeffIncr = -floor((Fs,out * 2^23) / Fs,in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * phiIncr = floor((Fs,in * 2^26) / Fs,out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) * correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) * GOF_PER_SEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * GOF_PER_SEC * correctionPerGOF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) * initialDelay = ceil((24 * Fs,in) / Fs,out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) * i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * correctionPerGOF:correctionPerSec =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * dividend:remainder(ulOther / GOF_PER_SEC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) tmp1 = rate << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) coeffIncr = tmp1 / 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) tmp1 -= coeffIncr * 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) tmp1 <<= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) coeffIncr <<= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) coeffIncr += tmp1 / 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) coeffIncr ^= 0xFFFFFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) coeffIncr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) tmp1 = 48000 << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) phiIncr = tmp1 / rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) tmp1 -= phiIncr * rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) tmp1 <<= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) phiIncr <<= 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) tmp2 = tmp1 / rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) phiIncr += tmp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) tmp1 -= tmp2 * rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) correctionPerGOF = tmp1 / GOF_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) tmp1 -= correctionPerGOF * GOF_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) correctionPerSec = tmp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) initialDelay = ((48000 * 24) + rate - 1) / rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * Fill in the VariDecimate control block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) snd_cs46xx_poke(chip, BA1_CSRC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) snd_cs46xx_poke(chip, BA1_CCI, coeffIncr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) snd_cs46xx_poke(chip, BA1_CD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) snd_cs46xx_poke(chip, BA1_CPI, phiIncr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * Figure out the frame group length for the write back task. Basically,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * this is just the factors of 24000 (2^6*3*5^3) that are not present in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * the output sample rate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) frameGroupLength = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) for (cnt = 2; cnt <= 64; cnt *= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (((rate / cnt) * cnt) != rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) frameGroupLength *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (((rate / 3) * 3) != rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) frameGroupLength *= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) for (cnt = 5; cnt <= 125; cnt *= 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (((rate / cnt) * cnt) != rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) frameGroupLength *= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * Fill in the WriteBack control block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) snd_cs46xx_poke(chip, BA1_CFG1, frameGroupLength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) snd_cs46xx_poke(chip, BA1_CFG2, (0x00800000 | frameGroupLength));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) snd_cs46xx_poke(chip, BA1_CCST, 0x0000FFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) snd_cs46xx_poke(chip, BA1_CSPB, ((65536 * rate) / 24000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) snd_cs46xx_poke(chip, (BA1_CSPB + 4), 0x0000FFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) * PCM part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static void snd_cs46xx_pb_trans_copy(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct snd_pcm_indirect *rec, size_t bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct snd_cs46xx_pcm * cpcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static int snd_cs46xx_playback_transfer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) struct snd_cs46xx_pcm * cpcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) snd_cs46xx_pb_trans_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) struct snd_pcm_indirect *rec, size_t bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) memcpy(runtime->dma_area + rec->sw_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) chip->capt.hw_buf.area + rec->hw_data, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) static int snd_cs46xx_capture_transfer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) snd_cs46xx_cp_trans_copy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) size_t ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (snd_BUG_ON(!cpcm->pcm_channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) ptr = snd_cs46xx_peek(chip, BA1_PBA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) ptr -= cpcm->hw_buf.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return ptr >> cpcm->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) size_t ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (snd_BUG_ON(!cpcm->pcm_channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) ptr = snd_cs46xx_peek(chip, BA1_PBA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) ptr -= cpcm->hw_buf.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return ptr >> chip->capt.shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static int snd_cs46xx_playback_trigger(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /*struct snd_pcm_runtime *runtime = substream->runtime;*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (! cpcm->pcm_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /* magic value to unmute PCM stream playback volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) SCBVolumeCtrl) << 2, 0x80008000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (cpcm->pcm_channel->unlinked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (substream->runtime->periods != CS46XX_FRAGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) snd_cs46xx_playback_transfer(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) spin_lock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (substream->runtime->periods != CS46XX_FRAGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) snd_cs46xx_playback_transfer(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) { unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) tmp = snd_cs46xx_peek(chip, BA1_PCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) tmp &= 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) spin_unlock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) /* magic mute channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) SCBVolumeCtrl) << 2, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (!cpcm->pcm_channel->unlinked)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) spin_lock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) { unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) tmp = snd_cs46xx_peek(chip, BA1_PCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) tmp &= 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) snd_cs46xx_poke(chip, BA1_PCTL, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) spin_unlock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) static int snd_cs46xx_capture_trigger(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) spin_lock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) tmp = snd_cs46xx_peek(chip, BA1_CCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) tmp &= 0xffff0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) snd_cs46xx_poke(chip, BA1_CCTL, chip->capt.ctl | tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) tmp = snd_cs46xx_peek(chip, BA1_CCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) tmp &= 0xffff0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) snd_cs46xx_poke(chip, BA1_CCTL, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) spin_unlock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46xx_pcm *cpcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) int sample_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) /* If PCMReaderSCB and SrcTaskSCB not created yet ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if ( cpcm->pcm_channel == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) cpcm, cpcm->hw_buf.addr,cpcm->pcm_channel_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (cpcm->pcm_channel == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) "failed to create virtual PCM channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) cpcm->pcm_channel->sample_rate = sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) /* if sample rate is changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if ((int)cpcm->pcm_channel->sample_rate != sample_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) int unlinked = cpcm->pcm_channel->unlinked;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) cpcm->hw_buf.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) cpcm->pcm_channel_id)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) "failed to re-create virtual PCM channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) cpcm->pcm_channel->sample_rate = sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) struct snd_cs46xx_pcm *cpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) int sample_rate = params_rate(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) int period_size = params_period_bytes(hw_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) cpcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) if (snd_BUG_ON(!sample_rate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) mutex_lock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) snd_BUG_ON(!cpcm->pcm_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (!cpcm->pcm_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) "period_size (%d), periods (%d) buffer_size(%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) period_size, params_periods(hw_params),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) params_buffer_bytes(hw_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (params_periods(hw_params) == CS46XX_FRAGS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (runtime->dma_area != cpcm->hw_buf.area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) snd_pcm_lib_free_pages(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) runtime->dma_area = cpcm->hw_buf.area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) runtime->dma_addr = cpcm->hw_buf.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) runtime->dma_bytes = cpcm->hw_buf.bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) substream->ops = &snd_cs46xx_playback_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) substream->ops = &snd_cs46xx_playback_rear_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) substream->ops = &snd_cs46xx_playback_clfe_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) substream->ops = &snd_cs46xx_playback_iec958_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) snd_BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) substream->ops = &snd_cs46xx_playback_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (runtime->dma_area == cpcm->hw_buf.area) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) runtime->dma_area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) runtime->dma_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) runtime->dma_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) substream->ops = &snd_cs46xx_playback_indirect_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) substream->ops = &snd_cs46xx_playback_indirect_rear_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) substream->ops = &snd_cs46xx_playback_indirect_clfe_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) substream->ops = &snd_cs46xx_playback_indirect_iec958_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) snd_BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) substream->ops = &snd_cs46xx_playback_indirect_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) static int snd_cs46xx_playback_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) /*struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) struct snd_cs46xx_pcm *cpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) cpcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) /* if play_back open fails, then this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) is called and cpcm can actually be NULL here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (!cpcm) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (runtime->dma_area != cpcm->hw_buf.area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) snd_pcm_lib_free_pages(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) runtime->dma_area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) runtime->dma_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) runtime->dma_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) static int snd_cs46xx_playback_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) unsigned int pfie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) struct snd_cs46xx_pcm *cpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) cpcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (snd_BUG_ON(!cpcm->pcm_channel))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) pfie &= ~0x0000f03f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) /* old dsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) pfie = snd_cs46xx_peek(chip, BA1_PFIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) pfie &= ~0x0000f03f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) cpcm->shift = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) /* if to convert from stereo to mono */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (runtime->channels == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) cpcm->shift--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) pfie |= 0x00002000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) /* if to convert from 8 bit to 16 bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) if (snd_pcm_format_width(runtime->format) == 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) cpcm->shift--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) pfie |= 0x00001000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) /* if to convert to unsigned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (snd_pcm_format_unsigned(runtime->format))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) pfie |= 0x00008000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) /* Never convert byte order when sample stream is 8 bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (snd_pcm_format_width(runtime->format) != 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) /* convert from big endian to little endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (snd_pcm_format_big_endian(runtime->format))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) pfie |= 0x00004000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) tmp = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) tmp &= ~0x000003ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) tmp |= (4 << cpcm->shift) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) /* playback transaction count register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) /* playback format && interrupt enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2, pfie | cpcm->pcm_channel->pcm_slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) snd_cs46xx_poke(chip, BA1_PBA, cpcm->hw_buf.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) tmp = snd_cs46xx_peek(chip, BA1_PDTC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) tmp &= ~0x000003ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) tmp |= (4 << cpcm->shift) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) snd_cs46xx_poke(chip, BA1_PDTC, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) snd_cs46xx_poke(chip, BA1_PFIE, pfie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) snd_cs46xx_set_play_sample_rate(chip, runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) static int snd_cs46xx_capture_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) cs46xx_dsp_pcm_ostream_set_period (chip, params_period_bytes(hw_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) if (runtime->periods == CS46XX_FRAGS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (runtime->dma_area != chip->capt.hw_buf.area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) snd_pcm_lib_free_pages(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) runtime->dma_area = chip->capt.hw_buf.area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) runtime->dma_addr = chip->capt.hw_buf.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) runtime->dma_bytes = chip->capt.hw_buf.bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) substream->ops = &snd_cs46xx_capture_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (runtime->dma_area == chip->capt.hw_buf.area) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) runtime->dma_area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) runtime->dma_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) runtime->dma_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) substream->ops = &snd_cs46xx_capture_indirect_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) static int snd_cs46xx_capture_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (runtime->dma_area != chip->capt.hw_buf.area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) snd_pcm_lib_free_pages(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) runtime->dma_area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) runtime->dma_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) runtime->dma_bytes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) static int snd_cs46xx_capture_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) chip->capt.shift = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) struct snd_cs46xx *chip = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) u32 status1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) struct dsp_spos_instance * ins = chip->dsp_spos_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) u32 status2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) struct snd_cs46xx_pcm *cpcm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) * Read the Interrupt Status Register to clear the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) status1 = snd_cs46xx_peekBA0(chip, BA0_HISR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if ((status1 & 0x7fffffff) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) status2 = snd_cs46xx_peekBA0(chip, BA0_HSR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (i <= 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) if ( status1 & (1 << i) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (i == CS46XX_DSP_CAPTURE_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (chip->capt.substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) snd_pcm_period_elapsed(chip->capt.substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) if (ins->pcm_channels[i].active &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) ins->pcm_channels[i].private_data &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) !ins->pcm_channels[i].unlinked) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) cpcm = ins->pcm_channels[i].private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) snd_pcm_period_elapsed(cpcm->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if ( status2 & (1 << (i - 16))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) if (ins->pcm_channels[i].active &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) ins->pcm_channels[i].private_data &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) !ins->pcm_channels[i].unlinked) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) cpcm = ins->pcm_channels[i].private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) snd_pcm_period_elapsed(cpcm->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) /* old dsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) if ((status1 & HISR_VC0) && chip->playback_pcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (chip->playback_pcm->substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) snd_pcm_period_elapsed(chip->playback_pcm->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) if ((status1 & HISR_VC1) && chip->pcm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if (chip->capt.substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) snd_pcm_period_elapsed(chip->capt.substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if ((status1 & HISR_MIDI) && chip->rmidi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) unsigned char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) spin_lock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if ((chip->midcr & MIDCR_RIE) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) snd_rawmidi_receive(chip->midi_input, &c, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if ((chip->midcr & MIDCR_TIE) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if (snd_rawmidi_transmit(chip->midi_output, &c, 1) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) chip->midcr &= ~MIDCR_TIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) spin_unlock(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) * EOI to the PCI part....reenables interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) static const struct snd_pcm_hardware snd_cs46xx_playback =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) .info = (SNDRV_PCM_INFO_MMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) /*SNDRV_PCM_INFO_RESUME*/ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) SNDRV_PCM_INFO_SYNC_APPLPTR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) .formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) .rate_min = 5500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) .rate_max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) .buffer_bytes_max = (256 * 1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) .period_bytes_min = CS46XX_MIN_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) .period_bytes_max = CS46XX_MAX_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) .periods_min = CS46XX_FRAGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) .periods_max = 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) .fifo_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) static const struct snd_pcm_hardware snd_cs46xx_capture =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) .info = (SNDRV_PCM_INFO_MMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) SNDRV_PCM_INFO_BLOCK_TRANSFER /*|*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) /*SNDRV_PCM_INFO_RESUME*/ |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) SNDRV_PCM_INFO_SYNC_APPLPTR),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) .formats = SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) .rate_min = 5500,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) .rate_max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) .channels_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) .buffer_bytes_max = (256 * 1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) .period_bytes_min = CS46XX_MIN_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) .period_bytes_max = CS46XX_MAX_PERIOD_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) .periods_min = CS46XX_FRAGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) .periods_max = 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) .fifo_size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) static const unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) static const struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) .count = ARRAY_SIZE(period_sizes),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) .list = period_sizes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) .mask = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) static void snd_cs46xx_pcm_free_substream(struct snd_pcm_runtime *runtime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) kfree(runtime->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,int pcm_channel_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) struct snd_cs46xx_pcm * cpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) cpcm = kzalloc(sizeof(*cpcm), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) if (cpcm == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) PAGE_SIZE, &cpcm->hw_buf) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) kfree(cpcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) runtime->hw = snd_cs46xx_playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) runtime->private_data = cpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) runtime->private_free = snd_cs46xx_pcm_free_substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) cpcm->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) mutex_lock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) cpcm->pcm_channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) cpcm->pcm_channel_id = pcm_channel_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) snd_pcm_hw_constraint_list(runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) &hw_constraints_period_sizes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) chip->playback_pcm = cpcm; /* HACK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) if (chip->accept_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) chip->active_ctrl(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) static int snd_cs46xx_playback_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) dev_dbg(substream->pcm->card->dev, "open front channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) static int snd_cs46xx_playback_open_rear(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) dev_dbg(substream->pcm->card->dev, "open rear channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) static int snd_cs46xx_playback_open_clfe(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) dev_dbg(substream->pcm->card->dev, "open center - LFE channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) dev_dbg(chip->card->dev, "open raw iec958 channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) mutex_lock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) cs46xx_iec958_pre_open (chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) dev_dbg(chip->card->dev, "close raw iec958 channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) err = snd_cs46xx_playback_close(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) mutex_lock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) cs46xx_iec958_post_close (chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) static int snd_cs46xx_capture_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) PAGE_SIZE, &chip->capt.hw_buf) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) chip->capt.substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) substream->runtime->hw = snd_cs46xx_capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (chip->accept_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) chip->active_ctrl(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) snd_pcm_hw_constraint_list(substream->runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) &hw_constraints_period_sizes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) struct snd_cs46xx_pcm * cpcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) cpcm = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) /* when playback_open fails, then cpcm can be NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) if (!cpcm) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) mutex_lock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) if (cpcm->pcm_channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) cpcm->pcm_channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) chip->playback_pcm = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) cpcm->substream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) snd_dma_free_pages(&cpcm->hw_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) chip->active_ctrl(chip, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) static int snd_cs46xx_capture_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) chip->capt.substream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) snd_dma_free_pages(&chip->capt.hw_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) chip->active_ctrl(chip, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) static const struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) .open = snd_cs46xx_playback_open_rear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) .close = snd_cs46xx_playback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) .hw_params = snd_cs46xx_playback_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) .hw_free = snd_cs46xx_playback_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) .prepare = snd_cs46xx_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) .trigger = snd_cs46xx_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) .pointer = snd_cs46xx_playback_direct_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) static const struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) .open = snd_cs46xx_playback_open_rear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) .close = snd_cs46xx_playback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) .hw_params = snd_cs46xx_playback_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) .hw_free = snd_cs46xx_playback_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) .prepare = snd_cs46xx_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) .trigger = snd_cs46xx_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) .pointer = snd_cs46xx_playback_indirect_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) .ack = snd_cs46xx_playback_transfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) static const struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) .open = snd_cs46xx_playback_open_clfe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) .close = snd_cs46xx_playback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) .hw_params = snd_cs46xx_playback_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) .hw_free = snd_cs46xx_playback_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) .prepare = snd_cs46xx_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) .trigger = snd_cs46xx_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) .pointer = snd_cs46xx_playback_direct_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) static const struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) .open = snd_cs46xx_playback_open_clfe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) .close = snd_cs46xx_playback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) .hw_params = snd_cs46xx_playback_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) .hw_free = snd_cs46xx_playback_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) .prepare = snd_cs46xx_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) .trigger = snd_cs46xx_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) .pointer = snd_cs46xx_playback_indirect_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) .ack = snd_cs46xx_playback_transfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) static const struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) .open = snd_cs46xx_playback_open_iec958,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) .close = snd_cs46xx_playback_close_iec958,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) .hw_params = snd_cs46xx_playback_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) .hw_free = snd_cs46xx_playback_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) .prepare = snd_cs46xx_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) .trigger = snd_cs46xx_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) .pointer = snd_cs46xx_playback_direct_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) static const struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) .open = snd_cs46xx_playback_open_iec958,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) .close = snd_cs46xx_playback_close_iec958,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) .hw_params = snd_cs46xx_playback_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) .hw_free = snd_cs46xx_playback_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) .prepare = snd_cs46xx_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) .trigger = snd_cs46xx_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) .pointer = snd_cs46xx_playback_indirect_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) .ack = snd_cs46xx_playback_transfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) static const struct snd_pcm_ops snd_cs46xx_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) .open = snd_cs46xx_playback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) .close = snd_cs46xx_playback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) .hw_params = snd_cs46xx_playback_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) .hw_free = snd_cs46xx_playback_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) .prepare = snd_cs46xx_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) .trigger = snd_cs46xx_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) .pointer = snd_cs46xx_playback_direct_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) static const struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) .open = snd_cs46xx_playback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) .close = snd_cs46xx_playback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) .hw_params = snd_cs46xx_playback_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) .hw_free = snd_cs46xx_playback_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) .prepare = snd_cs46xx_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) .trigger = snd_cs46xx_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) .pointer = snd_cs46xx_playback_indirect_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) .ack = snd_cs46xx_playback_transfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) static const struct snd_pcm_ops snd_cs46xx_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) .open = snd_cs46xx_capture_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) .close = snd_cs46xx_capture_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) .hw_params = snd_cs46xx_capture_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) .hw_free = snd_cs46xx_capture_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) .prepare = snd_cs46xx_capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) .trigger = snd_cs46xx_capture_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) .pointer = snd_cs46xx_capture_direct_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) static const struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) .open = snd_cs46xx_capture_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) .close = snd_cs46xx_capture_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) .hw_params = snd_cs46xx_capture_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) .hw_free = snd_cs46xx_capture_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) .prepare = snd_cs46xx_capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) .trigger = snd_cs46xx_capture_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) .pointer = snd_cs46xx_capture_indirect_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) .ack = snd_cs46xx_capture_transfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) #define MAX_PLAYBACK_CHANNELS (DSP_MAX_PCM_CHANNELS - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) #define MAX_PLAYBACK_CHANNELS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) pcm->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs46xx_capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) /* global setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) strcpy(pcm->name, "CS46xx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) chip->pcm = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) &chip->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) 64*1024, 256*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) pcm->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_rear_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) /* global setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) strcpy(pcm->name, "CS46xx - Rear");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) chip->pcm_rear = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) &chip->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 64*1024, 256*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) if ((err = snd_pcm_new(chip->card, "CS46xx - Center LFE", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) pcm->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_clfe_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) /* global setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) strcpy(pcm->name, "CS46xx - Center LFE");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) chip->pcm_center_lfe = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) &chip->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) 64*1024, 256*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) pcm->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_iec958_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) /* global setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) strcpy(pcm->name, "CS46xx - IEC958");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) chip->pcm_iec958 = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) &chip->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) 64*1024, 256*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) * Mixer routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) static void snd_cs46xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) struct snd_cs46xx *chip = bus->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) chip->ac97_bus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) struct snd_cs46xx *chip = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) if (snd_BUG_ON(ac97 != chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) ac97 != chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) chip->eapd_switch = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) static int snd_cs46xx_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) uinfo->value.integer.max = 0x7fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) static int snd_cs46xx_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) int reg = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) unsigned int val = snd_cs46xx_peek(chip, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) ucontrol->value.integer.value[0] = 0xffff - (val >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) ucontrol->value.integer.value[1] = 0xffff - (val & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) static int snd_cs46xx_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) int reg = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) (0xffff - ucontrol->value.integer.value[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) unsigned int old = snd_cs46xx_peek(chip, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) int change = (old != val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) snd_cs46xx_poke(chip, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) static int snd_cs46xx_vol_dac_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) static int snd_cs46xx_vol_dac_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) chip->dsp_spos_instance->dac_volume_left != ucontrol->value.integer.value[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) cs46xx_dsp_set_dac_volume(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) ucontrol->value.integer.value[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) ucontrol->value.integer.value[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) static int snd_cs46xx_vol_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) static int snd_cs46xx_vol_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) if (chip->dsp_spos_instance->spdif_input_volume_left != ucontrol->value.integer.value[0] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) chip->dsp_spos_instance->spdif_input_volume_right!= ucontrol->value.integer.value[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) cs46xx_dsp_set_iec958_volume (chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) ucontrol->value.integer.value[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) ucontrol->value.integer.value[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) #define snd_mixer_boolean_info snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) int reg = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) int change, res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) switch (kcontrol->private_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) mutex_lock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) if (ucontrol->value.integer.value[0] && !change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) cs46xx_dsp_enable_spdif_out(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) else if (change && !ucontrol->value.integer.value[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) cs46xx_dsp_disable_spdif_out(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) case CS46XX_MIXER_SPDIF_INPUT_ELEMENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) change = chip->dsp_spos_instance->spdif_status_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) if (ucontrol->value.integer.value[0] && !change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) cs46xx_dsp_enable_spdif_in(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) /* restore volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) else if (change && !ucontrol->value.integer.value[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) cs46xx_dsp_disable_spdif_in(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) res = (change != chip->dsp_spos_instance->spdif_status_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) res = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) snd_BUG(); /* should never happen ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) static int snd_cs46xx_adc_capture_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) struct dsp_spos_instance * ins = chip->dsp_spos_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) if (ins->adc_input != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) ucontrol->value.integer.value[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) ucontrol->value.integer.value[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) static int snd_cs46xx_adc_capture_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) struct dsp_spos_instance * ins = chip->dsp_spos_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) if (ucontrol->value.integer.value[0] && !ins->adc_input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) cs46xx_dsp_enable_adc_capture(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) } else if (!ucontrol->value.integer.value[0] && ins->adc_input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) cs46xx_dsp_disable_adc_capture(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) static int snd_cs46xx_pcm_capture_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) struct dsp_spos_instance * ins = chip->dsp_spos_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) if (ins->pcm_input != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) ucontrol->value.integer.value[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) ucontrol->value.integer.value[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) static int snd_cs46xx_pcm_capture_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) struct dsp_spos_instance * ins = chip->dsp_spos_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) if (ucontrol->value.integer.value[0] && !ins->pcm_input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) cs46xx_dsp_enable_pcm_capture(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) } else if (!ucontrol->value.integer.value[0] && ins->pcm_input) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) cs46xx_dsp_disable_pcm_capture(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) static int snd_herc_spdif_select_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) if (val1 & EGPIODR_GPOE0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) ucontrol->value.integer.value[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) ucontrol->value.integer.value[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) * Game Theatre XP card - EGPIO[0] is used to select SPDIF input optical or coaxial.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) static int snd_herc_spdif_select_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) if (ucontrol->value.integer.value[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) /* optical is default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) EGPIODR_GPOE0 | val1); /* enable EGPIO0 output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) EGPIOPTR_GPPT0 | val2); /* open-drain on output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) /* coaxial */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE0); /* disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT0); /* disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) /* checking diff from the EGPIO direction register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) should be enough */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) return (val1 != (int)snd_cs46xx_peekBA0(chip, BA0_EGPIODR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) static int snd_cs46xx_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) static int snd_cs46xx_spdif_default_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) struct dsp_spos_instance * ins = chip->dsp_spos_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) mutex_lock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) ucontrol->value.iec958.status[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) struct dsp_spos_instance * ins = chip->dsp_spos_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) mutex_lock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) /* left and right validity bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) (1 << 13) | (1 << 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) change = (unsigned int)ins->spdif_csuv_default != val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) ins->spdif_csuv_default = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) static int snd_cs46xx_spdif_mask_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) ucontrol->value.iec958.status[0] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) ucontrol->value.iec958.status[1] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) ucontrol->value.iec958.status[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) ucontrol->value.iec958.status[3] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) static int snd_cs46xx_spdif_stream_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) struct dsp_spos_instance * ins = chip->dsp_spos_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) mutex_lock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) ucontrol->value.iec958.status[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) struct dsp_spos_instance * ins = chip->dsp_spos_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) mutex_lock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) /* left and right validity bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) (1 << 13) | (1 << 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) change = ins->spdif_csuv_stream != val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) ins->spdif_csuv_stream = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) mutex_unlock(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) #endif /* CONFIG_SND_CS46XX_NEW_DSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) static const struct snd_kcontrol_new snd_cs46xx_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) .name = "DAC Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) .info = snd_cs46xx_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) #ifndef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) .get = snd_cs46xx_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) .put = snd_cs46xx_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) .private_value = BA1_PVOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) .get = snd_cs46xx_vol_dac_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) .put = snd_cs46xx_vol_dac_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) .name = "ADC Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) .info = snd_cs46xx_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) .get = snd_cs46xx_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) .put = snd_cs46xx_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) #ifndef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) .private_value = BA1_CVOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) .private_value = (VARIDECIMATE_SCB_ADDR + 0xE) << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) .name = "ADC Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) .info = snd_mixer_boolean_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) .get = snd_cs46xx_adc_capture_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) .put = snd_cs46xx_adc_capture_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) .name = "DAC Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) .info = snd_mixer_boolean_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) .get = snd_cs46xx_pcm_capture_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) .put = snd_cs46xx_pcm_capture_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) .name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) .info = snd_mixer_boolean_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) .get = snd_cs46xx_iec958_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) .put = snd_cs46xx_iec958_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) .private_value = CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,SWITCH),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) .info = snd_mixer_boolean_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) .get = snd_cs46xx_iec958_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) .put = snd_cs46xx_iec958_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) .private_value = CS46XX_MIXER_SPDIF_INPUT_ELEMENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) /* Input IEC958 volume does not work for the moment. (Benny) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) .name = SNDRV_CTL_NAME_IEC958("Input ",NONE,VOLUME),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) .info = snd_cs46xx_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) .get = snd_cs46xx_vol_iec958_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) .put = snd_cs46xx_vol_iec958_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) .private_value = (ASYNCRX_SCB_ADDR + 0xE) << 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) .info = snd_cs46xx_spdif_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) .get = snd_cs46xx_spdif_default_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) .put = snd_cs46xx_spdif_default_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) .info = snd_cs46xx_spdif_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) .get = snd_cs46xx_spdif_mask_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) .access = SNDRV_CTL_ELEM_ACCESS_READ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) .info = snd_cs46xx_spdif_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) .get = snd_cs46xx_spdif_stream_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) .put = snd_cs46xx_spdif_stream_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) /* set primary cs4294 codec into Extended Audio Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) static int snd_cs46xx_front_dup_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) val = snd_ac97_read(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], AC97_CSR_ACMODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) ucontrol->value.integer.value[0] = (val & 0x200) ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) static int snd_cs46xx_front_dup_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) return snd_ac97_update_bits(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) AC97_CSR_ACMODE, 0x200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) ucontrol->value.integer.value[0] ? 0 : 0x200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) static const struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) .name = "Duplicate Front",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) .info = snd_mixer_boolean_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) .get = snd_cs46xx_front_dup_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) .put = snd_cs46xx_front_dup_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) /* Only available on the Hercules Game Theater XP soundcard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) static const struct snd_kcontrol_new snd_hercules_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) .name = "Optical/Coaxial SPDIF Input Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) .info = snd_mixer_boolean_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) .get = snd_herc_spdif_select_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) .put = snd_herc_spdif_select_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) unsigned long end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) /* reset to defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) snd_ac97_write(ac97, AC97_RESET, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) /* set the desired CODEC mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) dev_dbg(ac97->bus->card->dev, "CODEC1 mode %04x\n", 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) snd_cs46xx_ac97_write(ac97, AC97_CSR_ACMODE, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) } else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) dev_dbg(ac97->bus->card->dev, "CODEC2 mode %04x\n", 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) snd_cs46xx_ac97_write(ac97, AC97_CSR_ACMODE, 0x3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) snd_BUG(); /* should never happen ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) /* it's necessary to wait awhile until registers are accessible after RESET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) /* because the PCM or MASTER volume registers can be modified, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) /* the REC_GAIN register is used for tests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) end_time = jiffies + HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) unsigned short ext_mid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) /* use preliminary reads to settle the communication */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) snd_ac97_read(ac97, AC97_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) snd_ac97_read(ac97, AC97_VENDOR_ID1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) snd_ac97_read(ac97, AC97_VENDOR_ID2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) /* modem? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) if (ext_mid != 0xffff && (ext_mid & 1) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) /* test if we can write to the record gain volume register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) snd_ac97_write(ac97, AC97_REC_GAIN, 0x8a05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) } while (time_after_eq(end_time, jiffies));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) dev_err(ac97->bus->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) "CS46xx secondary codec doesn't respond!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) static int cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) int idx, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) struct snd_ac97_template ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) memset(&ac97, 0, sizeof(ac97));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) ac97.private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) ac97.private_free = snd_cs46xx_mixer_free_ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) ac97.num = codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) if (chip->amplifier_ctrl == amp_voyetra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) ac97.scaps = AC97_SCAP_INV_EAPD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) if (codec == CS46XX_SECONDARY_CODEC_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) "secondary codec not present\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000, codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) for (idx = 0; idx < 100; ++idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) if (snd_cs46xx_codec_read(chip, AC97_MASTER, codec) == 0x8000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) dev_dbg(chip->card->dev, "codec %d detection timeout\n", codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) struct snd_card *card = chip->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) struct snd_ctl_elem_id id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) static const struct snd_ac97_bus_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) .reset = snd_cs46xx_codec_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) .write = snd_cs46xx_ac97_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) .read = snd_cs46xx_ac97_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) /* detect primary codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) chip->nr_ac97_codecs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) dev_dbg(chip->card->dev, "detecting primary codec\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) chip->nr_ac97_codecs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) dev_dbg(chip->card->dev, "detecting secondary codec\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) /* try detect a secondary codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) chip->nr_ac97_codecs = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) #endif /* CONFIG_SND_CS46XX_NEW_DSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) /* add cs4630 mixer controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) for (idx = 0; idx < ARRAY_SIZE(snd_cs46xx_controls); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) struct snd_kcontrol *kctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) if (kctl && kctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) kctl->id.device = spdif_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) if ((err = snd_ctl_add(card, kctl)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) /* get EAPD mixer switch (for voyetra hack) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) memset(&id, 0, sizeof(id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) strcpy(id.name, "External Amplifier");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) chip->eapd_switch = snd_ctl_find_id(chip->card, &id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) if (chip->nr_ac97_codecs == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) unsigned int id2 = chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]->id & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) if ((id2 & 0xfff0) == 0x5920) { /* CS4294 and CS4298 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) err = snd_ctl_add(card, snd_ctl_new1(&snd_cs46xx_front_dup_ctl, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) snd_ac97_write_cache(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) AC97_CSR_ACMODE, 0x200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) /* do soundcard specific mixer setup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) if (chip->mixer_init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) dev_dbg(chip->card->dev, "calling chip->mixer_init(chip);\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) chip->mixer_init(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) /* turn on amplifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) chip->amplifier_ctrl(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) * RawMIDI interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) static void snd_cs46xx_midi_reset(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, MIDCR_MRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) static int snd_cs46xx_midi_input_open(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) struct snd_cs46xx *chip = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) chip->active_ctrl(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) spin_lock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) chip->uartm |= CS46XX_MODE_INPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) chip->midcr |= MIDCR_RXE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) chip->midi_input = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) snd_cs46xx_midi_reset(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) spin_unlock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) static int snd_cs46xx_midi_input_close(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) struct snd_cs46xx *chip = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) spin_lock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) chip->midi_input = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) snd_cs46xx_midi_reset(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) chip->uartm &= ~CS46XX_MODE_INPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) spin_unlock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) chip->active_ctrl(chip, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) static int snd_cs46xx_midi_output_open(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) struct snd_cs46xx *chip = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) chip->active_ctrl(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) spin_lock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) chip->uartm |= CS46XX_MODE_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) chip->midcr |= MIDCR_TXE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) chip->midi_output = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) if (!(chip->uartm & CS46XX_MODE_INPUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) snd_cs46xx_midi_reset(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) spin_unlock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) static int snd_cs46xx_midi_output_close(struct snd_rawmidi_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) struct snd_cs46xx *chip = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) spin_lock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) chip->midi_output = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) if (!(chip->uartm & CS46XX_MODE_INPUT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) snd_cs46xx_midi_reset(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) chip->uartm &= ~CS46XX_MODE_OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) spin_unlock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) chip->active_ctrl(chip, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) static void snd_cs46xx_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) struct snd_cs46xx *chip = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) if (up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) if ((chip->midcr & MIDCR_RIE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) chip->midcr |= MIDCR_RIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) if (chip->midcr & MIDCR_RIE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) chip->midcr &= ~MIDCR_RIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) static void snd_cs46xx_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) struct snd_cs46xx *chip = substream->rmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) unsigned char byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) if (up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) if ((chip->midcr & MIDCR_TIE) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) chip->midcr |= MIDCR_TIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) /* fill UART FIFO buffer at first, and turn Tx interrupts only if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) while ((chip->midcr & MIDCR_TIE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) (snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) if (snd_rawmidi_transmit(substream, &byte, 1) != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) chip->midcr &= ~MIDCR_TIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) snd_cs46xx_pokeBA0(chip, BA0_MIDWP, byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) if (chip->midcr & MIDCR_TIE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) chip->midcr &= ~MIDCR_TIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) static const struct snd_rawmidi_ops snd_cs46xx_midi_output =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) .open = snd_cs46xx_midi_output_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) .close = snd_cs46xx_midi_output_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) .trigger = snd_cs46xx_midi_output_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) static const struct snd_rawmidi_ops snd_cs46xx_midi_input =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) .open = snd_cs46xx_midi_input_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) .close = snd_cs46xx_midi_input_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) .trigger = snd_cs46xx_midi_input_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) int snd_cs46xx_midi(struct snd_cs46xx *chip, int device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) struct snd_rawmidi *rmidi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) strcpy(rmidi->name, "CS46XX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs46xx_midi_output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs46xx_midi_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) rmidi->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) chip->rmidi = rmidi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) * gameport interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) #if IS_REACHABLE(CONFIG_GAMEPORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) struct snd_cs46xx *chip = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) if (snd_BUG_ON(!chip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) struct snd_cs46xx *chip = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) if (snd_BUG_ON(!chip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) struct snd_cs46xx *chip = gameport_get_port_data(gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) unsigned js1, js2, jst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) if (snd_BUG_ON(!chip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) jst = snd_cs46xx_peekBA0(chip, BA0_JSPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) *buttons = (~jst >> 4) & 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) for(jst=0;jst<4;++jst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) if(axes[jst]==0xFFFF) axes[jst] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) case GAMEPORT_MODE_COOKED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) case GAMEPORT_MODE_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) int snd_cs46xx_gameport(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) struct gameport *gp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) chip->gameport = gp = gameport_allocate_port();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) if (!gp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) "cannot allocate memory for gameport\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) gameport_set_name(gp, "CS46xx Gameport");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) gameport_set_dev_parent(gp, &chip->pci->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) gameport_set_port_data(gp, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) gp->open = snd_cs46xx_gameport_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) gp->read = snd_cs46xx_gameport_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) gp->trigger = snd_cs46xx_gameport_trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) gp->cooked_read = snd_cs46xx_gameport_cooked_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) gameport_register_port(gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) if (chip->gameport) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) gameport_unregister_port(chip->gameport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) chip->gameport = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) int snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) #endif /* CONFIG_GAMEPORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) #ifdef CONFIG_SND_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) * proc interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) static ssize_t snd_cs46xx_io_read(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) void *file_private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) struct file *file, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) size_t count, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) struct snd_cs46xx_region *region = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) if (copy_to_user_fromio(buf, region->remap_addr + pos, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) static const struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) .read = snd_cs46xx_io_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) static int snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) struct snd_info_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) for (idx = 0; idx < 5; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) struct snd_cs46xx_region *region = &chip->region.idx[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) if (! snd_card_proc_new(card, region->name, &entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) entry->content = SNDRV_INFO_CONTENT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) entry->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) entry->c.ops = &snd_cs46xx_proc_io_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) entry->size = region->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) entry->mode = S_IFREG | 0400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) cs46xx_dsp_proc_init(card, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) static int snd_cs46xx_proc_done(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) cs46xx_dsp_proc_done(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) #else /* !CONFIG_SND_PROC_FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) #define snd_cs46xx_proc_init(card, chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) #define snd_cs46xx_proc_done(chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) * stop the h/w
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) static void snd_cs46xx_hw_stop(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) tmp = snd_cs46xx_peek(chip, BA1_PFIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) tmp &= ~0x0000f03f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) tmp |= 0x00000010;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) tmp = snd_cs46xx_peek(chip, BA1_CIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) tmp &= ~0x0000003f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) tmp |= 0x00000011;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) * Stop playback DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) tmp = snd_cs46xx_peek(chip, BA1_PCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) * Stop capture DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) tmp = snd_cs46xx_peek(chip, BA1_CCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) * Reset the processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) snd_cs46xx_reset(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) snd_cs46xx_proc_stop(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) * Power down the PLL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) * Turn off the Processor by turning off the software clock enable flag in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) * the clock control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) static int snd_cs46xx_free(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) if (snd_BUG_ON(!chip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) if (chip->active_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) chip->active_ctrl(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) snd_cs46xx_remove_gameport(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) if (chip->amplifier_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) snd_cs46xx_proc_done(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) if (chip->region.idx[0].resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) snd_cs46xx_hw_stop(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) if (chip->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) free_irq(chip->irq, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) if (chip->active_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) chip->active_ctrl(chip, -chip->amplifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) for (idx = 0; idx < 5; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) struct snd_cs46xx_region *region = &chip->region.idx[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) iounmap(region->remap_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) release_and_free_resource(region->resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) if (chip->dsp_spos_instance) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) cs46xx_dsp_spos_destroy(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) chip->dsp_spos_instance = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) for (idx = 0; idx < CS46XX_DSP_MODULES; idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) free_module_desc(chip->modules[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) vfree(chip->ba1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) kfree(chip->saved_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) pci_disable_device(chip->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) kfree(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) static int snd_cs46xx_dev_free(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) struct snd_cs46xx *chip = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) return snd_cs46xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) * initialize chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) static int snd_cs46xx_chip_init(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) * First, blast the clock control register to zero so that the PLL starts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) * out in a known state, and blast the master serial port control register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) * to zero so that the serial ports also start out in a known state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) snd_cs46xx_pokeBA0(chip, BA0_SERMC1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) * If we are in AC97 mode, then we must set the part to a host controlled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) * AC-link. Otherwise, we won't be able to bring up the link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) SERACC_TWO_CODECS); /* 2.00 dual codecs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) /* snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0); */ /* 2.00 codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_1_03); /* 1.03 codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) * Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) * spec) and then drive it high. This is done for non AC97 modes since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) * there might be logic external to the CS461x that uses the ARST# line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) * for a reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) udelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) * The first thing we do here is to enable sync generation. As soon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) * as we start receiving bit clock, we'll start producing the SYNC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) * signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_ESYN | ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) * Now wait for a short while to allow the AC97 part to start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) * generating bit clock (so we don't try to start the PLL without an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) * input clock).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) mdelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) * Set the serial port timing configuration, so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) * the clock control circuit gets its clock from the correct place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) * Write the selected clock control setup to the hardware. Do not turn on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) * SWCE yet (if requested), so that the devices clocked by the output of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) * PLL are not clocked until the PLL is stable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) snd_cs46xx_pokeBA0(chip, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) snd_cs46xx_pokeBA0(chip, BA0_PLLM, 0x3a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) snd_cs46xx_pokeBA0(chip, BA0_CLKCR2, CLKCR2_PDIVS_8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) * Power up the PLL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) * Wait until the PLL has stabilized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) * Turn on clocking of the core so that we can setup the serial ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP | CLKCR1_SWCE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) * Enable FIFO Host Bypass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) snd_cs46xx_pokeBA0(chip, BA0_SERBCF, SERBCF_HBP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) * Fill the serial port FIFOs with silence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) snd_cs46xx_clear_serial_FIFOs(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) * Set the serial port FIFO pointer to the first sample in the FIFO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) /* snd_cs46xx_pokeBA0(chip, BA0_SERBSP, 0); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) * Write the serial port configuration to the part. The master
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) * enable bit is not set until all other values have been written.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) snd_cs46xx_pokeBA0(chip, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) snd_cs46xx_pokeBA0(chip, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) snd_cs46xx_pokeBA0(chip, BA0_SERC7, SERC7_ASDI2EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) snd_cs46xx_pokeBA0(chip, BA0_SERC3, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) snd_cs46xx_pokeBA0(chip, BA0_SERC4, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) snd_cs46xx_pokeBA0(chip, BA0_SERC5, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) snd_cs46xx_pokeBA0(chip, BA0_SERC6, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) * Wait for the codec ready signal from the AC97 codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) timeout = 150;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) while (timeout-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) * Read the AC97 status register to see if we've seen a CODEC READY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) * signal from the AC97 codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) goto ok1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) "create - never read codec ready from AC'97\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) "it is not probably bug, try to use CS4236 driver\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) ok1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) for (count = 0; count < 150; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) /* First, we want to wait for a short time. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) udelay(25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) if (snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) * Make sure CODEC is READY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) if (!(snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) "never read card ready from secondary AC'97\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) * Assert the vaid frame signal so that we can start sending commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) * to the AC97 codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) * Wait until we've sampled input slots 3 and 4 as valid, meaning that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) * the codec is pumping ADC data across the AC-link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) timeout = 150;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) while (timeout-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) * Read the input slot valid register and see if input slots 3 and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) * 4 are valid yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) goto ok2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) #ifndef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) "create - never read ISV3 & ISV4 from AC'97\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) /* This may happen on a cold boot with a Terratec SiXPack 5.1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) Reloading the driver may help, if there's other soundcards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) with the same problem I would like to know. (Benny) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) dev_err(chip->card->dev, "never read ISV3 & ISV4 from AC'97\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) "Try reloading the ALSA driver, if you find something\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) "broken or not working on your soundcard upon\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) "this message please report to alsa-devel@alsa-project.org\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) ok2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) * Now, assert valid frame and the slot 3 and 4 valid bits. This will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) * commense the transfer of digital audio data to the AC97 codec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) * Power down the DAC and ADC. We will power them up (if) when we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) * them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) /* snd_cs46xx_pokeBA0(chip, BA0_AC97_POWERDOWN, 0x300); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) * Turn off the Processor by turning off the software clock enable flag in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) * the clock control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) /* tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) /* snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) * start and load DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) tmp = snd_cs46xx_peek(chip, BA1_PFIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) tmp &= ~0x0000f03f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) tmp = snd_cs46xx_peek(chip, BA1_CIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) tmp &= ~0x0000003f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) tmp |= 0x00000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) int snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) * Reset the processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) snd_cs46xx_reset(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) * Download the image to the processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) for (i = 0; i < CS46XX_DSP_MODULES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) err = load_firmware(chip, &chip->modules[i], module_names[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) dev_err(chip->card->dev, "firmware load error [%s]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) module_names[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) err = cs46xx_dsp_load_module(chip, chip->modules[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) dev_err(chip->card->dev, "image download error [%s]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) module_names[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) if (cs46xx_dsp_scb_and_task_init(chip) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) err = load_firmware(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) /* old image */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) err = snd_cs46xx_download_image(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) dev_err(chip->card->dev, "image download error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) * Stop playback DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) tmp = snd_cs46xx_peek(chip, BA1_PCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) chip->play_ctl = tmp & 0xffff0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) * Stop capture DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) tmp = snd_cs46xx_peek(chip, BA1_CCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) chip->capt.ctl = tmp & 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) snd_cs46xx_set_play_sample_rate(chip, 8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) snd_cs46xx_set_capture_sample_rate(chip, 8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) snd_cs46xx_proc_start(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) cs46xx_enable_stream_irqs(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) #ifndef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) /* set the attenuation to 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) * AMP control - null AMP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) static void amp_none(struct snd_cs46xx *chip, int change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) u32 idx, valid_slots,tmp,powerdown = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) u16 modem_power,pin_config,logic_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) dev_dbg(chip->card->dev, "cs46xx_setup_eapd_slot()+\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) * See if the devices are powered down. If so, we must power them up first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) * or they will not respond.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) if (!(tmp & CLKCR1_SWCE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) powerdown = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) * Clear PRA. The Bonzo chip will be used for GPIO not for modem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) * stuff.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) if(chip->nr_ac97_codecs != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) "cs46xx_setup_eapd_slot() - no secondary codec configured\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) modem_power = snd_cs46xx_codec_read (chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) AC97_EXTENDED_MSTATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) CS46XX_SECONDARY_CODEC_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) modem_power &=0xFEFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) snd_cs46xx_codec_write(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) AC97_EXTENDED_MSTATUS, modem_power,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) CS46XX_SECONDARY_CODEC_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) * Set GPIO pin's 7 and 8 so that they are configured for output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) pin_config = snd_cs46xx_codec_read (chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) AC97_GPIO_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) CS46XX_SECONDARY_CODEC_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) pin_config &=0x27F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) snd_cs46xx_codec_write(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) AC97_GPIO_CFG, pin_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) CS46XX_SECONDARY_CODEC_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) * Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) logic_type = snd_cs46xx_codec_read(chip, AC97_GPIO_POLARITY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) CS46XX_SECONDARY_CODEC_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) logic_type &=0x27F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) snd_cs46xx_codec_write (chip, AC97_GPIO_POLARITY, logic_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) CS46XX_SECONDARY_CODEC_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) valid_slots |= 0x200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) if ( cs46xx_wait_for_fifo(chip,1) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) dev_dbg(chip->card->dev, "FIFO is busy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) * Fill slots 12 with the correct value for the GPIO pins.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) for(idx = 0x90; idx <= 0x9F; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) * Initialize the fifo so that bits 7 and 8 are on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) * Remember that the GPIO pins in bonzo are shifted by 4 bits to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) * the left. 0x1800 corresponds to bits 7 and 8.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) * Wait for command to complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) if ( cs46xx_wait_for_fifo(chip,200) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) "failed waiting for FIFO at addr (%02X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) * Write the serial port FIFO index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) * Tell the serial port to load the new value into the FIFO location.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) /* wait for last command to complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) cs46xx_wait_for_fifo(chip,200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) * Now, if we powered up the devices, then power them back down again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) * This is kinda ugly, but should never happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) if (powerdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) * Crystal EAPD mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) static void amp_voyetra(struct snd_cs46xx *chip, int change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) /* Manage the EAPD bit on the Crystal 4297
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) and the Analog AD1885 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) int old = chip->amplifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) int oval, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) chip->amplifier += change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) oval = snd_cs46xx_codec_read(chip, AC97_POWERDOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) CS46XX_PRIMARY_CODEC_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) val = oval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) if (chip->amplifier) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) /* Turn the EAPD amp on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) val |= 0x8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) /* Turn the EAPD amp off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) val &= ~0x8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) if (val != oval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) snd_cs46xx_codec_write(chip, AC97_POWERDOWN, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) CS46XX_PRIMARY_CODEC_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) if (chip->eapd_switch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) &chip->eapd_switch->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) if (chip->amplifier && !old) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) voyetra_setup_eapd_slot(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) static void hercules_init(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) /* default: AMP off, and SPDIF input optical */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) * Game Theatre XP card - EGPIO[2] is used to enable the external amp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) static void amp_hercules(struct snd_cs46xx *chip, int change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) int old = chip->amplifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) chip->amplifier += change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) if (chip->amplifier && !old) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) dev_dbg(chip->card->dev, "Hercules amplifier ON\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) EGPIODR_GPOE2 | val1); /* enable EGPIO2 output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) EGPIOPTR_GPPT2 | val2); /* open-drain on output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) } else if (old && !chip->amplifier) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) dev_dbg(chip->card->dev, "Hercules amplifier OFF\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, val1 & ~EGPIODR_GPOE2); /* disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT2); /* disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) static void voyetra_mixer_init (struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) dev_dbg(chip->card->dev, "initializing Voyetra mixer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) /* Enable SPDIF out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) static void hercules_mixer_init (struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) struct snd_card *card = chip->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) /* set EGPIO to default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) hercules_init(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) dev_dbg(chip->card->dev, "initializing Hercules mixer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) if (chip->in_suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) for (idx = 0 ; idx < ARRAY_SIZE(snd_hercules_controls); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) struct snd_kcontrol *kctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) if ((err = snd_ctl_add(card, kctl)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) dev_err(card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) "failed to initialize Hercules mixer (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) * Untested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) static void amp_voyetra_4294(struct snd_cs46xx *chip, int change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) chip->amplifier += change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) if (chip->amplifier) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) /* Switch the GPIO pins 7 and 8 to open drain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) snd_cs46xx_codec_write(chip, 0x4C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) snd_cs46xx_codec_read(chip, 0x4C) & 0xFE7F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) snd_cs46xx_codec_write(chip, 0x4E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) snd_cs46xx_codec_read(chip, 0x4E) | 0x0180);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) /* Now wake the AMP (this might be backwards) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) snd_cs46xx_codec_write(chip, 0x54,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) snd_cs46xx_codec_read(chip, 0x54) & ~0x0180);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) snd_cs46xx_codec_write(chip, 0x54,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) snd_cs46xx_codec_read(chip, 0x54) | 0x0180);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) * Handle the CLKRUN on a thinkpad. We must disable CLKRUN support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) * whenever we need to beat on the chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) * The original idea and code for this hack comes from David Kaiser at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) * Linuxcare. Perhaps one day Crystal will document their chips well
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) * enough to make them useful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) static void clkrun_hack(struct snd_cs46xx *chip, int change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) u16 control, nval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) if (!chip->acpi_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) chip->amplifier += change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) /* Read ACPI port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) nval = control = inw(chip->acpi_port + 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) /* Flip CLKRUN off while running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) if (! chip->amplifier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) nval |= 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) nval &= ~0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) if (nval != control)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) outw(nval, chip->acpi_port + 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) * detect intel piix4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) static void clkrun_init(struct snd_cs46xx *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) u8 pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) chip->acpi_port = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) if (pdev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) return; /* Not a thinkpad thats for sure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) /* Find the control port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) pci_read_config_byte(pdev, 0x41, &pp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) chip->acpi_port = pp << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) pci_dev_put(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) * Card subid table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) struct cs_card_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) u16 vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) u16 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) void (*init)(struct snd_cs46xx *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) void (*amp)(struct snd_cs46xx *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) void (*active)(struct snd_cs46xx *, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) void (*mixer_init)(struct snd_cs46xx *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) static struct cs_card_type cards[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) .vendor = 0x1489,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) .id = 0x7001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) .name = "Genius Soundmaker 128 value",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) /* nothing special */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) .vendor = 0x5053,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) .id = 0x3357,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) .name = "Voyetra",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) .amp = amp_voyetra,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) .mixer_init = voyetra_mixer_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) .vendor = 0x1071,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) .id = 0x6003,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) .name = "Mitac MI6020/21",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) .amp = amp_voyetra,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) /* Hercules Game Theatre XP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) .vendor = 0x14af, /* Guillemot Corporation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) .id = 0x0050,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658) .name = "Hercules Game Theatre XP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) .amp = amp_hercules,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) .mixer_init = hercules_mixer_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) .vendor = 0x1681,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) .id = 0x0050,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) .name = "Hercules Game Theatre XP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) .amp = amp_hercules,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) .mixer_init = hercules_mixer_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) .vendor = 0x1681,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) .id = 0x0051,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) .name = "Hercules Game Theatre XP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) .amp = amp_hercules,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) .mixer_init = hercules_mixer_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) .vendor = 0x1681,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) .id = 0x0052,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) .name = "Hercules Game Theatre XP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) .amp = amp_hercules,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) .mixer_init = hercules_mixer_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) .vendor = 0x1681,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) .id = 0x0053,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) .name = "Hercules Game Theatre XP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) .amp = amp_hercules,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) .mixer_init = hercules_mixer_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) .vendor = 0x1681,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) .id = 0x0054,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) .name = "Hercules Game Theatre XP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) .amp = amp_hercules,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) .mixer_init = hercules_mixer_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) /* Herculess Fortissimo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) .vendor = 0x1681,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) .id = 0xa010,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) .name = "Hercules Gamesurround Fortissimo II",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) .vendor = 0x1681,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) .id = 0xa011,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) .name = "Hercules Gamesurround Fortissimo III 7.1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) /* Teratec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) .vendor = 0x153b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) .id = 0x112e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) .name = "Terratec DMX XFire 1024",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) .vendor = 0x153b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) .id = 0x1136,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) .name = "Terratec SiXPack 5.1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) /* Not sure if the 570 needs the clkrun hack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) .vendor = PCI_VENDOR_ID_IBM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) .id = 0x0132,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) .name = "Thinkpad 570",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) .init = clkrun_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) .active = clkrun_hack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) .vendor = PCI_VENDOR_ID_IBM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) .id = 0x0153,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) .name = "Thinkpad 600X/A20/T20",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) .init = clkrun_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) .active = clkrun_hack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) .vendor = PCI_VENDOR_ID_IBM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) .id = 0x1010,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) .name = "Thinkpad 600E (unsupported)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) {} /* terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) * APM support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) static const unsigned int saved_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) BA0_ACOSV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) /*BA0_ASER_FADDR,*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) BA0_ASER_MASTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) BA1_PVOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) BA1_CVOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) static int snd_cs46xx_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) struct snd_cs46xx *chip = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) int i, amp_saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) chip->in_suspend = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) // chip->ac97_powerdown = snd_cs46xx_codec_read(chip, AC97_POWER_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) // chip->ac97_general_purpose = snd_cs46xx_codec_read(chip, BA0_AC97_GENERAL_PURPOSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) /* save some registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) chip->saved_regs[i] = snd_cs46xx_peekBA0(chip, saved_regs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) amp_saved = chip->amplifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) /* turn off amp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) chip->amplifier_ctrl(chip, -chip->amplifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) snd_cs46xx_hw_stop(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) /* disable CLKRUN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) chip->active_ctrl(chip, -chip->amplifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) chip->amplifier = amp_saved; /* restore the status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) static int snd_cs46xx_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) struct snd_cs46xx *chip = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) int amp_saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) unsigned int tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) amp_saved = chip->amplifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) chip->amplifier = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) chip->active_ctrl(chip, 1); /* force to on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) snd_cs46xx_chip_init(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) snd_cs46xx_reset(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) cs46xx_dsp_resume(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) /* restore some registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) snd_cs46xx_pokeBA0(chip, saved_regs[i], chip->saved_regs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) snd_cs46xx_download_image(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) chip->ac97_general_purpose);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) snd_cs46xx_codec_write(chip, AC97_POWER_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) chip->ac97_powerdown);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) mdelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) snd_cs46xx_codec_write(chip, BA0_AC97_POWERDOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) chip->ac97_powerdown);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) * Stop capture DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) tmp = snd_cs46xx_peek(chip, BA1_CCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) chip->capt.ctl = tmp & 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) /* reset playback/capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) snd_cs46xx_set_play_sample_rate(chip, 8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) snd_cs46xx_set_capture_sample_rate(chip, 8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) snd_cs46xx_proc_start(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) cs46xx_enable_stream_irqs(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) if (amp_saved)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) chip->amplifier_ctrl(chip, 1); /* turn amp on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) chip->active_ctrl(chip, -1); /* disable CLKRUN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) chip->amplifier = amp_saved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) chip->in_suspend = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) snd_power_change_state(card, SNDRV_CTL_POWER_D0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) #endif /* CONFIG_PM_SLEEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) int snd_cs46xx_create(struct snd_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) int external_amp, int thinkpad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) struct snd_cs46xx **rchip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) struct snd_cs46xx *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) int err, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) struct snd_cs46xx_region *region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) struct cs_card_type *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) u16 ss_card, ss_vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) .dev_free = snd_cs46xx_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) *rchip = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) /* enable PCI device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) if ((err = pci_enable_device(pci)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) chip = kzalloc(sizeof(*chip), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) if (chip == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) spin_lock_init(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) mutex_init(&chip->spos_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) chip->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) chip->pci = pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) chip->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) chip->ba0_addr = pci_resource_start(pci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) chip->ba1_addr = pci_resource_start(pci, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) chip->ba0_addr, chip->ba1_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) snd_cs46xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) region = &chip->region.name.ba0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) strcpy(region->name, "CS46xx_BA0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) region->base = chip->ba0_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) region->size = CS46XX_BA0_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) region = &chip->region.name.data0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) strcpy(region->name, "CS46xx_BA1_data0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) region->base = chip->ba1_addr + BA1_SP_DMEM0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) region->size = CS46XX_BA1_DATA0_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) region = &chip->region.name.data1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) strcpy(region->name, "CS46xx_BA1_data1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) region->base = chip->ba1_addr + BA1_SP_DMEM1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) region->size = CS46XX_BA1_DATA1_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) region = &chip->region.name.pmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) strcpy(region->name, "CS46xx_BA1_pmem");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) region->base = chip->ba1_addr + BA1_SP_PMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) region->size = CS46XX_BA1_PRG_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) region = &chip->region.name.reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) strcpy(region->name, "CS46xx_BA1_reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) region->base = chip->ba1_addr + BA1_SP_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) region->size = CS46XX_BA1_REG_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) /* set up amp and clkrun hack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &ss_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) for (cp = &cards[0]; cp->name; cp++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930) if (cp->vendor == ss_vendor && cp->id == ss_card) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) dev_dbg(chip->card->dev, "hack for %s enabled\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) cp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) chip->amplifier_ctrl = cp->amp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) chip->active_ctrl = cp->active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) chip->mixer_init = cp->mixer_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) if (cp->init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) cp->init(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) if (external_amp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) dev_info(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) "Crystal EAPD support forced on.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) chip->amplifier_ctrl = amp_voyetra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) if (thinkpad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) dev_info(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) "Activating CLKRUN hack for Thinkpad.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) chip->active_ctrl = clkrun_hack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) clkrun_init(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) if (chip->amplifier_ctrl == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) chip->amplifier_ctrl = amp_none;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959) if (chip->active_ctrl == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) chip->active_ctrl = amp_none;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) chip->active_ctrl(chip, 1); /* enable CLKRUN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) for (idx = 0; idx < 5; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967) region = &chip->region.idx[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) if ((region->resource = request_mem_region(region->base, region->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) region->name)) == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) "unable to request memory region 0x%lx-0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) region->base, region->base + region->size - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) snd_cs46xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) region->remap_addr = ioremap(region->base, region->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) if (region->remap_addr == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) "%s ioremap problem\n", region->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980) snd_cs46xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) KBUILD_MODNAME, chip)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) dev_err(chip->card->dev, "unable to grab IRQ %d\n", pci->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) snd_cs46xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) chip->irq = pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) card->sync_irq = chip->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) #ifdef CONFIG_SND_CS46XX_NEW_DSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) if (chip->dsp_spos_instance == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) snd_cs46xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) err = snd_cs46xx_chip_init(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) snd_cs46xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) snd_cs46xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) snd_cs46xx_proc_init(card, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) chip->saved_regs = kmalloc_array(ARRAY_SIZE(saved_regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) sizeof(*chip->saved_regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) if (!chip->saved_regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) snd_cs46xx_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) chip->active_ctrl(chip, -1); /* disable CLKRUN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) *rchip = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) }