Orange Pi5 kernel

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

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *                   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) }