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