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)  *  Matt Wu <Matt_Wu@acersoftech.com.cn>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *  Apr 26, 2001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *  Routines for control of ALi pci audio M5451
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *  BUGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *    --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *  TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *    --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <sound/info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <sound/ac97_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <sound/mpu401.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) MODULE_AUTHOR("Matt Wu <Matt_Wu@acersoftech.com.cn>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) MODULE_DESCRIPTION("ALI M5451");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) MODULE_SUPPORTED_DEVICE("{{ALI,M5451,pci},{ALI,M5451}}");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) static int index = SNDRV_DEFAULT_IDX1;	/* Index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) static char *id = SNDRV_DEFAULT_STR1;	/* ID for this card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) static int pcm_channels = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) static bool spdif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) module_param(index, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) module_param(id, charp, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) MODULE_PARM_DESC(id, "ID string for ALI M5451 PCI Audio.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) module_param(pcm_channels, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) MODULE_PARM_DESC(pcm_channels, "PCM Channels");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) module_param(spdif, bool, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) /* just for backward compatibility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) static bool enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) module_param(enable, bool, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54)  *  Constants definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #define DEVICE_ID_ALI5451	((PCI_VENDOR_ID_AL<<16)|PCI_DEVICE_ID_AL_M5451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define ALI_CHANNELS		32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define ALI_PCM_IN_CHANNEL	31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define ALI_SPDIF_IN_CHANNEL	19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #define ALI_SPDIF_OUT_CHANNEL	15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #define ALI_CENTER_CHANNEL	24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #define ALI_LEF_CHANNEL		23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #define ALI_SURR_LEFT_CHANNEL	26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #define ALI_SURR_RIGHT_CHANNEL	25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #define ALI_MODEM_IN_CHANNEL    21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #define ALI_MODEM_OUT_CHANNEL   20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) #define	SNDRV_ALI_VOICE_TYPE_PCM	01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) #define SNDRV_ALI_VOICE_TYPE_OTH	02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) #define	ALI_5451_V02		0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78)  *  Direct Registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) #define ALI_LEGACY_DMAR0        0x00  /* ADR0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #define ALI_LEGACY_DMAR4        0x04  /* CNT0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) #define ALI_LEGACY_DMAR11       0x0b  /* MOD  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) #define ALI_LEGACY_DMAR15       0x0f  /* MMR  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #define ALI_MPUR0		0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) #define ALI_MPUR1		0x21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) #define ALI_MPUR2		0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) #define ALI_MPUR3		0x23
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) #define	ALI_AC97_WRITE		0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) #define ALI_AC97_READ		0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) #define ALI_SCTRL		0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) #define   ALI_SPDIF_OUT_ENABLE		0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) #define   ALI_SCTRL_LINE_IN2		(1 << 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) #define   ALI_SCTRL_GPIO_IN2		(1 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) #define   ALI_SCTRL_LINE_OUT_EN 	(1 << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) #define   ALI_SCTRL_GPIO_OUT_EN 	(1 << 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) #define   ALI_SCTRL_CODEC1_READY	(1 << 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) #define   ALI_SCTRL_CODEC2_READY	(1 << 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) #define ALI_AC97_GPIO		0x4c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) #define   ALI_AC97_GPIO_ENABLE		0x8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) #define   ALI_AC97_GPIO_DATA_SHIFT	16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) #define ALI_SPDIF_CS		0x70
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) #define ALI_SPDIF_CTRL		0x74
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) #define   ALI_SPDIF_IN_FUNC_ENABLE	0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) #define   ALI_SPDIF_IN_CH_STATUS	0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) #define   ALI_SPDIF_OUT_CH_STATUS	0xbf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) #define ALI_START		0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) #define ALI_STOP		0x84
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) #define ALI_CSPF		0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) #define ALI_AINT		0x98
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) #define ALI_GC_CIR		0xa0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 	#define ENDLP_IE		0x00001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 	#define MIDLP_IE		0x00002000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) #define ALI_AINTEN		0xa4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) #define ALI_VOLUME		0xa8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) #define ALI_SBDELTA_DELTA_R     0xac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) #define ALI_MISCINT		0xb0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	#define ADDRESS_IRQ		0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	#define TARGET_REACHED		0x00008000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	#define MIXER_OVERFLOW		0x00000800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	#define MIXER_UNDERFLOW		0x00000400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	#define GPIO_IRQ		0x01000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) #define ALI_SBBL_SBCL           0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) #define ALI_SBCTRL_SBE2R_SBDD   0xc4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) #define ALI_STIMER		0xc8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) #define ALI_GLOBAL_CONTROL	0xd4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) #define   ALI_SPDIF_OUT_SEL_PCM		0x00000400 /* bit 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) #define   ALI_SPDIF_IN_SUPPORT		0x00000800 /* bit 11 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) #define   ALI_SPDIF_OUT_CH_ENABLE	0x00008000 /* bit 15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) #define   ALI_SPDIF_IN_CH_ENABLE	0x00080000 /* bit 19 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) #define   ALI_PCM_IN_ENABLE		0x80000000 /* bit 31 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) #define ALI_CSO_ALPHA_FMS	0xe0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) #define ALI_LBA			0xe4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) #define ALI_ESO_DELTA		0xe8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) #define ALI_GVSEL_PAN_VOC_CTRL_EC	0xf0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) #define ALI_EBUF1		0xf4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) #define ALI_EBUF2		0xf8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) #define ALI_REG(codec, x) ((codec)->port + x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) #define MAX_CODECS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) struct snd_ali;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) struct snd_ali_voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) struct snd_ali_channel_control {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	/* register data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	struct REGDATA {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 		unsigned int start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 		unsigned int stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 		unsigned int aint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 		unsigned int ainten;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	} data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	/* register addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	struct REGS {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 		unsigned int start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 		unsigned int stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 		unsigned int aint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 		unsigned int ainten;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 		unsigned int ac97read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 		unsigned int ac97write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	} regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) struct snd_ali_voice {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	unsigned int number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	unsigned int use :1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 		pcm :1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 		midi :1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 		mode :1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 		synth :1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 		running :1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 	/* PCM data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 	struct snd_ali *codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	struct snd_pcm_substream *substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 	struct snd_ali_voice *extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	int eso;                /* final ESO value for channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	int count;              /* runtime->period_size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	/* --- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	void *private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	void (*private_free)(void *private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) struct snd_alidev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	struct snd_ali_voice voices[ALI_CHANNELS];	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	unsigned int	chcnt;			/* num of opened channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	unsigned int	chmap;			/* bitmap for opened channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	unsigned int synthcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) #define ALI_GLOBAL_REGS		56
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) #define ALI_CHANNEL_REGS	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) struct snd_ali_image {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	u32 regs[ALI_GLOBAL_REGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	u32 channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) struct snd_ali {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	int		irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	unsigned long	port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	unsigned char	revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	unsigned int hw_initialized :1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	unsigned int spdif_support :1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	struct pci_dev	*pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	struct pci_dev	*pci_m1533;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	struct pci_dev	*pci_m7101;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	struct snd_card	*card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	struct snd_pcm	*pcm[MAX_CODECS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	struct snd_alidev	synth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	struct snd_ali_channel_control chregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	/* S/PDIF Mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	unsigned int	spdif_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 	unsigned int spurious_irq_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	unsigned int spurious_irq_max_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	unsigned int num_of_codecs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	struct snd_ac97_bus *ac97_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	struct snd_ac97 *ac97[MAX_CODECS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	unsigned short	ac97_ext_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	unsigned short	ac97_ext_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	spinlock_t	reg_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	spinlock_t	voice_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	struct snd_ali_image *image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) static const struct pci_device_id snd_ali_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	{PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	{0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) MODULE_DEVICE_TABLE(pci, snd_ali_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) static void snd_ali_clear_voices(struct snd_ali *, unsigned int, unsigned int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) static unsigned short snd_ali_codec_peek(struct snd_ali *, int, unsigned short);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) static void snd_ali_codec_poke(struct snd_ali *, int, unsigned short,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 			       unsigned short);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264)  *  AC97 ACCESS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) static inline unsigned int snd_ali_5451_peek(struct snd_ali *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 					     unsigned int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	return (unsigned int)inl(ALI_REG(codec, port)); 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) static inline void snd_ali_5451_poke(struct snd_ali *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 				     unsigned int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 				     unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	outl((unsigned int)val, ALI_REG(codec, port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) static int snd_ali_codec_ready(struct snd_ali *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 			       unsigned int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	unsigned long end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	unsigned int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	end_time = jiffies + msecs_to_jiffies(250);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 		res = snd_ali_5451_peek(codec,port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 		if (!(res & 0x8000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 		if (!time_after_eq(end_time, jiffies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 		schedule_timeout_uninterruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	snd_ali_5451_poke(codec, port, res & ~0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	dev_dbg(codec->card->dev, "ali_codec_ready: codec is not ready.\n ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) static int snd_ali_stimer_ready(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	unsigned long end_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	unsigned long dwChk1,dwChk2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	end_time = jiffies + msecs_to_jiffies(250);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 		dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 		if (dwChk2 != dwChk1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 		if (!time_after_eq(end_time, jiffies))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 		schedule_timeout_uninterruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 	dev_err(codec->card->dev, "ali_stimer_read: stimer is not ready.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) static void snd_ali_codec_poke(struct snd_ali *codec,int secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 			       unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 			       unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	unsigned int dwVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	unsigned int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	if (reg >= 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 		dev_err(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 			"ali_codec_poke: reg(%xh) invalid.\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	port = codec->chregs.regs.ac97write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	if (snd_ali_codec_ready(codec, port) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	if (snd_ali_stimer_ready(codec) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	dwVal  = (unsigned int) (reg & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	dwVal |= 0x8000 | (val << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	if (secondary)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 		dwVal |= 0x0080;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	if (codec->revision == ALI_5451_V02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 		dwVal |= 0x0100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	snd_ali_5451_poke(codec, port, dwVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	return ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) static unsigned short snd_ali_codec_peek(struct snd_ali *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 					 int secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 					 unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	unsigned int dwVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 	unsigned int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	if (reg >= 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 		dev_err(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 			"ali_codec_peek: reg(%xh) invalid.\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 		return ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	port = codec->chregs.regs.ac97read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	if (snd_ali_codec_ready(codec, port) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 		return ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	if (snd_ali_stimer_ready(codec) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 		return ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 	dwVal  = (unsigned int) (reg & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	dwVal |= 0x8000;				/* bit 15*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	if (secondary)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 		dwVal |= 0x0080;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	snd_ali_5451_poke(codec, port, dwVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	if (snd_ali_stimer_ready(codec) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 		return ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	if (snd_ali_codec_ready(codec, port) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 		return ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	return (snd_ali_5451_peek(codec, port) & 0xffff0000) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) static void snd_ali_codec_write(struct snd_ac97 *ac97,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 				unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 				unsigned short val )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	struct snd_ali *codec = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	dev_dbg(codec->card->dev, "codec_write: reg=%xh data=%xh.\n", reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	if (reg == AC97_GPIO_STATUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 		outl((val << ALI_AC97_GPIO_DATA_SHIFT) | ALI_AC97_GPIO_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 		     ALI_REG(codec, ALI_AC97_GPIO));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	snd_ali_codec_poke(codec, ac97->num, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	return ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 					 unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	struct snd_ali *codec = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	dev_dbg(codec->card->dev, "codec_read reg=%xh.\n", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	return snd_ali_codec_peek(codec, ac97->num, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417)  *	AC97 Reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) static int snd_ali_reset_5451(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	struct pci_dev *pci_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	unsigned short wCount, wReg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	unsigned int   dwVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	pci_dev = codec->pci_m1533;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	if (pci_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 		pci_read_config_dword(pci_dev, 0x7c, &dwVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 		pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 		mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 		pci_read_config_dword(pci_dev, 0x7c, &dwVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 		pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 		mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	pci_dev = codec->pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	pci_read_config_dword(pci_dev, 0x44, &dwVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	pci_write_config_dword(pci_dev, 0x44, dwVal | 0x000c0000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	pci_read_config_dword(pci_dev, 0x44, &dwVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	wCount = 200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	while(wCount--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 		wReg = snd_ali_codec_peek(codec, 0, AC97_POWERDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		if ((wReg & 0x000f) == 0x000f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	/* non-fatal if you have a non PM capable codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	/* dev_warn(codec->card->dev, "ali5451: reset time out\n"); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458)  *  ALI 5451 Controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) static void snd_ali_enable_special_channel(struct snd_ali *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 					   unsigned int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	unsigned long dwVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	dwVal  = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	dwVal |= 1 << (channel & 0x0000001f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) static void snd_ali_disable_special_channel(struct snd_ali *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 					    unsigned int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 	unsigned long dwVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	dwVal  = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 	dwVal &= ~(1 << (channel & 0x0000001f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) static void snd_ali_enable_address_interrupt(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	unsigned int gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	gc  = inl(ALI_REG(codec, ALI_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	gc |= ENDLP_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	gc |= MIDLP_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	outl( gc, ALI_REG(codec, ALI_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) static void snd_ali_disable_address_interrupt(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	unsigned int gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	gc  = inl(ALI_REG(codec, ALI_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	gc &= ~ENDLP_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	gc &= ~MIDLP_IE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	outl(gc, ALI_REG(codec, ALI_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) static void snd_ali_disable_voice_irq(struct snd_ali *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 				      unsigned int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	struct snd_ali_channel_control *pchregs = &(codec->chregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	dev_dbg(codec->card->dev, "disable_voice_irq channel=%d\n", channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	mask = 1 << (channel & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	pchregs->data.ainten  = inl(ALI_REG(codec, pchregs->regs.ainten));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	pchregs->data.ainten &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	outl(pchregs->data.ainten, ALI_REG(codec, pchregs->regs.ainten));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) static int snd_ali_alloc_pcm_channel(struct snd_ali *codec, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	unsigned int idx =  channel & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	if (codec->synth.chcnt >= ALI_CHANNELS){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 		dev_err(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 			   "ali_alloc_pcm_channel: no free channels.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	if (!(codec->synth.chmap & (1 << idx))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 		codec->synth.chmap |= 1 << idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 		codec->synth.chcnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 		dev_dbg(codec->card->dev, "alloc_pcm_channel no. %d.\n", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 		return idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	return -1;
^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) static int snd_ali_find_free_channel(struct snd_ali * codec, int rec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	int result = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	dev_dbg(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 		"find_free_channel: for %s\n", rec ? "rec" : "pcm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	/* recording */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	if (rec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 		if (codec->spdif_support &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 		    (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		     ALI_SPDIF_IN_SUPPORT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 			idx = ALI_SPDIF_IN_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 			idx = ALI_PCM_IN_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 		result = snd_ali_alloc_pcm_channel(codec, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 		if (result >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 			return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 			dev_err(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 				"ali_find_free_channel: record channel is busy now.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	/* playback... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	if (codec->spdif_support &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	    (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	     ALI_SPDIF_OUT_CH_ENABLE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 		idx = ALI_SPDIF_OUT_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		result = snd_ali_alloc_pcm_channel(codec, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 		if (result >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 			return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 			dev_err(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 				"ali_find_free_channel: S/PDIF out channel is in busy now.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	for (idx = 0; idx < ALI_CHANNELS; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 		result = snd_ali_alloc_pcm_channel(codec, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 		if (result >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 			return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	dev_err(codec->card->dev, "ali_find_free_channel: no free channels.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	unsigned int idx = channel & 0x0000001f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	dev_dbg(codec->card->dev, "free_channel_pcm channel=%d\n", channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 	if (channel < 0 || channel >= ALI_CHANNELS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	if (!(codec->synth.chmap & (1 << idx))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 		dev_err(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 			"ali_free_channel_pcm: channel %d is not in use.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 			channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		codec->synth.chmap &= ~(1 << idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 		codec->synth.chcnt--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) static void snd_ali_stop_voice(struct snd_ali *codec, unsigned int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	unsigned int mask = 1 << (channel & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	dev_dbg(codec->card->dev, "stop_voice: channel=%d\n", channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	outl(mask, ALI_REG(codec, codec->chregs.regs.stop));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612)  *    S/PDIF Part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) static void snd_ali_delay(struct snd_ali *codec,int interval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	unsigned long  begintimer,currenttimer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	begintimer   = inl(ALI_REG(codec, ALI_STIMER));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	currenttimer = inl(ALI_REG(codec, ALI_STIMER));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	while (currenttimer < begintimer + interval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 		if (snd_ali_stimer_ready(codec) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 		currenttimer = inl(ALI_REG(codec,  ALI_STIMER));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) static void snd_ali_detect_spdif_rate(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	u16 wval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	u16 count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 	u8  bval, R1 = 0, R2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	bval  = inb(ALI_REG(codec, ALI_SPDIF_CTRL + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	bval |= 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	outb(bval, ALI_REG(codec, ALI_SPDIF_CTRL + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	while ((R1 < 0x0b || R1 > 0x0e) && R1 != 0x12 && count <= 50000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 		count ++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 		snd_ali_delay(codec, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 		bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 		R1 = bval & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	if (count > 50000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 		dev_err(codec->card->dev, "ali_detect_spdif_rate: timeout!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	for (count = 0; count <= 50000; count++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 		snd_ali_delay(codec, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 		R2 = bval & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 		if (R2 != R1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 			R1 = R2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	if (count > 50000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 		dev_err(codec->card->dev, "ali_detect_spdif_rate: timeout!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 	if (R2 >= 0x0b && R2 <= 0x0e) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 		wval  = inw(ALI_REG(codec, ALI_SPDIF_CTRL + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 		wval &= 0xe0f0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 		wval |= (0x09 << 8) | 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 		outw(wval, ALI_REG(codec, ALI_SPDIF_CTRL + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 		bval  = inb(ALI_REG(codec, ALI_SPDIF_CS + 3)) & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 		outb(bval | 0x02, ALI_REG(codec, ALI_SPDIF_CS + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	} else if (R2 == 0x12) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		wval  = inw(ALI_REG(codec, ALI_SPDIF_CTRL + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 		wval &= 0xe0f0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 		wval |= (0x0e << 8) | 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 		outw(wval, ALI_REG(codec, ALI_SPDIF_CTRL + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		bval  = inb(ALI_REG(codec,ALI_SPDIF_CS + 3)) & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 		outb(bval | 0x03, ALI_REG(codec, ALI_SPDIF_CS + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) static unsigned int snd_ali_get_spdif_in_rate(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	u32	dwRate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	u8	bval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	bval  = inb(ALI_REG(codec, ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 	bval &= 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	bval |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 	outb(bval, ALI_REG(codec, ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	snd_ali_detect_spdif_rate(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	bval  = inb(ALI_REG(codec, ALI_SPDIF_CS + 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	bval &= 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	switch (bval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	case 0: dwRate = 44100; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	case 1: dwRate = 48000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	case 2: dwRate = 32000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	default: dwRate = 0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	return dwRate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) static void snd_ali_enable_spdif_in(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) {	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	unsigned int dwVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	dwVal |= ALI_SPDIF_IN_SUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	dwVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	dwVal |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	outb(dwVal, ALI_REG(codec, ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	snd_ali_enable_special_channel(codec, ALI_SPDIF_IN_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) static void snd_ali_disable_spdif_in(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	unsigned int dwVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	dwVal &= ~ALI_SPDIF_IN_SUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	snd_ali_disable_special_channel(codec, ALI_SPDIF_IN_CHANNEL);	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) static void snd_ali_set_spdif_out_rate(struct snd_ali *codec, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	unsigned char  bVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	unsigned int  dwRate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	case 32000: dwRate = 0x300; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	case 48000: dwRate = 0x200; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	default: dwRate = 0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	bVal  = inb(ALI_REG(codec, ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	bVal &= (unsigned char)(~(1<<6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	bVal |= 0x80;		/* select right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	outb(bVal, ALI_REG(codec, ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 	outb(dwRate | 0x20, ALI_REG(codec, ALI_SPDIF_CS + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	bVal &= ~0x80;	/* select left */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	outb(bVal, ALI_REG(codec, ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	outw(rate | 0x10, ALI_REG(codec, ALI_SPDIF_CS + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) static void snd_ali_enable_spdif_out(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	unsigned short wVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	unsigned char bVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765)         struct pci_dev *pci_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767)         pci_dev = codec->pci_m1533;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768)         if (pci_dev == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769)                 return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770)         pci_read_config_byte(pci_dev, 0x61, &bVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771)         bVal |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772)         pci_write_config_byte(pci_dev, 0x61, bVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773)         pci_read_config_byte(pci_dev, 0x7d, &bVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774)         bVal |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775)         pci_write_config_byte(pci_dev, 0x7d, bVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777)         pci_read_config_byte(pci_dev, 0x7e, &bVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778)         bVal &= (~0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779)         bVal |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780)         pci_write_config_byte(pci_dev, 0x7e, bVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	bVal = inb(ALI_REG(codec, ALI_SCTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	outb(bVal | ALI_SPDIF_OUT_ENABLE, ALI_REG(codec, ALI_SCTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	bVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	outb(bVal & ALI_SPDIF_OUT_CH_STATUS, ALI_REG(codec, ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787)    
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	wVal |= ALI_SPDIF_OUT_SEL_PCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	snd_ali_disable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) static void snd_ali_enable_spdif_chnout(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	unsigned short wVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	wVal  = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799)    	wVal &= ~ALI_SPDIF_OUT_SEL_PCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800)    	outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	wVal = inw(ALI_REG(codec, ALI_SPDIF_CS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	if (flag & ALI_SPDIF_OUT_NON_PCM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804)    		wVal |= 0x0002;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	else	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		wVal &= (~0x0002);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807)    	outw(wVal, ALI_REG(codec, ALI_SPDIF_CS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	snd_ali_enable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) static void snd_ali_disable_spdif_chnout(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	unsigned short wVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816)   	wVal  = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817)    	wVal |= ALI_SPDIF_OUT_SEL_PCM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818)    	outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	snd_ali_enable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) static void snd_ali_disable_spdif_out(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	unsigned char  bVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	bVal = inb(ALI_REG(codec, ALI_SCTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	outb(bVal & ~ALI_SPDIF_OUT_ENABLE, ALI_REG(codec, ALI_SCTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	snd_ali_disable_spdif_chnout(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) static void snd_ali_update_ptr(struct snd_ali *codec, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	struct snd_ali_voice *pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	struct snd_ali_channel_control *pchregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	unsigned int old, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	pchregs = &(codec->chregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	/* check if interrupt occurred for channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 	old  = pchregs->data.aint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	mask = 1U << (channel & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	if (!(old & mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	pvoice = &codec->synth.voices[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	spin_lock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	if (pvoice->pcm && pvoice->substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		/* pcm interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		if (pvoice->running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 			dev_dbg(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 				"update_ptr: cso=%4.4x cspf=%d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 				inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 				(inl(ALI_REG(codec, ALI_CSPF)) & mask) == mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 			spin_unlock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 			snd_pcm_period_elapsed(pvoice->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 			spin_lock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 			snd_ali_stop_voice(codec, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 			snd_ali_disable_voice_irq(codec, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 		}	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	} else if (codec->synth.voices[channel].synth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 		/* synth interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	} else if (codec->synth.voices[channel].midi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 		/* midi interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		/* unknown interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		snd_ali_stop_voice(codec, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		snd_ali_disable_voice_irq(codec, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 	spin_unlock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	outl(mask,ALI_REG(codec,pchregs->regs.aint));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	pchregs->data.aint = old & (~mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) static irqreturn_t snd_ali_card_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	struct snd_ali 	*codec = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	unsigned int audio_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	struct snd_ali_channel_control *pchregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	if (codec == NULL || !codec->hw_initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	audio_int = inl(ALI_REG(codec, ALI_MISCINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	if (!audio_int)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	pchregs = &(codec->chregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	if (audio_int & ADDRESS_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 		/* get interrupt status for all channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 		pchregs->data.aint = inl(ALI_REG(codec, pchregs->regs.aint));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 		for (channel = 0; channel < ALI_CHANNELS; channel++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 			snd_ali_update_ptr(codec, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	outl((TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 		ALI_REG(codec, ALI_MISCINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 						 int type, int rec, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	struct snd_ali_voice *pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	dev_dbg(codec->card->dev, "alloc_voice: type=%d rec=%d\n", type, rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	spin_lock_irq(&codec->voice_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	if (type == SNDRV_ALI_VOICE_TYPE_PCM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 			snd_ali_find_free_channel(codec,rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 		if (idx < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 			dev_err(codec->card->dev, "ali_alloc_voice: err.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 			spin_unlock_irq(&codec->voice_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 			return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		pvoice = &(codec->synth.voices[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 		pvoice->codec = codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 		pvoice->use = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 		pvoice->pcm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 		pvoice->mode = rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 		spin_unlock_irq(&codec->voice_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		return pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	spin_unlock_irq(&codec->voice_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	return NULL;
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) static void snd_ali_free_voice(struct snd_ali * codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 			       struct snd_ali_voice *pvoice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	void (*private_free)(void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	void *private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	dev_dbg(codec->card->dev, "free_voice: channel=%d\n", pvoice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	if (!pvoice->use)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	snd_ali_clear_voices(codec, pvoice->number, pvoice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	spin_lock_irq(&codec->voice_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	private_free = pvoice->private_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	private_data = pvoice->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	pvoice->private_free = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	pvoice->private_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	if (pvoice->pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 		snd_ali_free_channel_pcm(codec, pvoice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	pvoice->use = pvoice->pcm = pvoice->synth = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	pvoice->substream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	spin_unlock_irq(&codec->voice_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	if (private_free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		private_free(private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) static void snd_ali_clear_voices(struct snd_ali *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 				 unsigned int v_min,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 				 unsigned int v_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	for (i = v_min; i <= v_max; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		snd_ali_stop_voice(codec, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		snd_ali_disable_voice_irq(codec, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) static void snd_ali_write_voice_regs(struct snd_ali *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 			 unsigned int Channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 			 unsigned int LBA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 			 unsigned int CSO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 			 unsigned int ESO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 			 unsigned int DELTA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 			 unsigned int ALPHA_FMS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 			 unsigned int GVSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 			 unsigned int PAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 			 unsigned int VOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 			 unsigned int CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 			 unsigned int EC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	unsigned int ctlcmds[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	outb((unsigned char)(Channel & 0x001f), ALI_REG(codec, ALI_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	ctlcmds[0] =  (CSO << 16) | (ALPHA_FMS & 0x0000ffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	ctlcmds[1] =  LBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	ctlcmds[2] =  (ESO << 16) | (DELTA & 0x0ffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	ctlcmds[3] =  (GVSEL << 31) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 		      ((PAN & 0x0000007f) << 24) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		      ((VOL & 0x000000ff) << 16) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		      ((CTRL & 0x0000000f) << 12) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 		      (EC & 0x00000fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	outb(Channel, ALI_REG(codec, ALI_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	outl(ctlcmds[0], ALI_REG(codec, ALI_CSO_ALPHA_FMS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	outl(ctlcmds[1], ALI_REG(codec, ALI_LBA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 	outl(ctlcmds[2], ALI_REG(codec, ALI_ESO_DELTA));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	outl(ctlcmds[3], ALI_REG(codec, ALI_GVSEL_PAN_VOC_CTRL_EC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	outl(0x30000000, ALI_REG(codec, ALI_EBUF1));	/* Still Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	outl(0x30000000, ALI_REG(codec, ALI_EBUF2));	/* Still Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) static unsigned int snd_ali_convert_rate(unsigned int rate, int rec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	unsigned int delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	if (rate < 4000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 		rate = 4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	if (rate > 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		rate = 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	if (rec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 		if (rate == 44100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 			delta = 0x116a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		else if (rate == 8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 			delta = 0x6000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 		else if (rate == 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 			delta = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 			delta = ((48000 << 12) / rate) & 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 		if (rate == 44100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 			delta = 0xeb3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 		else if (rate == 8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 			delta = 0x2ab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		else if (rate == 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 			delta = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 		else 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 			delta = (((rate << 12) + rate) / 48000) & 0x0000ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	return delta;
^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) static unsigned int snd_ali_control_mode(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	unsigned int CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	/* set ctrl mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	   CTRL default: 8-bit (unsigned) mono, loop mode enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	CTRL = 0x00000001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	if (snd_pcm_format_width(runtime->format) == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 		CTRL |= 0x00000008;	/* 16-bit data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	if (!snd_pcm_format_unsigned(runtime->format))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 		CTRL |= 0x00000002;	/* signed data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 	if (runtime->channels > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 		CTRL |= 0x00000004;	/* stereo data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	return CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)  *  PCM part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) static int snd_ali_trigger(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 			       int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 				    
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 	struct snd_pcm_substream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 	unsigned int what, whati;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 	struct snd_ali_voice *pvoice, *evoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	int do_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 	case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		do_start = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 		do_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	what = whati = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	snd_pcm_group_for_each_entry(s, substream) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 		if ((struct snd_ali *) snd_pcm_substream_chip(s) == codec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 			pvoice = s->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 			evoice = pvoice->extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 			what |= 1 << (pvoice->number & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 			if (evoice == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 				whati |= 1 << (pvoice->number & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 			else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 				whati |= 1 << (evoice->number & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 				what |= 1 << (evoice->number & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 			if (do_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 				pvoice->running = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 				if (evoice != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 					evoice->running = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 				pvoice->running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 				if (evoice != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 					evoice->running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 			snd_pcm_trigger_done(s, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	spin_lock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	if (!do_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 		outl(what, ALI_REG(codec, ALI_STOP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	val = inl(ALI_REG(codec, ALI_AINTEN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	if (do_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 		val |= whati;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 		val &= ~whati;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	outl(val, ALI_REG(codec, ALI_AINTEN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	if (do_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 		outl(what, ALI_REG(codec, ALI_START));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	dev_dbg(codec->card->dev, "trigger: what=%xh whati=%xh\n", what, whati);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	spin_unlock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) static int snd_ali_playback_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 				      struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	struct snd_ali_voice *pvoice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	struct snd_ali_voice *evoice = pvoice->extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	/* voice management */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	if (params_buffer_size(hw_params) / 2 !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	    params_period_size(hw_params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 		if (!evoice) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 			evoice = snd_ali_alloc_voice(codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 						     SNDRV_ALI_VOICE_TYPE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 						     0, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 			if (!evoice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 				return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 			pvoice->extra = evoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 			evoice->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 		if (evoice) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 			snd_ali_free_voice(codec, evoice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 			pvoice->extra = evoice = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	struct snd_ali_voice *pvoice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	struct snd_ali_voice *evoice = pvoice ? pvoice->extra : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	if (evoice) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 		snd_ali_free_voice(codec, evoice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		pvoice->extra = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) static int snd_ali_playback_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	struct snd_ali_voice *pvoice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	struct snd_ali_voice *evoice = pvoice->extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	unsigned int LBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	unsigned int Delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	unsigned int ESO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 	unsigned int CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	unsigned int GVSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	unsigned int PAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 	unsigned int VOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	unsigned int EC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	dev_dbg(codec->card->dev, "playback_prepare ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	spin_lock_irq(&codec->reg_lock);	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	/* set Delta (rate) value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	Delta = snd_ali_convert_rate(runtime->rate, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	if (pvoice->number == ALI_SPDIF_IN_CHANNEL || 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 	    pvoice->number == ALI_PCM_IN_CHANNEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 		snd_ali_disable_special_channel(codec, pvoice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 	else if (codec->spdif_support &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 		 (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 		  ALI_SPDIF_OUT_CH_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 		 && pvoice->number == ALI_SPDIF_OUT_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 		snd_ali_set_spdif_out_rate(codec, runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 		Delta = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	/* set Loop Back Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	LBA = runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	/* set interrupt count size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 	pvoice->count = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 	/* set target ESO for channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	pvoice->eso = runtime->buffer_size; 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	dev_dbg(codec->card->dev, "playback_prepare: eso=%xh count=%xh\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 		       pvoice->eso, pvoice->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	/* set ESO to capture first MIDLP interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	ESO = pvoice->eso -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	/* set ctrl mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	CTRL = snd_ali_control_mode(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	GVSEL = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	PAN = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	VOL = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	dev_dbg(codec->card->dev, "playback_prepare:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 	dev_dbg(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 		"ch=%d, Rate=%d Delta=%xh,GVSEL=%xh,PAN=%xh,CTRL=%xh\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 		       pvoice->number,runtime->rate,Delta,GVSEL,PAN,CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	snd_ali_write_voice_regs(codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 				 pvoice->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 				 LBA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 				 0,	/* cso */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 				 ESO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 				 Delta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 				 0,	/* alpha */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 				 GVSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 				 PAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 				 VOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 				 CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 				 EC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 	if (evoice) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 		evoice->count = pvoice->count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 		evoice->eso = pvoice->count << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 		ESO = evoice->eso - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 		snd_ali_write_voice_regs(codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 					 evoice->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 					 LBA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 					 0,	/* cso */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 					 ESO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 					 Delta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 					 0,	/* alpha */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 					 GVSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 					 0x7f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 					 0x3ff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 					 CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 					 EC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 	spin_unlock_irq(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) static int snd_ali_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	struct snd_ali_voice *pvoice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 	unsigned int LBA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	unsigned int Delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	unsigned int ESO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	unsigned int CTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 	unsigned int GVSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	unsigned int PAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 	unsigned int VOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 	unsigned int EC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 	u8	 bValue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 	spin_lock_irq(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 	dev_dbg(codec->card->dev, "ali_prepare...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 	snd_ali_enable_special_channel(codec,pvoice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	Delta = (pvoice->number == ALI_MODEM_IN_CHANNEL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 		 pvoice->number == ALI_MODEM_OUT_CHANNEL) ? 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 		0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 	/* Prepare capture intr channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	if (pvoice->number == ALI_SPDIF_IN_CHANNEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 		unsigned int rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 		spin_unlock_irq(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 		if (codec->revision != ALI_5451_V02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) 		rate = snd_ali_get_spdif_in_rate(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 		if (rate == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 			dev_warn(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 				 "ali_capture_prepare: spdif rate detect err!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 			rate = 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 		spin_lock_irq(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 		bValue = inb(ALI_REG(codec,ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 		if (bValue & 0x10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 			outb(bValue,ALI_REG(codec,ALI_SPDIF_CTRL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 			dev_warn(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 				 "clear SPDIF parity error flag.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 		if (rate != 48000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 			Delta = ((rate << 12) / runtime->rate) & 0x00ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	/* set target ESO for channel  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 	pvoice->eso = runtime->buffer_size; 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	/* set interrupt count size  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 	pvoice->count = runtime->period_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 	/* set Loop Back Address  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 	LBA = runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	/* set ESO to capture first MIDLP interrupt  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 	ESO = pvoice->eso - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	CTRL = snd_ali_control_mode(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 	GVSEL = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 	PAN = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 	VOL = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 	EC = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 	snd_ali_write_voice_regs(    codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 				     pvoice->number,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 				     LBA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 				     0,	/* cso */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 				     ESO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 				     Delta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 				     0,	/* alpha */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 				     GVSEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 				     PAN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 				     VOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 				     CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 				     EC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 	spin_unlock_irq(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) static snd_pcm_uframes_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) snd_ali_playback_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	struct snd_ali_voice *pvoice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 	unsigned int cso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 	spin_lock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 	if (!pvoice->running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 		spin_unlock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 	outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 	cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 	spin_unlock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 	dev_dbg(codec->card->dev, "playback pointer returned cso=%xh.\n", cso);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 	cso %= runtime->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 	return cso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) 	struct snd_ali_voice *pvoice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	unsigned int cso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 	spin_lock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 	if (!pvoice->running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 		spin_unlock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 	outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 	cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 	spin_unlock(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 	cso %= runtime->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 	return cso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) static const struct snd_pcm_hardware snd_ali_playback =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) 	.info =		(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 			 SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 			 SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 			 SNDRV_PCM_INFO_RESUME |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 			 SNDRV_PCM_INFO_SYNC_START),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 	.formats =	(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 			 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 	.rates =	SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 	.rate_min =		4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 	.rate_max =		48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 	.channels_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 	.channels_max =		2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 	.buffer_bytes_max =	(256*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 	.period_bytes_min =	64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 	.period_bytes_max =	(256*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 	.periods_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 	.periods_max =		1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 	.fifo_size =		0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)  *  Capture support device description
^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_ali_capture =
^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 | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 			 SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 			 SNDRV_PCM_INFO_MMAP_VALID |
^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_START),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 	.formats =	(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 			 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 	.rates =	SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 	.rate_min =		4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 	.rate_max =		48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 	.channels_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 	.channels_max =		2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 	.buffer_bytes_max =	(128*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 	.period_bytes_min =	64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 	.period_bytes_max =	(128*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 	.periods_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 	.periods_max =		1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 	.fifo_size =		0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) static void snd_ali_pcm_free_substream(struct snd_pcm_runtime *runtime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 	struct snd_ali_voice *pvoice = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 	if (pvoice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 		snd_ali_free_voice(pvoice->codec, pvoice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) static int snd_ali_open(struct snd_pcm_substream *substream, int rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 			int channel, const struct snd_pcm_hardware *phw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 	struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	struct snd_ali_voice *pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 	pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 				     channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 	if (!pvoice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 	pvoice->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 	runtime->private_data = pvoice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 	runtime->private_free = snd_ali_pcm_free_substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 	runtime->hw = *phw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 	snd_pcm_set_sync(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 				     0, 64*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) static int snd_ali_playback_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 	return snd_ali_open(substream, 0, -1, &snd_ali_playback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) static int snd_ali_capture_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 	return snd_ali_open(substream, 1, -1, &snd_ali_capture);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) static int snd_ali_playback_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) static int snd_ali_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 	struct snd_ali_voice *pvoice = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 	snd_ali_disable_special_channel(codec,pvoice->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) static const struct snd_pcm_ops snd_ali_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 	.open =		snd_ali_playback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 	.close =	snd_ali_playback_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 	.hw_params =	snd_ali_playback_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 	.hw_free =	snd_ali_playback_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 	.prepare =	snd_ali_playback_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 	.trigger =	snd_ali_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 	.pointer =	snd_ali_playback_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) static const struct snd_pcm_ops snd_ali_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 	.open =		snd_ali_capture_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 	.close =	snd_ali_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 	.prepare =	snd_ali_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 	.trigger =	snd_ali_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 	.pointer =	snd_ali_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)  * Modem PCM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) static int snd_ali_modem_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 				 struct snd_pcm_hw_params *hw_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 	struct snd_ali *chip = snd_pcm_substream_chip(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 	unsigned int modem_num = chip->num_of_codecs - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 	snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 		       params_rate(hw_params));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 	snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) static const struct snd_pcm_hardware snd_ali_modem =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 	.info =		(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 			 SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) 			 SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) 			 SNDRV_PCM_INFO_RESUME |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) 			 SNDRV_PCM_INFO_SYNC_START),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) 	.formats =	SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) 	.rates =	(SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) 			 SNDRV_PCM_RATE_16000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) 	.rate_min =		8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) 	.rate_max =		16000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 	.channels_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 	.channels_max =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 	.buffer_bytes_max =	(256*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 	.period_bytes_min =	64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 	.period_bytes_max =	(256*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 	.periods_min =		1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 	.periods_max =		1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 	.fifo_size =		0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 			      int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 	static const unsigned int rates[] = {8000, 9600, 12000, 16000};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) 	static const struct snd_pcm_hw_constraint_list hw_constraint_rates = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 		.count = ARRAY_SIZE(rates),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) 		.list = rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) 		.mask = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) 	int err = snd_ali_open(substream, rec, channel, &snd_ali_modem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) 	return snd_pcm_hw_constraint_list(substream->runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) 			SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) static int snd_ali_modem_playback_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 	return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) static int snd_ali_modem_capture_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) 	return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) static const struct snd_pcm_ops snd_ali_modem_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) 	.open =		snd_ali_modem_playback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) 	.close =	snd_ali_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 	.hw_params =	snd_ali_modem_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) 	.prepare =	snd_ali_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) 	.trigger =	snd_ali_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) 	.pointer =	snd_ali_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) static const struct snd_pcm_ops snd_ali_modem_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) 	.open =		snd_ali_modem_capture_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 	.close =	snd_ali_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 	.hw_params =	snd_ali_modem_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 	.prepare =	snd_ali_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 	.trigger =	snd_ali_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 	.pointer =	snd_ali_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) struct ali_pcm_description {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 	char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) 	unsigned int playback_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 	unsigned int capture_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 	const struct snd_pcm_ops *playback_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 	const struct snd_pcm_ops *capture_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 	unsigned short class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) static void snd_ali_pcm_free(struct snd_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) 	struct snd_ali *codec = pcm->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 	codec->pcm[pcm->device] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) static int snd_ali_pcm(struct snd_ali *codec, int device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) 		       struct ali_pcm_description *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) 	struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) 	err = snd_pcm_new(codec->card, desc->name, device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) 			  desc->playback_num, desc->capture_num, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) 		dev_err(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 			"snd_ali_pcm: err called snd_pcm_new.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 	pcm->private_data = codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 	pcm->private_free = snd_ali_pcm_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 	if (desc->playback_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 				desc->playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) 	if (desc->capture_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) 				desc->capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) 	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 				       &codec->pci->dev, 64*1024, 128*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 	pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) 	pcm->dev_class = desc->class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) 	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) 	strcpy(pcm->name, desc->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 	codec->pcm[0] = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) static struct ali_pcm_description ali_pcms[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 	{ .name = "ALI 5451",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) 	  .playback_num = ALI_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 	  .capture_num = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) 	  .playback_ops = &snd_ali_playback_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 	  .capture_ops = &snd_ali_capture_ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 	{ .name = "ALI 5451 modem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 	  .playback_num = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) 	  .capture_num = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 	  .playback_ops = &snd_ali_modem_playback_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 	  .capture_ops = &snd_ali_modem_capture_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 	  .class = SNDRV_PCM_CLASS_MODEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) static int snd_ali_build_pcms(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 	int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 	for (i = 0; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 		err = snd_ali_pcm(codec, i, &ali_pcms[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 			return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) #define ALI5451_SPDIF(xname, xindex, value) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) .put = snd_ali5451_spdif_put, .private_value = value}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) #define snd_ali5451_spdif_info		snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) 				 struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) 	struct snd_ali *codec = kcontrol->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) 	unsigned int spdif_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 	spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 	spin_lock_irq(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 	switch (kcontrol->private_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) 		spdif_enable = (codec->spdif_mask & 0x02) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) 		spdif_enable = ((codec->spdif_mask & 0x02) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) 			  (codec->spdif_mask & 0x04)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) 		spdif_enable = (codec->spdif_mask & 0x01) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 	ucontrol->value.integer.value[0] = spdif_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) 	spin_unlock_irq(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) 				 struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) 	struct snd_ali *codec = kcontrol->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) 	unsigned int change = 0, spdif_enable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) 	spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) 	spin_lock_irq(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 	switch (kcontrol->private_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) 		change = (codec->spdif_mask & 0x02) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 		change = change ^ spdif_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 		if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) 			if (spdif_enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 				codec->spdif_mask |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 				snd_ali_enable_spdif_out(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 				codec->spdif_mask &= ~(0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 				codec->spdif_mask &= ~(0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 				snd_ali_disable_spdif_out(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) 	case 1: 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 		change = (codec->spdif_mask & 0x04) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) 		change = change ^ spdif_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) 		if (change && (codec->spdif_mask & 0x02)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) 			if (spdif_enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) 				codec->spdif_mask |= 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) 				snd_ali_enable_spdif_chnout(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) 				codec->spdif_mask &= ~(0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) 				snd_ali_disable_spdif_chnout(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) 		change = (codec->spdif_mask & 0x01) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) 		change = change ^ spdif_enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) 		if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 			if (spdif_enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 				codec->spdif_mask |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) 				snd_ali_enable_spdif_in(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 				codec->spdif_mask &= ~(0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 				snd_ali_disable_spdif_in(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 	spin_unlock_irq(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) static const struct snd_kcontrol_new snd_ali5451_mixer_spdif[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) 	/* spdif aplayback switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 	/* FIXME: "IEC958 Playback Switch" may conflict with one on ac97_codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) 	ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), 0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) 	/* spdif out to spdif channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) 	ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Channel Output ",NONE,SWITCH), 0, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 	/* spdif in from spdif channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) 	ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) static int snd_ali_mixer(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 	struct snd_ac97_template ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 	unsigned int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) 	int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 	static const struct snd_ac97_bus_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) 		.write = snd_ali_codec_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) 		.read = snd_ali_codec_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) 	err = snd_ac97_bus(codec->card, 0, &ops, codec, &codec->ac97_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 	memset(&ac97, 0, sizeof(ac97));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) 	ac97.private_data = codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 	for (i = 0; i < codec->num_of_codecs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) 		ac97.num = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) 		err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) 		if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) 			dev_err(codec->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) 				   "ali mixer %d creating error.\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) 			if (i == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) 				return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) 			codec->num_of_codecs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) 	if (codec->spdif_support) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 		for (idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) 			err = snd_ctl_add(codec->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 					  snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 			if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) 				return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) static int ali_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) 	struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) 	struct snd_ali *chip = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) 	struct snd_ali_image *im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) 	im = chip->image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) 	if (!im)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) 	for (i = 0; i < chip->num_of_codecs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) 		snd_ac97_suspend(chip->ac97[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) 	spin_lock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) 	im->regs[ALI_MISCINT >> 2] = inl(ALI_REG(chip, ALI_MISCINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) 	/* im->regs[ALI_START >> 2] = inl(ALI_REG(chip, ALI_START)); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) 	im->regs[ALI_STOP >> 2] = inl(ALI_REG(chip, ALI_STOP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) 	/* disable all IRQ bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) 	outl(0, ALI_REG(chip, ALI_MISCINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) 	for (i = 0; i < ALI_GLOBAL_REGS; i++) {	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) 		if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) 		im->regs[i] = inl(ALI_REG(chip, i*4));
^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) 	for (i = 0; i < ALI_CHANNELS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) 		outb(i, ALI_REG(chip, ALI_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) 		for (j = 0; j < ALI_CHANNEL_REGS; j++) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) 			im->channel_regs[i][j] = inl(ALI_REG(chip, j*4 + 0xe0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) 	/* stop all HW channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) 	outl(0xffffffff, ALI_REG(chip, ALI_STOP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) 	spin_unlock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) static int ali_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) 	struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) 	struct snd_ali *chip = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) 	struct snd_ali_image *im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) 	im = chip->image;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) 	if (!im)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) 	spin_lock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) 	for (i = 0; i < ALI_CHANNELS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) 		outb(i, ALI_REG(chip, ALI_GC_CIR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) 		for (j = 0; j < ALI_CHANNEL_REGS; j++) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) 			outl(im->channel_regs[i][j], ALI_REG(chip, j*4 + 0xe0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) 	for (i = 0; i < ALI_GLOBAL_REGS; i++) {	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) 		if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) 		    (i*4 == ALI_START))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) 		outl(im->regs[i], ALI_REG(chip, i*4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) 	/* start HW channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) 	outl(im->regs[ALI_START >> 2], ALI_REG(chip, ALI_START));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) 	/* restore IRQ enable bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) 	outl(im->regs[ALI_MISCINT >> 2], ALI_REG(chip, ALI_MISCINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) 	spin_unlock_irq(&chip->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) 	for (i = 0 ; i < chip->num_of_codecs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) 		snd_ac97_resume(chip->ac97[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) static SIMPLE_DEV_PM_OPS(ali_pm, ali_suspend, ali_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) #define ALI_PM_OPS	&ali_pm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) #define ALI_PM_OPS	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) #endif /* CONFIG_PM_SLEEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) static int snd_ali_free(struct snd_ali * codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) 	if (codec->hw_initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) 		snd_ali_disable_address_interrupt(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) 	if (codec->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) 		free_irq(codec->irq, codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) 	if (codec->port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) 		pci_release_regions(codec->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) 	pci_disable_device(codec->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) 	kfree(codec->image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) 	pci_dev_put(codec->pci_m1533);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) 	pci_dev_put(codec->pci_m7101);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) 	kfree(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) static int snd_ali_chip_init(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) 	unsigned int legacy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) 	unsigned char temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) 	struct pci_dev *pci_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) 	dev_dbg(codec->card->dev, "chip initializing ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) 	if (snd_ali_reset_5451(codec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) 		dev_err(codec->card->dev, "ali_chip_init: reset 5451 error.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) 	if (codec->revision == ALI_5451_V02) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)         	pci_dev = codec->pci_m1533;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) 		pci_read_config_byte(pci_dev, 0x59, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) 		temp |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) 		pci_write_config_byte(pci_dev, 0x59, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) 		pci_dev = codec->pci_m7101;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) 		pci_read_config_byte(pci_dev, 0xb8, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) 		temp |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) 		pci_write_config_byte(pci_dev, 0xB8, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) 	pci_read_config_dword(codec->pci, 0x44, &legacy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) 	legacy &= 0xff00ff00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) 	legacy |= 0x000800aa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) 	pci_write_config_dword(codec->pci, 0x44, legacy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) 	outl(0x80000001, ALI_REG(codec, ALI_GLOBAL_CONTROL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) 	outl(0x00000000, ALI_REG(codec, ALI_AINTEN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) 	outl(0xffffffff, ALI_REG(codec, ALI_AINT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) 	outl(0x00000000, ALI_REG(codec, ALI_VOLUME));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) 	outb(0x10, 	 ALI_REG(codec, ALI_MPUR2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) 	codec->ac97_ext_id = snd_ali_codec_peek(codec, 0, AC97_EXTENDED_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) 	codec->ac97_ext_status = snd_ali_codec_peek(codec, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) 						    AC97_EXTENDED_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) 	if (codec->spdif_support) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) 		snd_ali_enable_spdif_out(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) 		codec->spdif_mask = 0x00000002;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) 	codec->num_of_codecs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) 	/* secondary codec - modem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) 	if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) 		codec->num_of_codecs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) 		outl(inl(ALI_REG(codec, ALI_SCTRL)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) 		     (ALI_SCTRL_LINE_IN2 | ALI_SCTRL_GPIO_IN2 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) 		      ALI_SCTRL_LINE_OUT_EN),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) 		     ALI_REG(codec, ALI_SCTRL));
^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) 	dev_dbg(codec->card->dev, "chip initialize succeed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) /* proc for register dump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) static void snd_ali_proc_read(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) 			      struct snd_info_buffer *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) 	struct snd_ali *codec = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) 	for (i = 0; i < 256 ; i+= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) 		snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) static void snd_ali_proc_init(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) 	snd_card_ro_proc_new(codec->card, "ali5451", codec, snd_ali_proc_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) static int snd_ali_resources(struct snd_ali *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) 	dev_dbg(codec->card->dev, "resources allocation ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) 	err = pci_request_regions(codec->pci, "ALI 5451");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) 	codec->port = pci_resource_start(codec->pci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) 	if (request_irq(codec->pci->irq, snd_ali_card_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) 			IRQF_SHARED, KBUILD_MODNAME, codec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) 		dev_err(codec->card->dev, "Unable to request irq.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) 	codec->irq = codec->pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) 	codec->card->sync_irq = codec->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) 	dev_dbg(codec->card->dev, "resources allocated.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) static int snd_ali_dev_free(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) 	struct snd_ali *codec = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) 	snd_ali_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) static int snd_ali_create(struct snd_card *card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) 			  struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) 			  int pcm_streams,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) 			  int spdif_support,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) 			  struct snd_ali **r_ali)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) 	struct snd_ali *codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) 	int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) 	unsigned short cmdw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) 	static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) 		.dev_free = snd_ali_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049)         };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) 	*r_ali = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) 	dev_dbg(card->dev, "creating ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) 	/* enable PCI device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) 	err = pci_enable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) 	/* check, if we can restrict PCI DMA transfers to 31 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) 	if (dma_set_mask(&pci->dev, DMA_BIT_MASK(31)) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) 	    dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(31)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) 		dev_err(card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) 			"architecture does not support 31bit PCI busmaster DMA\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) 		pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) 	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) 	if (!codec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) 		pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) 		return -ENOMEM;
^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) 	spin_lock_init(&codec->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) 	spin_lock_init(&codec->voice_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) 	codec->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) 	codec->pci = pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) 	codec->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) 	codec->revision = pci->revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) 	codec->spdif_support = spdif_support;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) 	if (pcm_streams < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) 		pcm_streams = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) 	if (pcm_streams > 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) 		pcm_streams = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) 	pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) 	pci_read_config_word(pci, PCI_COMMAND, &cmdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) 	if ((cmdw & PCI_COMMAND_IO) != PCI_COMMAND_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) 		cmdw |= PCI_COMMAND_IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) 		pci_write_config_word(pci, PCI_COMMAND, cmdw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) 	pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) 	if (snd_ali_resources(codec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) 		snd_ali_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) 	codec->synth.chmap = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) 	codec->synth.chcnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) 	codec->spdif_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) 	codec->synth.synthcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) 	if (codec->revision == ALI_5451_V02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) 		codec->chregs.regs.ac97read = ALI_AC97_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) 		codec->chregs.regs.ac97read = ALI_AC97_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) 	codec->chregs.regs.ac97write = ALI_AC97_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) 	codec->chregs.regs.start  = ALI_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) 	codec->chregs.regs.stop   = ALI_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) 	codec->chregs.regs.aint   = ALI_AINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) 	codec->chregs.regs.ainten = ALI_AINTEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) 	codec->chregs.data.start  = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) 	codec->chregs.data.stop   = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) 	codec->chregs.data.aint   = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) 	codec->chregs.data.ainten = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) 	/* M1533: southbridge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) 	codec->pci_m1533 = pci_get_device(0x10b9, 0x1533, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) 	if (!codec->pci_m1533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) 		dev_err(card->dev, "cannot find ALi 1533 chip.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) 		snd_ali_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) 	/* M7101: power management */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) 	codec->pci_m7101 = pci_get_device(0x10b9, 0x7101, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) 	if (!codec->pci_m7101 && codec->revision == ALI_5451_V02) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) 		dev_err(card->dev, "cannot find ALi 7101 chip.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) 		snd_ali_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) 	dev_dbg(card->dev, "snd_device_new is called.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) 	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) 		snd_ali_free(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) 	/* initialise synth voices*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) 	for (i = 0; i < ALI_CHANNELS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) 		codec->synth.voices[i].number = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) 	err = snd_ali_chip_init(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) 		dev_err(card->dev, "ali create: chip init error.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) 	codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) 	if (!codec->image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) 		dev_warn(card->dev, "can't allocate apm buffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) 	snd_ali_enable_address_interrupt(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) 	codec->hw_initialized = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) 	*r_ali = codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) 	dev_dbg(card->dev, "created.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) static int snd_ali_probe(struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) 			 const struct pci_device_id *pci_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) 	struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) 	struct snd_ali *codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) 	dev_dbg(&pci->dev, "probe ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) 	err = snd_card_new(&pci->dev, index, id, THIS_MODULE, 0, &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) 	err = snd_ali_create(card, pci, pcm_channels, spdif, &codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) 	card->private_data = codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) 	dev_dbg(&pci->dev, "mixer building ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) 	err = snd_ali_mixer(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) 	dev_dbg(&pci->dev, "pcm building ...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) 	err = snd_ali_build_pcms(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) 	snd_ali_proc_init(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) 	strcpy(card->driver, "ALI5451");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) 	strcpy(card->shortname, "ALI 5451");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) 	sprintf(card->longname, "%s at 0x%lx, irq %i",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) 		card->shortname, codec->port, codec->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) 	dev_dbg(&pci->dev, "register card.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) 	err = snd_card_register(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) 	pci_set_drvdata(pci, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212)  error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) 	snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) static void snd_ali_remove(struct pci_dev *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) 	snd_card_free(pci_get_drvdata(pci));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) static struct pci_driver ali5451_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) 	.name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) 	.id_table = snd_ali_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) 	.probe = snd_ali_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) 	.remove = snd_ali_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) 		.pm = ALI_PM_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) };                                
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) module_pci_driver(ali5451_driver);