X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=sound%2Fpci%2Fcmipci.c;h=1ded64e056433e22f8e96d8b0fbeb6dbf2c557d4;hb=f68596c6d8711650722b2a54328a088a2c21bc5b;hp=b098b51099c2ddbccac84f9ebf2ebae629837b90;hpb=67ed4161f60d76b3b27efc085b36357a6a90768c;p=safe%2Fjmp%2Flinux-2.6 diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index b098b51..1ded64e 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -20,7 +20,6 @@ /* Does not work. Warning may block system in capture mode */ /* #define USE_VAR48KRATE */ -#include #include #include #include @@ -29,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +56,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ static long mpu_port[SNDRV_CARDS]; -static long fm_port[SNDRV_CARDS]; +static long fm_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1}; static int soft_ac3[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1}; #ifdef SUPPORT_JOYSTICK static int joystick_port[SNDRV_CARDS]; @@ -79,13 +79,6 @@ module_param_array(joystick_port, int, NULL, 0444); MODULE_PARM_DESC(joystick_port, "Joystick port address."); #endif -#ifndef PCI_DEVICE_ID_CMEDIA_CM8738 -#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111 -#endif -#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B -#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112 -#endif - /* * CM8x38 registers definition */ @@ -101,30 +94,34 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); #define CM_CHADC0 0x00000001 /* ch0, 0:playback, 1:record */ #define CM_REG_FUNCTRL1 0x04 -#define CM_ASFC_MASK 0x0000E000 /* ADC sampling frequency */ -#define CM_ASFC_SHIFT 13 -#define CM_DSFC_MASK 0x00001C00 /* DAC sampling frequency */ -#define CM_DSFC_SHIFT 10 +#define CM_DSFC_MASK 0x0000E000 /* channel 1 (DAC?) sampling frequency */ +#define CM_DSFC_SHIFT 13 +#define CM_ASFC_MASK 0x00001C00 /* channel 0 (ADC?) sampling frequency */ +#define CM_ASFC_SHIFT 10 #define CM_SPDF_1 0x00000200 /* SPDIF IN/OUT at channel B */ #define CM_SPDF_0 0x00000100 /* SPDIF OUT only channel A */ -#define CM_SPDFLOOP 0x00000080 /* ext. SPDIIF/OUT -> IN loopback */ +#define CM_SPDFLOOP 0x00000080 /* ext. SPDIIF/IN -> OUT loopback */ #define CM_SPDO2DAC 0x00000040 /* SPDIF/OUT can be heard from internal DAC */ #define CM_INTRM 0x00000020 /* master control block (MCB) interrupt enabled */ #define CM_BREQ 0x00000010 /* bus master enabled */ #define CM_VOICE_EN 0x00000008 /* legacy voice (SB16,FM) */ -#define CM_UART_EN 0x00000004 /* UART */ -#define CM_JYSTK_EN 0x00000002 /* joy stick */ +#define CM_UART_EN 0x00000004 /* legacy UART */ +#define CM_JYSTK_EN 0x00000002 /* legacy joystick */ +#define CM_ZVPORT 0x00000001 /* ZVPORT */ #define CM_REG_CHFORMAT 0x08 #define CM_CHB3D5C 0x80000000 /* 5,6 channels */ +#define CM_FMOFFSET2 0x40000000 /* initial FM PCM offset 2 when Fmute=1 */ #define CM_CHB3D 0x20000000 /* 4 channels */ #define CM_CHIP_MASK1 0x1f000000 #define CM_CHIP_037 0x01000000 - -#define CM_SPDIF_SELECT1 0x00080000 /* for model <= 037 ? */ +#define CM_SETLAT48 0x00800000 /* set latency timer 48h */ +#define CM_EDGEIRQ 0x00400000 /* emulated edge trigger legacy IRQ */ +#define CM_SPD24SEL39 0x00200000 /* 24-bit spdif: model 039 */ #define CM_AC3EN1 0x00100000 /* enable AC3: model 037 */ +#define CM_SPDIF_SELECT1 0x00080000 /* for model <= 037 ? */ #define CM_SPD24SEL 0x00020000 /* 24bit spdif: model 037 */ /* #define CM_SPDIF_INVERSE 0x00010000 */ /* ??? */ @@ -134,35 +131,47 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); #define CM_ADCBITLEN_14 0x00008000 #define CM_ADCBITLEN_13 0x0000C000 -#define CM_ADCDACLEN_MASK 0x00003000 +#define CM_ADCDACLEN_MASK 0x00003000 /* model 037 */ #define CM_ADCDACLEN_060 0x00000000 #define CM_ADCDACLEN_066 0x00001000 #define CM_ADCDACLEN_130 0x00002000 #define CM_ADCDACLEN_280 0x00003000 +#define CM_ADCDLEN_MASK 0x00003000 /* model 039 */ +#define CM_ADCDLEN_ORIGINAL 0x00000000 +#define CM_ADCDLEN_EXTRA 0x00001000 +#define CM_ADCDLEN_24K 0x00002000 +#define CM_ADCDLEN_WEIGHT 0x00003000 + #define CM_CH1_SRATE_176K 0x00000800 +#define CM_CH1_SRATE_96K 0x00000800 /* model 055? */ #define CM_CH1_SRATE_88K 0x00000400 #define CM_CH0_SRATE_176K 0x00000200 +#define CM_CH0_SRATE_96K 0x00000200 /* model 055? */ #define CM_CH0_SRATE_88K 0x00000100 +#define CM_CH0_SRATE_128K 0x00000300 +#define CM_CH0_SRATE_MASK 0x00000300 #define CM_SPDIF_INVERSE2 0x00000080 /* model 055? */ +#define CM_DBLSPDS 0x00000040 /* double SPDIF sample rate 88.2/96 */ +#define CM_POLVALID 0x00000020 /* inverse SPDIF/IN valid bit */ +#define CM_SPDLOCKED 0x00000010 -#define CM_CH1FMT_MASK 0x0000000C +#define CM_CH1FMT_MASK 0x0000000C /* bit 3: 16 bits, bit 2: stereo */ #define CM_CH1FMT_SHIFT 2 -#define CM_CH0FMT_MASK 0x00000003 +#define CM_CH0FMT_MASK 0x00000003 /* bit 1: 16 bits, bit 0: stereo */ #define CM_CH0FMT_SHIFT 0 #define CM_REG_INT_HLDCLR 0x0C #define CM_CHIP_MASK2 0xff000000 +#define CM_CHIP_8768 0x20000000 +#define CM_CHIP_055 0x08000000 #define CM_CHIP_039 0x04000000 #define CM_CHIP_039_6CH 0x01000000 -#define CM_CHIP_055 0x08000000 -#define CM_CHIP_8768 0x20000000 +#define CM_UNKNOWN_INT_EN 0x00080000 /* ? */ #define CM_TDMA_INT_EN 0x00040000 #define CM_CH1_INT_EN 0x00020000 #define CM_CH0_INT_EN 0x00010000 -#define CM_INT_HOLD 0x00000002 -#define CM_INT_CLEAR 0x00000001 #define CM_REG_INT_STATUS 0x10 #define CM_INTR 0x80000000 @@ -181,12 +190,13 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); #define CM_CHINT0 0x00000001 #define CM_REG_LEGACY_CTRL 0x14 -#define CM_NXCHG 0x80000000 /* h/w multi channels? */ +#define CM_NXCHG 0x80000000 /* don't map base reg dword->sample */ #define CM_VMPU_MASK 0x60000000 /* MPU401 i/o port address */ #define CM_VMPU_330 0x00000000 #define CM_VMPU_320 0x20000000 #define CM_VMPU_310 0x40000000 #define CM_VMPU_300 0x60000000 +#define CM_ENWR8237 0x10000000 /* enable bus master to write 8237 base reg */ #define CM_VSBSEL_MASK 0x0C000000 /* SB16 base address */ #define CM_VSBSEL_220 0x00000000 #define CM_VSBSEL_240 0x04000000 @@ -197,44 +207,73 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); #define CM_FMSEL_3C8 0x01000000 #define CM_FMSEL_3E0 0x02000000 #define CM_FMSEL_3E8 0x03000000 -#define CM_ENSPDOUT 0x00800000 /* enable XPDIF/OUT to I/O interface */ -#define CM_SPDCOPYRHT 0x00400000 /* set copyright spdif in/out */ +#define CM_ENSPDOUT 0x00800000 /* enable XSPDIF/OUT to I/O interface */ +#define CM_SPDCOPYRHT 0x00400000 /* spdif in/out copyright bit */ #define CM_DAC2SPDO 0x00200000 /* enable wave+fm_midi -> SPDIF/OUT */ -#define CM_SETRETRY 0x00010000 /* 0: legacy i/o wait (default), 1: legacy i/o bus retry */ +#define CM_INVIDWEN 0x00100000 /* internal vendor ID write enable, model 039? */ +#define CM_SETRETRY 0x00100000 /* 0: legacy i/o wait (default), 1: legacy i/o bus retry */ +#define CM_C_EEACCESS 0x00080000 /* direct programming eeprom regs */ +#define CM_C_EECS 0x00040000 +#define CM_C_EEDI46 0x00020000 +#define CM_C_EECK46 0x00010000 #define CM_CHB3D6C 0x00008000 /* 5.1 channels support */ -#define CM_LINE_AS_BASS 0x00006000 /* use line-in as bass */ +#define CM_CENTR2LIN 0x00004000 /* line-in as center out */ +#define CM_BASE2LIN 0x00002000 /* line-in as bass out */ +#define CM_EXBASEN 0x00001000 /* external bass input enable */ #define CM_REG_MISC_CTRL 0x18 -#define CM_PWD 0x80000000 +#define CM_PWD 0x80000000 /* power down */ #define CM_RESET 0x40000000 -#define CM_SFIL_MASK 0x30000000 -#define CM_TXVX 0x08000000 -#define CM_N4SPK3D 0x04000000 /* 4ch output */ +#define CM_SFIL_MASK 0x30000000 /* filter control at front end DAC, model 037? */ +#define CM_VMGAIN 0x10000000 /* analog master amp +6dB, model 039? */ +#define CM_TXVX 0x08000000 /* model 037? */ +#define CM_N4SPK3D 0x04000000 /* copy front to rear */ #define CM_SPDO5V 0x02000000 /* 5V spdif output (1 = 0.5v (coax)) */ #define CM_SPDIF48K 0x01000000 /* write */ #define CM_SPATUS48K 0x01000000 /* read */ -#define CM_ENDBDAC 0x00800000 /* enable dual dac */ +#define CM_ENDBDAC 0x00800000 /* enable double dac */ #define CM_XCHGDAC 0x00400000 /* 0: front=ch0, 1: front=ch1 */ #define CM_SPD32SEL 0x00200000 /* 0: 16bit SPDIF, 1: 32bit */ -#define CM_SPDFLOOPI 0x00100000 /* int. SPDIF-IN -> int. OUT */ -#define CM_FM_EN 0x00080000 /* enalbe FM */ +#define CM_SPDFLOOPI 0x00100000 /* int. SPDIF-OUT -> int. IN */ +#define CM_FM_EN 0x00080000 /* enable legacy FM */ #define CM_AC3EN2 0x00040000 /* enable AC3: model 039 */ -#define CM_VIDWPDSB 0x00010000 +#define CM_ENWRASID 0x00010000 /* choose writable internal SUBID (audio) */ +#define CM_VIDWPDSB 0x00010000 /* model 037? */ #define CM_SPDF_AC97 0x00008000 /* 0: SPDIF/OUT 44.1K, 1: 48K */ -#define CM_MASK_EN 0x00004000 -#define CM_VIDWPPRT 0x00002000 -#define CM_SFILENB 0x00001000 -#define CM_MMODE_MASK 0x00000E00 +#define CM_MASK_EN 0x00004000 /* activate channel mask on legacy DMA */ +#define CM_ENWRMSID 0x00002000 /* choose writable internal SUBID (modem) */ +#define CM_VIDWPPRT 0x00002000 /* model 037? */ +#define CM_SFILENB 0x00001000 /* filter stepping at front end DAC, model 037? */ +#define CM_MMODE_MASK 0x00000E00 /* model DAA interface mode */ #define CM_SPDIF_SELECT2 0x00000100 /* for model > 039 ? */ #define CM_ENCENTER 0x00000080 -#define CM_FLINKON 0x00000040 -#define CM_FLINKOFF 0x00000020 -#define CM_MIDSMP 0x00000010 -#define CM_UPDDMA_MASK 0x0000000C -#define CM_TWAIT_MASK 0x00000003 +#define CM_FLINKON 0x00000040 /* force modem link detection on, model 037 */ +#define CM_MUTECH1 0x00000040 /* mute PCI ch1 to DAC */ +#define CM_FLINKOFF 0x00000020 /* force modem link detection off, model 037 */ +#define CM_MIDSMP 0x00000010 /* 1/2 interpolation at front end DAC */ +#define CM_UPDDMA_MASK 0x0000000C /* TDMA position update notification */ +#define CM_UPDDMA_2048 0x00000000 +#define CM_UPDDMA_1024 0x00000004 +#define CM_UPDDMA_512 0x00000008 +#define CM_UPDDMA_256 0x0000000C +#define CM_TWAIT_MASK 0x00000003 /* model 037 */ +#define CM_TWAIT1 0x00000002 /* FM i/o cycle, 0: 48, 1: 64 PCICLKs */ +#define CM_TWAIT0 0x00000001 /* i/o cycle, 0: 4, 1: 6 PCICLKs */ + +#define CM_REG_TDMA_POSITION 0x1C +#define CM_TDMA_CNT_MASK 0xFFFF0000 /* current byte/word count */ +#define CM_TDMA_ADR_MASK 0x0000FFFF /* current address */ /* byte */ #define CM_REG_MIXER0 0x20 +#define CM_REG_SBVR 0x20 /* write: sb16 version */ +#define CM_REG_DEV 0x20 /* read: hardware device version */ + +#define CM_REG_MIXER21 0x21 +#define CM_UNKNOWN_21_MASK 0x78 /* ? */ +#define CM_X_ADPCM 0x04 /* SB16 ADPCM enable */ +#define CM_PROINV 0x02 /* SBPro left/right channel switching */ +#define CM_X_SB16 0x01 /* SB16 compatible */ #define CM_REG_SB16_DATA 0x22 #define CM_REG_SB16_ADDR 0x23 @@ -249,8 +288,8 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); #define CM_FMMUTE_SHIFT 7 #define CM_WSMUTE 0x40 /* mute PCM */ #define CM_WSMUTE_SHIFT 6 -#define CM_SPK4 0x20 /* lin-in -> rear line out */ -#define CM_SPK4_SHIFT 5 +#define CM_REAR2LIN 0x20 /* lin-in -> rear line out */ +#define CM_REAR2LIN_SHIFT 5 #define CM_REAR2FRONT 0x10 /* exchange rear/front */ #define CM_REAR2FRONT_SHIFT 4 #define CM_WAVEINL 0x08 /* digital wave rec. left chan */ @@ -276,17 +315,19 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); #define CM_MICGAINZ 0x01 /* mic boost */ #define CM_MICGAINZ_SHIFT 0 +#define CM_REG_MIXER3 0x24 #define CM_REG_AUX_VOL 0x26 #define CM_VAUXL_MASK 0xf0 #define CM_VAUXR_MASK 0x0f #define CM_REG_MISC 0x27 +#define CM_UNKNOWN_27_MASK 0xd8 /* ? */ #define CM_XGPO1 0x20 // #define CM_XGPBIO 0x04 #define CM_MIC_CENTER_LFE 0x04 /* mic as center/lfe out? (model 039 or later?) */ #define CM_SPDIF_INVERSE 0x04 /* spdif input phase inverse (model 037) */ #define CM_SPDVALID 0x02 /* spdif input valid check */ -#define CM_DMAUTO 0x01 +#define CM_DMAUTO 0x01 /* SB16 DMA auto detect */ #define CM_REG_AC97 0x28 /* hmmm.. do we have ac97 link? */ /* @@ -327,17 +368,20 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); /* * extended registers */ -#define CM_REG_CH0_FRAME1 0x80 /* base address */ -#define CM_REG_CH0_FRAME2 0x84 +#define CM_REG_CH0_FRAME1 0x80 /* write: base address */ +#define CM_REG_CH0_FRAME2 0x84 /* read: current address */ #define CM_REG_CH1_FRAME1 0x88 /* 0-15: count of samples at bus master; buffer size */ #define CM_REG_CH1_FRAME2 0x8C /* 16-31: count of samples at codec; fragment size */ -#define CM_REG_MISC_CTRL_8768 0x92 /* reg. name the same as 0x18 */ -#define CM_CHB3D8C 0x20 /* 7.1 channels support */ -#define CM_SPD32FMT 0x10 /* SPDIF/IN 32k */ -#define CM_ADC2SPDIF 0x08 /* ADC output to SPDIF/OUT */ -#define CM_SHAREADC 0x04 /* DAC in ADC as Center/LFE */ -#define CM_REALTCMP 0x02 /* monitor the CMPL/CMPR of ADC */ -#define CM_INVLRCK 0x01 /* invert ZVPORT's LRCK */ + +#define CM_REG_EXT_MISC 0x90 +#define CM_ADC48K44K 0x10000000 /* ADC parameters group, 0: 44k, 1: 48k */ +#define CM_CHB3D8C 0x00200000 /* 7.1 channels support */ +#define CM_SPD32FMT 0x00100000 /* SPDIF/IN 32k sample rate */ +#define CM_ADC2SPDIF 0x00080000 /* ADC output to SPDIF/OUT */ +#define CM_SHAREADC 0x00040000 /* DAC in ADC as Center/LFE */ +#define CM_REALTCMP 0x00020000 /* monitor the CMPL/CMPR of ADC */ +#define CM_INVLRCK 0x00010000 /* invert ZVPORT's LRCK */ +#define CM_UNKNOWN_90_MASK 0x0000FFFF /* ? */ /* * size of i/o region @@ -348,25 +392,6 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); /* - * pci ids - */ -#ifndef PCI_VENDOR_ID_CMEDIA -#define PCI_VENDOR_ID_CMEDIA 0x13F6 -#endif -#ifndef PCI_DEVICE_ID_CMEDIA_CM8338A -#define PCI_DEVICE_ID_CMEDIA_CM8338A 0x0100 -#endif -#ifndef PCI_DEVICE_ID_CMEDIA_CM8338B -#define PCI_DEVICE_ID_CMEDIA_CM8338B 0x0101 -#endif -#ifndef PCI_DEVICE_ID_CMEDIA_CM8738 -#define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111 -#endif -#ifndef PCI_DEVICE_ID_CMEDIA_CM8738B -#define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112 -#endif - -/* * channels for playback / capture */ #define CM_CH_PLAY 0 @@ -404,20 +429,16 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address."); * driver data */ -typedef struct snd_stru_cmipci cmipci_t; -typedef struct snd_stru_cmipci_pcm cmipci_pcm_t; - -struct snd_stru_cmipci_pcm { - snd_pcm_substream_t *substream; - int running; /* dac/adc running? */ +struct cmipci_pcm { + struct snd_pcm_substream *substream; + u8 running; /* dac/adc running? */ + u8 fmt; /* format bits */ + u8 is_dac; + u8 needs_silencing; unsigned int dma_size; /* in frames */ - unsigned int period_size; /* in frames */ + unsigned int shift; + unsigned int ch; /* channel (0/1) */ unsigned int offset; /* physical address of the buffer */ - unsigned int fmt; /* format bits */ - int ch; /* channel (0/1) */ - unsigned int is_dac; /* is dac? */ - int bytes_per_frame; - int shift; }; /* mixer elements toggled/resumed during ac3 playback */ @@ -434,8 +455,8 @@ static const struct cmipci_mixer_auto_switches cm_saved_mixer[] = { }; #define CM_SAVED_MIXERS ARRAY_SIZE(cm_saved_mixer) -struct snd_stru_cmipci { - snd_card_t *card; +struct cmipci { + struct snd_card *card; struct pci_dev *pci; unsigned int device; /* device ID */ @@ -444,16 +465,16 @@ struct snd_stru_cmipci { unsigned long iobase; unsigned int ctrl; /* FUNCTRL0 current value */ - snd_pcm_t *pcm; /* DAC/ADC PCM */ - snd_pcm_t *pcm2; /* 2nd DAC */ - snd_pcm_t *pcm_spdif; /* SPDIF */ + struct snd_pcm *pcm; /* DAC/ADC PCM */ + struct snd_pcm *pcm2; /* 2nd DAC */ + struct snd_pcm *pcm_spdif; /* SPDIF */ int chip_version; int max_channels; - unsigned int has_dual_dac: 1; unsigned int can_ac3_sw: 1; unsigned int can_ac3_hw: 1; unsigned int can_multi_ch: 1; + unsigned int can_96k: 1; /* samplerate above 48k */ unsigned int do_soft_ac3: 1; unsigned int spdif_playback_avail: 1; /* spdif ready? */ @@ -463,66 +484,68 @@ struct snd_stru_cmipci { unsigned int dig_status; unsigned int dig_pcm_status; - snd_pcm_hardware_t *hw_info[3]; /* for playbacks */ + struct snd_pcm_hardware *hw_info[3]; /* for playbacks */ int opened[2]; /* open mode */ - struct semaphore open_mutex; + struct mutex open_mutex; unsigned int mixer_insensitive: 1; - snd_kcontrol_t *mixer_res_ctl[CM_SAVED_MIXERS]; + struct snd_kcontrol *mixer_res_ctl[CM_SAVED_MIXERS]; int mixer_res_status[CM_SAVED_MIXERS]; - opl3_t *opl3; - snd_hwdep_t *opl3hwdep; - - cmipci_pcm_t channel[2]; /* ch0 - DAC, ch1 - ADC or 2nd DAC */ + struct cmipci_pcm channel[2]; /* ch0 - DAC, ch1 - ADC or 2nd DAC */ /* external MIDI */ - snd_rawmidi_t *rmidi; + struct snd_rawmidi *rmidi; #ifdef SUPPORT_JOYSTICK struct gameport *gameport; #endif spinlock_t reg_lock; + +#ifdef CONFIG_PM + unsigned int saved_regs[0x20]; + unsigned char saved_mixers[0x20]; +#endif }; /* read/write operations for dword register */ -static inline void snd_cmipci_write(cmipci_t *cm, unsigned int cmd, unsigned int data) +static inline void snd_cmipci_write(struct cmipci *cm, unsigned int cmd, unsigned int data) { outl(data, cm->iobase + cmd); } -static inline unsigned int snd_cmipci_read(cmipci_t *cm, unsigned int cmd) +static inline unsigned int snd_cmipci_read(struct cmipci *cm, unsigned int cmd) { return inl(cm->iobase + cmd); } /* read/write operations for word register */ -static inline void snd_cmipci_write_w(cmipci_t *cm, unsigned int cmd, unsigned short data) +static inline void snd_cmipci_write_w(struct cmipci *cm, unsigned int cmd, unsigned short data) { outw(data, cm->iobase + cmd); } -static inline unsigned short snd_cmipci_read_w(cmipci_t *cm, unsigned int cmd) +static inline unsigned short snd_cmipci_read_w(struct cmipci *cm, unsigned int cmd) { return inw(cm->iobase + cmd); } /* read/write operations for byte register */ -static inline void snd_cmipci_write_b(cmipci_t *cm, unsigned int cmd, unsigned char data) +static inline void snd_cmipci_write_b(struct cmipci *cm, unsigned int cmd, unsigned char data) { outb(data, cm->iobase + cmd); } -static inline unsigned char snd_cmipci_read_b(cmipci_t *cm, unsigned int cmd) +static inline unsigned char snd_cmipci_read_b(struct cmipci *cm, unsigned int cmd) { return inb(cm->iobase + cmd); } /* bit operations for dword register */ -static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) +static int snd_cmipci_set_bit(struct cmipci *cm, unsigned int cmd, unsigned int flag) { unsigned int val, oval; val = oval = inl(cm->iobase + cmd); @@ -533,7 +556,7 @@ static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) return 1; } -static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag) +static int snd_cmipci_clear_bit(struct cmipci *cm, unsigned int cmd, unsigned int flag) { unsigned int val, oval; val = oval = inl(cm->iobase + cmd); @@ -545,7 +568,7 @@ static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int fla } /* bit operations for byte register */ -static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) +static int snd_cmipci_set_bit_b(struct cmipci *cm, unsigned int cmd, unsigned char flag) { unsigned char val, oval; val = oval = inb(cm->iobase + cmd); @@ -556,7 +579,7 @@ static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char fl return 1; } -static int snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag) +static int snd_cmipci_clear_bit_b(struct cmipci *cm, unsigned int cmd, unsigned char flag) { unsigned char val, oval; val = oval = inb(cm->iobase + cmd); @@ -581,6 +604,7 @@ static unsigned int rates[] = { 5512, 11025, 22050, 44100, 8000, 16000, 32000, 4 static unsigned int snd_cmipci_rate_freq(unsigned int rate) { unsigned int i; + for (i = 0; i < ARRAY_SIZE(rates); i++) { if (rates[i] == rate) return i; @@ -637,7 +661,7 @@ out: * at the register CM_REG_FUNCTRL1 (0x04). * Problem: other ways are also possible (any information about that?) */ -static void snd_cmipci_set_pll(cmipci_t *cm, unsigned int rate, unsigned int slot) +static void snd_cmipci_set_pll(struct cmipci *cm, unsigned int rate, unsigned int slot) { unsigned int reg = CM_REG_PLL + slot; /* @@ -655,30 +679,30 @@ static void snd_cmipci_set_pll(cmipci_t *cm, unsigned int rate, unsigned int slo } #endif /* USE_VAR48KRATE */ -static int snd_cmipci_hw_params(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) +static int snd_cmipci_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); } -static int snd_cmipci_playback2_hw_params(snd_pcm_substream_t * substream, - snd_pcm_hw_params_t * hw_params) +static int snd_cmipci_playback2_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); if (params_channels(hw_params) > 2) { - down(&cm->open_mutex); + mutex_lock(&cm->open_mutex); if (cm->opened[CM_CH_PLAY]) { - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); return -EBUSY; } /* reserve the channel A */ cm->opened[CM_CH_PLAY] = CM_OPEN_PLAYBACK_MULTI; - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); } return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); } -static void snd_cmipci_ch_reset(cmipci_t *cm, int ch) +static void snd_cmipci_ch_reset(struct cmipci *cm, int ch) { int reset = CM_RST_CH0 << (cm->channel[ch].ch); snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset); @@ -686,7 +710,7 @@ static void snd_cmipci_ch_reset(cmipci_t *cm, int ch) udelay(10); } -static int snd_cmipci_hw_free(snd_pcm_substream_t * substream) +static int snd_cmipci_hw_free(struct snd_pcm_substream *substream) { return snd_pcm_lib_free_pages(substream); } @@ -695,68 +719,57 @@ static int snd_cmipci_hw_free(snd_pcm_substream_t * substream) /* */ -static unsigned int hw_channels[] = {1, 2, 4, 5, 6, 8}; -static snd_pcm_hw_constraint_list_t hw_constraints_channels_4 = { +static unsigned int hw_channels[] = {1, 2, 4, 6, 8}; +static struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = { .count = 3, .list = hw_channels, .mask = 0, }; -static snd_pcm_hw_constraint_list_t hw_constraints_channels_6 = { - .count = 5, +static struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = { + .count = 4, .list = hw_channels, .mask = 0, }; -static snd_pcm_hw_constraint_list_t hw_constraints_channels_8 = { - .count = 6, +static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { + .count = 5, .list = hw_channels, .mask = 0, }; -static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels) +static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int channels) { if (channels > 2) { - if (! cm->can_multi_ch) + if (!cm->can_multi_ch || !rec->ch) return -EINVAL; if (rec->fmt != 0x03) /* stereo 16bit only */ return -EINVAL; + } + if (cm->can_multi_ch) { spin_lock_irq(&cm->reg_lock); - snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); - if (channels > 4) { - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); + if (channels > 2) { + snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); + snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); } else { - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); - snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); + snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); + snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); } - if (channels >= 6) { + if (channels == 8) + snd_cmipci_set_bit(cm, CM_REG_EXT_MISC, CM_CHB3D8C); + else + snd_cmipci_clear_bit(cm, CM_REG_EXT_MISC, CM_CHB3D8C); + if (channels == 6) { + snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); } else { - snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); - } - if (cm->chip_version == 68) { - if (channels == 8) { - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C); - } else { - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C); - } - } - spin_unlock_irq(&cm->reg_lock); - - } else { - if (cm->can_multi_ch) { - spin_lock_irq(&cm->reg_lock); - snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG); - snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C); snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); - spin_unlock_irq(&cm->reg_lock); } + if (channels == 4) + snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); + else + snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D); + spin_unlock_irq(&cm->reg_lock); } return 0; } @@ -766,11 +779,12 @@ static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels) * prepare playback/capture channel * channel to be used must have been set in rec->ch. */ -static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec, - snd_pcm_substream_t *substream) +static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec, + struct snd_pcm_substream *substream) { - unsigned int reg, freq, val; - snd_pcm_runtime_t *runtime = substream->runtime; + unsigned int reg, freq, freq_ext, val; + unsigned int period_size; + struct snd_pcm_runtime *runtime = substream->runtime; rec->fmt = 0; rec->shift = 0; @@ -789,11 +803,11 @@ static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec, rec->offset = runtime->dma_addr; /* buffer and period sizes in frame */ rec->dma_size = runtime->buffer_size << rec->shift; - rec->period_size = runtime->period_size << rec->shift; + period_size = runtime->period_size << rec->shift; if (runtime->channels > 2) { /* multi-channels */ rec->dma_size = (rec->dma_size * runtime->channels) / 2; - rec->period_size = (rec->period_size * runtime->channels) / 2; + period_size = (period_size * runtime->channels) / 2; } spin_lock_irq(&cm->reg_lock); @@ -804,7 +818,7 @@ static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec, /* program sample counts */ reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; snd_cmipci_write_w(cm, reg, rec->dma_size - 1); - snd_cmipci_write_w(cm, reg + 2, rec->period_size - 1); + snd_cmipci_write_w(cm, reg + 2, period_size - 1); /* set adc/dac flag */ val = rec->ch ? CM_CHADC1 : CM_CHADC0; @@ -816,14 +830,24 @@ static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec, //snd_printd("cmipci: functrl0 = %08x\n", cm->ctrl); /* set sample rate */ - freq = snd_cmipci_rate_freq(runtime->rate); + freq = 0; + freq_ext = 0; + if (runtime->rate > 48000) + switch (runtime->rate) { + case 88200: freq_ext = CM_CH0_SRATE_88K; break; + case 96000: freq_ext = CM_CH0_SRATE_96K; break; + case 128000: freq_ext = CM_CH0_SRATE_128K; break; + default: snd_BUG(); break; + } + else + freq = snd_cmipci_rate_freq(runtime->rate); val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); if (rec->ch) { - val &= ~CM_ASFC_MASK; - val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK; - } else { val &= ~CM_DSFC_MASK; val |= (freq << CM_DSFC_SHIFT) & CM_DSFC_MASK; + } else { + val &= ~CM_ASFC_MASK; + val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK; } snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); //snd_printd("cmipci: functrl1 = %08x\n", val); @@ -837,9 +861,20 @@ static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec, val &= ~CM_CH0FMT_MASK; val |= rec->fmt << CM_CH0FMT_SHIFT; } + if (cm->can_96k) { + val &= ~(CM_CH0_SRATE_MASK << (rec->ch * 2)); + val |= freq_ext << (rec->ch * 2); + } snd_cmipci_write(cm, CM_REG_CHFORMAT, val); //snd_printd("cmipci: chformat = %08x\n", val); + if (!rec->is_dac && cm->chip_version) { + if (runtime->rate > 44100) + snd_cmipci_set_bit(cm, CM_REG_EXT_MISC, CM_ADC48K44K); + else + snd_cmipci_clear_bit(cm, CM_REG_EXT_MISC, CM_ADC48K44K); + } + rec->running = 0; spin_unlock_irq(&cm->reg_lock); @@ -849,8 +884,8 @@ static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec, /* * PCM trigger/stop */ -static int snd_cmipci_pcm_trigger(cmipci_t *cm, cmipci_pcm_t *rec, - snd_pcm_substream_t *substream, int cmd) +static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec, + int cmd) { unsigned int inthld, chen, reset, pause; int result = 0; @@ -879,12 +914,15 @@ static int snd_cmipci_pcm_trigger(cmipci_t *cm, cmipci_pcm_t *rec, cm->ctrl &= ~chen; snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset); snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset); + rec->needs_silencing = rec->is_dac; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: cm->ctrl |= pause; snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: cm->ctrl &= ~pause; snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); break; @@ -899,8 +937,8 @@ static int snd_cmipci_pcm_trigger(cmipci_t *cm, cmipci_pcm_t *rec, /* * return the current pointer */ -static snd_pcm_uframes_t snd_cmipci_pcm_pointer(cmipci_t *cm, cmipci_pcm_t *rec, - snd_pcm_substream_t *substream) +static snd_pcm_uframes_t snd_cmipci_pcm_pointer(struct cmipci *cm, struct cmipci_pcm *rec, + struct snd_pcm_substream *substream) { size_t ptr; unsigned int reg; @@ -924,16 +962,16 @@ static snd_pcm_uframes_t snd_cmipci_pcm_pointer(cmipci_t *cm, cmipci_pcm_t *rec, * playback */ -static int snd_cmipci_playback_trigger(snd_pcm_substream_t *substream, +static int snd_cmipci_playback_trigger(struct snd_pcm_substream *substream, int cmd) { - cmipci_t *cm = snd_pcm_substream_chip(substream); - return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_PLAY], substream, cmd); + struct cmipci *cm = snd_pcm_substream_chip(substream); + return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_PLAY], cmd); } -static snd_pcm_uframes_t snd_cmipci_playback_pointer(snd_pcm_substream_t *substream) +static snd_pcm_uframes_t snd_cmipci_playback_pointer(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); return snd_cmipci_pcm_pointer(cm, &cm->channel[CM_CH_PLAY], substream); } @@ -943,16 +981,16 @@ static snd_pcm_uframes_t snd_cmipci_playback_pointer(snd_pcm_substream_t *substr * capture */ -static int snd_cmipci_capture_trigger(snd_pcm_substream_t *substream, +static int snd_cmipci_capture_trigger(struct snd_pcm_substream *substream, int cmd) { - cmipci_t *cm = snd_pcm_substream_chip(substream); - return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_CAPT], substream, cmd); + struct cmipci *cm = snd_pcm_substream_chip(substream); + return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_CAPT], cmd); } -static snd_pcm_uframes_t snd_cmipci_capture_pointer(snd_pcm_substream_t *substream) +static snd_pcm_uframes_t snd_cmipci_capture_pointer(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); return snd_cmipci_pcm_pointer(cm, &cm->channel[CM_CH_CAPT], substream); } @@ -961,18 +999,18 @@ static snd_pcm_uframes_t snd_cmipci_capture_pointer(snd_pcm_substream_t *substre * hw preparation for spdif */ -static int snd_cmipci_spdif_default_info(snd_kcontrol_t *kcontrol, - snd_ctl_elem_info_t *uinfo) +static int snd_cmipci_spdif_default_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0; } -static int snd_cmipci_spdif_default_get(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_spdif_default_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *chip = snd_kcontrol_chip(kcontrol); + struct cmipci *chip = snd_kcontrol_chip(kcontrol); int i; spin_lock_irq(&chip->reg_lock); @@ -982,10 +1020,10 @@ static int snd_cmipci_spdif_default_get(snd_kcontrol_t *kcontrol, return 0; } -static int snd_cmipci_spdif_default_put(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t * ucontrol) +static int snd_cmipci_spdif_default_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *chip = snd_kcontrol_chip(kcontrol); + struct cmipci *chip = snd_kcontrol_chip(kcontrol); int i, change; unsigned int val; @@ -999,7 +1037,7 @@ static int snd_cmipci_spdif_default_put(snd_kcontrol_t * kcontrol, return change; } -static snd_kcontrol_new_t snd_cmipci_spdif_default __devinitdata = +static struct snd_kcontrol_new snd_cmipci_spdif_default __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), @@ -1008,16 +1046,16 @@ static snd_kcontrol_new_t snd_cmipci_spdif_default __devinitdata = .put = snd_cmipci_spdif_default_put }; -static int snd_cmipci_spdif_mask_info(snd_kcontrol_t *kcontrol, - snd_ctl_elem_info_t *uinfo) +static int snd_cmipci_spdif_mask_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0; } -static int snd_cmipci_spdif_mask_get(snd_kcontrol_t * kcontrol, - snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_spdif_mask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { ucontrol->value.iec958.status[0] = 0xff; ucontrol->value.iec958.status[1] = 0xff; @@ -1026,7 +1064,7 @@ static int snd_cmipci_spdif_mask_get(snd_kcontrol_t * kcontrol, return 0; } -static snd_kcontrol_new_t snd_cmipci_spdif_mask __devinitdata = +static struct snd_kcontrol_new snd_cmipci_spdif_mask __devinitdata = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -1035,18 +1073,18 @@ static snd_kcontrol_new_t snd_cmipci_spdif_mask __devinitdata = .get = snd_cmipci_spdif_mask_get, }; -static int snd_cmipci_spdif_stream_info(snd_kcontrol_t *kcontrol, - snd_ctl_elem_info_t *uinfo) +static int snd_cmipci_spdif_stream_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0; } -static int snd_cmipci_spdif_stream_get(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_spdif_stream_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *chip = snd_kcontrol_chip(kcontrol); + struct cmipci *chip = snd_kcontrol_chip(kcontrol); int i; spin_lock_irq(&chip->reg_lock); @@ -1056,10 +1094,10 @@ static int snd_cmipci_spdif_stream_get(snd_kcontrol_t *kcontrol, return 0; } -static int snd_cmipci_spdif_stream_put(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_spdif_stream_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *chip = snd_kcontrol_chip(kcontrol); + struct cmipci *chip = snd_kcontrol_chip(kcontrol); int i, change; unsigned int val; @@ -1073,7 +1111,7 @@ static int snd_cmipci_spdif_stream_put(snd_kcontrol_t *kcontrol, return change; } -static snd_kcontrol_new_t snd_cmipci_spdif_stream __devinitdata = +static struct snd_kcontrol_new snd_cmipci_spdif_stream __devinitdata = { .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -1087,17 +1125,17 @@ static snd_kcontrol_new_t snd_cmipci_spdif_stream __devinitdata = */ /* save mixer setting and mute for AC3 playback */ -static int save_mixer_state(cmipci_t *cm) +static int save_mixer_state(struct cmipci *cm) { if (! cm->mixer_insensitive) { - snd_ctl_elem_value_t *val; + struct snd_ctl_elem_value *val; unsigned int i; val = kmalloc(sizeof(*val), GFP_ATOMIC); if (!val) return -ENOMEM; for (i = 0; i < CM_SAVED_MIXERS; i++) { - snd_kcontrol_t *ctl = cm->mixer_res_ctl[i]; + struct snd_kcontrol *ctl = cm->mixer_res_ctl[i]; if (ctl) { int event; memset(val, 0, sizeof(*val)); @@ -1121,10 +1159,10 @@ static int save_mixer_state(cmipci_t *cm) /* restore the previously saved mixer status */ -static void restore_mixer_state(cmipci_t *cm) +static void restore_mixer_state(struct cmipci *cm) { if (cm->mixer_insensitive) { - snd_ctl_elem_value_t *val; + struct snd_ctl_elem_value *val; unsigned int i; val = kmalloc(sizeof(*val), GFP_KERNEL); @@ -1133,7 +1171,7 @@ static void restore_mixer_state(cmipci_t *cm) cm->mixer_insensitive = 0; /* at first clear this; otherwise the changes will be ignored */ for (i = 0; i < CM_SAVED_MIXERS; i++) { - snd_kcontrol_t *ctl = cm->mixer_res_ctl[i]; + struct snd_kcontrol *ctl = cm->mixer_res_ctl[i]; if (ctl) { int event; @@ -1154,7 +1192,7 @@ static void restore_mixer_state(cmipci_t *cm) } /* spinlock held! */ -static void setup_ac3(cmipci_t *cm, snd_pcm_substream_t *subs, int do_ac3, int rate) +static void setup_ac3(struct cmipci *cm, struct snd_pcm_substream *subs, int do_ac3, int rate) { if (do_ac3) { /* AC3EN for 037 */ @@ -1201,7 +1239,7 @@ static void setup_ac3(cmipci_t *cm, snd_pcm_substream_t *subs, int do_ac3, int r } } -static int setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up, int do_ac3) +static int setup_spdif_playback(struct cmipci *cm, struct snd_pcm_substream *subs, int up, int do_ac3) { int rate, err; @@ -1221,15 +1259,19 @@ static int setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up, snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); setup_ac3(cm, subs, do_ac3, rate); - if (rate == 48000) + if (rate == 48000 || rate == 96000) snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); else snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K | CM_SPDF_AC97); - + if (rate > 48000) + snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); + else + snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); } else { /* they are controlled via "IEC958 Output Switch" */ /* snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_ENSPDOUT); */ /* snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_SPDO2DAC); */ + snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF); setup_ac3(cm, subs, 0, 0); } @@ -1243,13 +1285,13 @@ static int setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up, */ /* playback - enable spdif only on the certain condition */ -static int snd_cmipci_playback_prepare(snd_pcm_substream_t *substream) +static int snd_cmipci_playback_prepare(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); int rate = substream->runtime->rate; int err, do_spdif, do_ac3 = 0; - do_spdif = ((rate == 44100 || rate == 48000) && + do_spdif = (rate >= 44100 && rate <= 96000 && substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE && substream->runtime->channels == 2); if (do_spdif && cm->can_ac3_hw) @@ -1260,9 +1302,9 @@ static int snd_cmipci_playback_prepare(snd_pcm_substream_t *substream) } /* playback (via device #2) - enable spdif always */ -static int snd_cmipci_playback_spdif_prepare(snd_pcm_substream_t *substream) +static int snd_cmipci_playback_spdif_prepare(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); int err, do_ac3; if (cm->can_ac3_hw) @@ -1274,39 +1316,113 @@ static int snd_cmipci_playback_spdif_prepare(snd_pcm_substream_t *substream) return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream); } -static int snd_cmipci_playback_hw_free(snd_pcm_substream_t *substream) +/* + * Apparently, the samples last played on channel A stay in some buffer, even + * after the channel is reset, and get added to the data for the rear DACs when + * playing a multichannel stream on channel B. This is likely to generate + * wraparounds and thus distortions. + * To avoid this, we play at least one zero sample after the actual stream has + * stopped. + */ +static void snd_cmipci_silence_hack(struct cmipci *cm, struct cmipci_pcm *rec) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = rec->substream->runtime; + unsigned int reg, val; + + if (rec->needs_silencing && runtime && runtime->dma_area) { + /* set up a small silence buffer */ + memset(runtime->dma_area, 0, PAGE_SIZE); + reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; + val = ((PAGE_SIZE / 4) - 1) | (((PAGE_SIZE / 4) / 2 - 1) << 16); + snd_cmipci_write(cm, reg, val); + + /* configure for 16 bits, 2 channels, 8 kHz */ + if (runtime->channels > 2) + set_dac_channels(cm, rec, 2); + spin_lock_irq(&cm->reg_lock); + val = snd_cmipci_read(cm, CM_REG_FUNCTRL1); + val &= ~(CM_ASFC_MASK << (rec->ch * 3)); + val |= (4 << CM_ASFC_SHIFT) << (rec->ch * 3); + snd_cmipci_write(cm, CM_REG_FUNCTRL1, val); + val = snd_cmipci_read(cm, CM_REG_CHFORMAT); + val &= ~(CM_CH0FMT_MASK << (rec->ch * 2)); + val |= (3 << CM_CH0FMT_SHIFT) << (rec->ch * 2); + if (cm->can_96k) + val &= ~(CM_CH0_SRATE_MASK << (rec->ch * 2)); + snd_cmipci_write(cm, CM_REG_CHFORMAT, val); + + /* start stream (we don't need interrupts) */ + cm->ctrl |= CM_CHEN0 << rec->ch; + snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl); + spin_unlock_irq(&cm->reg_lock); + + msleep(1); + + /* stop and reset stream */ + spin_lock_irq(&cm->reg_lock); + cm->ctrl &= ~(CM_CHEN0 << rec->ch); + val = CM_RST_CH0 << rec->ch; + snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | val); + snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~val); + spin_unlock_irq(&cm->reg_lock); + + rec->needs_silencing = 0; + } +} + +static int snd_cmipci_playback_hw_free(struct snd_pcm_substream *substream) +{ + struct cmipci *cm = snd_pcm_substream_chip(substream); setup_spdif_playback(cm, substream, 0, 0); restore_mixer_state(cm); + snd_cmipci_silence_hack(cm, &cm->channel[0]); + return snd_cmipci_hw_free(substream); +} + +static int snd_cmipci_playback2_hw_free(struct snd_pcm_substream *substream) +{ + struct cmipci *cm = snd_pcm_substream_chip(substream); + snd_cmipci_silence_hack(cm, &cm->channel[1]); return snd_cmipci_hw_free(substream); } /* capture */ -static int snd_cmipci_capture_prepare(snd_pcm_substream_t *substream) +static int snd_cmipci_capture_prepare(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream); } /* capture with spdif (via device #2) */ -static int snd_cmipci_capture_spdif_prepare(snd_pcm_substream_t *substream) +static int snd_cmipci_capture_spdif_prepare(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); spin_lock_irq(&cm->reg_lock); snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF); + if (cm->can_96k) { + if (substream->runtime->rate > 48000) + snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); + else + snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_DBLSPDS); + } + if (snd_pcm_format_width(substream->runtime->format) > 16) + snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); + else + snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); + spin_unlock_irq(&cm->reg_lock); return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream); } -static int snd_cmipci_capture_spdif_hw_free(snd_pcm_substream_t *subs) +static int snd_cmipci_capture_spdif_hw_free(struct snd_pcm_substream *subs) { - cmipci_t *cm = snd_pcm_substream_chip(subs); + struct cmipci *cm = snd_pcm_substream_chip(subs); spin_lock_irq(&cm->reg_lock); snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF); + snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL); spin_unlock_irq(&cm->reg_lock); return snd_cmipci_hw_free(subs); @@ -1316,9 +1432,9 @@ static int snd_cmipci_capture_spdif_hw_free(snd_pcm_substream_t *subs) /* * interrupt handler */ -static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id) { - cmipci_t *cm = dev_id; + struct cmipci *cm = dev_id; unsigned int status, mask = 0; /* fastpath out, to ease interrupt sharing */ @@ -1337,7 +1453,7 @@ static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id, struct pt_regs *r spin_unlock(&cm->reg_lock); if (cm->rmidi && (status & CM_UARTINT)) - snd_mpu401_uart_interrupt(irq, cm->rmidi->private_data, regs); + snd_mpu401_uart_interrupt(irq, cm->rmidi->private_data); if (cm->pcm) { if ((status & CM_CHINT0) && cm->channel[0].running) @@ -1353,11 +1469,11 @@ static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id, struct pt_regs *r */ /* playback on channel A */ -static snd_pcm_hardware_t snd_cmipci_playback = +static struct snd_pcm_hardware snd_cmipci_playback = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000, .rate_min = 5512, @@ -1373,11 +1489,11 @@ static snd_pcm_hardware_t snd_cmipci_playback = }; /* capture on channel B */ -static snd_pcm_hardware_t snd_cmipci_capture = +static struct snd_pcm_hardware snd_cmipci_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000, .rate_min = 5512, @@ -1393,11 +1509,11 @@ static snd_pcm_hardware_t snd_cmipci_capture = }; /* playback on channel B - stereo 16bit only? */ -static snd_pcm_hardware_t snd_cmipci_playback2 = +static struct snd_pcm_hardware snd_cmipci_playback2 = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000, .rate_min = 5512, @@ -1413,11 +1529,11 @@ static snd_pcm_hardware_t snd_cmipci_playback2 = }; /* spdif playback on channel A */ -static snd_pcm_hardware_t snd_cmipci_playback_spdif = +static struct snd_pcm_hardware snd_cmipci_playback_spdif = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, .rate_min = 44100, @@ -1433,11 +1549,11 @@ static snd_pcm_hardware_t snd_cmipci_playback_spdif = }; /* spdif playback on channel A (32bit, IEC958 subframes) */ -static snd_pcm_hardware_t snd_cmipci_playback_iec958_subframe = +static struct snd_pcm_hardware snd_cmipci_playback_iec958_subframe = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, .rate_min = 44100, @@ -1453,12 +1569,13 @@ static snd_pcm_hardware_t snd_cmipci_playback_iec958_subframe = }; /* spdif capture on channel B */ -static snd_pcm_hardware_t snd_cmipci_capture_spdif = +static struct snd_pcm_hardware snd_cmipci_capture_spdif = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE, .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, .rate_min = 44100, .rate_max = 48000, @@ -1472,10 +1589,18 @@ static snd_pcm_hardware_t snd_cmipci_capture_spdif = .fifo_size = 0, }; +static unsigned int rate_constraints[] = { 5512, 8000, 11025, 16000, 22050, + 32000, 44100, 48000, 88200, 96000, 128000 }; +static struct snd_pcm_hw_constraint_list hw_constraints_rates = { + .count = ARRAY_SIZE(rate_constraints), + .list = rate_constraints, + .mask = 0, +}; + /* * check device open/close */ -static int open_device_check(cmipci_t *cm, int mode, snd_pcm_substream_t *subs) +static int open_device_check(struct cmipci *cm, int mode, struct snd_pcm_substream *subs) { int ch = mode & CM_OPEN_CH_MASK; @@ -1484,9 +1609,9 @@ static int open_device_check(cmipci_t *cm, int mode, snd_pcm_substream_t *subs) * pcm framework doesn't pass file pointer before actually opened, * we can't know whether blocking mode or not in open callback.. */ - down(&cm->open_mutex); + mutex_lock(&cm->open_mutex); if (cm->opened[ch]) { - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); return -EBUSY; } cm->opened[ch] = mode; @@ -1498,15 +1623,15 @@ static int open_device_check(cmipci_t *cm, int mode, snd_pcm_substream_t *subs) snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC); spin_unlock_irq(&cm->reg_lock); } - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); return 0; } -static void close_device_check(cmipci_t *cm, int mode) +static void close_device_check(struct cmipci *cm, int mode) { int ch = mode & CM_OPEN_CH_MASK; - down(&cm->open_mutex); + mutex_lock(&cm->open_mutex); if (cm->opened[ch] == mode) { if (cm->channel[ch].substream) { snd_cmipci_ch_reset(cm, ch); @@ -1522,31 +1647,42 @@ static void close_device_check(cmipci_t *cm, int mode) spin_unlock_irq(&cm->reg_lock); } } - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); } /* */ -static int snd_cmipci_playback_open(snd_pcm_substream_t *substream) +static int snd_cmipci_playback_open(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + struct cmipci *cm = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; int err; if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0) return err; runtime->hw = snd_cmipci_playback; - runtime->hw.channels_max = cm->max_channels; + if (cm->chip_version == 68) { + runtime->hw.rates |= SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000; + runtime->hw.rate_max = 96000; + } else if (cm->chip_version == 55) { + err = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); + if (err < 0) + return err; + runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; + runtime->hw.rate_max = 128000; + } snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); cm->dig_pcm_status = cm->dig_status; return 0; } -static int snd_cmipci_capture_open(snd_pcm_substream_t *substream) +static int snd_cmipci_capture_open(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + struct cmipci *cm = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; int err; if ((err = open_device_check(cm, CM_OPEN_CAPTURE, substream)) < 0) @@ -1555,21 +1691,28 @@ static int snd_cmipci_capture_open(snd_pcm_substream_t *substream) if (cm->chip_version == 68) { // 8768 only supports 44k/48k recording runtime->hw.rate_min = 41000; runtime->hw.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; + } else if (cm->chip_version == 55) { + err = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); + if (err < 0) + return err; + runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; + runtime->hw.rate_max = 128000; } snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); return 0; } -static int snd_cmipci_playback2_open(snd_pcm_substream_t *substream) +static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + struct cmipci *cm = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; int err; if ((err = open_device_check(cm, CM_OPEN_PLAYBACK2, substream)) < 0) /* use channel B */ return err; runtime->hw = snd_cmipci_playback2; - down(&cm->open_mutex); + mutex_lock(&cm->open_mutex); if (! cm->opened[CM_CH_PLAY]) { if (cm->can_multi_ch) { runtime->hw.channels_max = cm->max_channels; @@ -1580,24 +1723,43 @@ static int snd_cmipci_playback2_open(snd_pcm_substream_t *substream) else if (cm->max_channels == 8) snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8); } - snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); } - up(&cm->open_mutex); + mutex_unlock(&cm->open_mutex); + if (cm->chip_version == 68) { + runtime->hw.rates |= SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000; + runtime->hw.rate_max = 96000; + } else if (cm->chip_version == 55) { + err = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates); + if (err < 0) + return err; + runtime->hw.rates |= SNDRV_PCM_RATE_KNOT; + runtime->hw.rate_max = 128000; + } + snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000); return 0; } -static int snd_cmipci_playback_spdif_open(snd_pcm_substream_t *substream) +static int snd_cmipci_playback_spdif_open(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + struct cmipci *cm = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; int err; if ((err = open_device_check(cm, CM_OPEN_SPDIF_PLAYBACK, substream)) < 0) /* use channel A */ return err; if (cm->can_ac3_hw) { runtime->hw = snd_cmipci_playback_spdif; - if (cm->chip_version >= 37) + if (cm->chip_version >= 37) { runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE; + snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); + } + if (cm->can_96k) { + runtime->hw.rates |= SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000; + runtime->hw.rate_max = 96000; + } } else { runtime->hw = snd_cmipci_playback_iec958_subframe; } @@ -1606,15 +1768,20 @@ static int snd_cmipci_playback_spdif_open(snd_pcm_substream_t *substream) return 0; } -static int snd_cmipci_capture_spdif_open(snd_pcm_substream_t * substream) +static int snd_cmipci_capture_spdif_open(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); - snd_pcm_runtime_t *runtime = substream->runtime; + struct cmipci *cm = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; int err; if ((err = open_device_check(cm, CM_OPEN_SPDIF_CAPTURE, substream)) < 0) /* use channel B */ return err; runtime->hw = snd_cmipci_capture_spdif; + if (cm->can_96k && !(cm->chip_version == 68)) { + runtime->hw.rates |= SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000; + runtime->hw.rate_max = 96000; + } snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x40000); return 0; } @@ -1623,38 +1790,38 @@ static int snd_cmipci_capture_spdif_open(snd_pcm_substream_t * substream) /* */ -static int snd_cmipci_playback_close(snd_pcm_substream_t * substream) +static int snd_cmipci_playback_close(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); close_device_check(cm, CM_OPEN_PLAYBACK); return 0; } -static int snd_cmipci_capture_close(snd_pcm_substream_t * substream) +static int snd_cmipci_capture_close(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); close_device_check(cm, CM_OPEN_CAPTURE); return 0; } -static int snd_cmipci_playback2_close(snd_pcm_substream_t * substream) +static int snd_cmipci_playback2_close(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); close_device_check(cm, CM_OPEN_PLAYBACK2); close_device_check(cm, CM_OPEN_PLAYBACK_MULTI); return 0; } -static int snd_cmipci_playback_spdif_close(snd_pcm_substream_t * substream) +static int snd_cmipci_playback_spdif_close(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); close_device_check(cm, CM_OPEN_SPDIF_PLAYBACK); return 0; } -static int snd_cmipci_capture_spdif_close(snd_pcm_substream_t * substream) +static int snd_cmipci_capture_spdif_close(struct snd_pcm_substream *substream) { - cmipci_t *cm = snd_pcm_substream_chip(substream); + struct cmipci *cm = snd_pcm_substream_chip(substream); close_device_check(cm, CM_OPEN_SPDIF_CAPTURE); return 0; } @@ -1663,7 +1830,7 @@ static int snd_cmipci_capture_spdif_close(snd_pcm_substream_t * substream) /* */ -static snd_pcm_ops_t snd_cmipci_playback_ops = { +static struct snd_pcm_ops snd_cmipci_playback_ops = { .open = snd_cmipci_playback_open, .close = snd_cmipci_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1674,7 +1841,7 @@ static snd_pcm_ops_t snd_cmipci_playback_ops = { .pointer = snd_cmipci_playback_pointer, }; -static snd_pcm_ops_t snd_cmipci_capture_ops = { +static struct snd_pcm_ops snd_cmipci_capture_ops = { .open = snd_cmipci_capture_open, .close = snd_cmipci_capture_close, .ioctl = snd_pcm_lib_ioctl, @@ -1685,18 +1852,18 @@ static snd_pcm_ops_t snd_cmipci_capture_ops = { .pointer = snd_cmipci_capture_pointer, }; -static snd_pcm_ops_t snd_cmipci_playback2_ops = { +static struct snd_pcm_ops snd_cmipci_playback2_ops = { .open = snd_cmipci_playback2_open, .close = snd_cmipci_playback2_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cmipci_playback2_hw_params, - .hw_free = snd_cmipci_hw_free, + .hw_free = snd_cmipci_playback2_hw_free, .prepare = snd_cmipci_capture_prepare, /* channel B */ .trigger = snd_cmipci_capture_trigger, /* channel B */ .pointer = snd_cmipci_capture_pointer, /* channel B */ }; -static snd_pcm_ops_t snd_cmipci_playback_spdif_ops = { +static struct snd_pcm_ops snd_cmipci_playback_spdif_ops = { .open = snd_cmipci_playback_spdif_open, .close = snd_cmipci_playback_spdif_close, .ioctl = snd_pcm_lib_ioctl, @@ -1707,7 +1874,7 @@ static snd_pcm_ops_t snd_cmipci_playback_spdif_ops = { .pointer = snd_cmipci_playback_pointer, }; -static snd_pcm_ops_t snd_cmipci_capture_spdif_ops = { +static struct snd_pcm_ops snd_cmipci_capture_spdif_ops = { .open = snd_cmipci_capture_spdif_open, .close = snd_cmipci_capture_spdif_close, .ioctl = snd_pcm_lib_ioctl, @@ -1722,14 +1889,9 @@ static snd_pcm_ops_t snd_cmipci_capture_spdif_ops = { /* */ -static void snd_cmipci_pcm_free(snd_pcm_t *pcm) -{ - snd_pcm_lib_preallocate_free_for_all(pcm); -} - -static int __devinit snd_cmipci_pcm_new(cmipci_t *cm, int device) +static int __devinit snd_cmipci_pcm_new(struct cmipci *cm, int device) { - snd_pcm_t *pcm; + struct snd_pcm *pcm; int err; err = snd_pcm_new(cm->card, cm->card->driver, device, 1, 1, &pcm); @@ -1740,7 +1902,6 @@ static int __devinit snd_cmipci_pcm_new(cmipci_t *cm, int device) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cmipci_capture_ops); pcm->private_data = cm; - pcm->private_free = snd_cmipci_pcm_free; pcm->info_flags = 0; strcpy(pcm->name, "C-Media PCI DAC/ADC"); cm->pcm = pcm; @@ -1751,9 +1912,9 @@ static int __devinit snd_cmipci_pcm_new(cmipci_t *cm, int device) return 0; } -static int __devinit snd_cmipci_pcm2_new(cmipci_t *cm, int device) +static int __devinit snd_cmipci_pcm2_new(struct cmipci *cm, int device) { - snd_pcm_t *pcm; + struct snd_pcm *pcm; int err; err = snd_pcm_new(cm->card, cm->card->driver, device, 1, 0, &pcm); @@ -1763,7 +1924,6 @@ static int __devinit snd_cmipci_pcm2_new(cmipci_t *cm, int device) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cmipci_playback2_ops); pcm->private_data = cm; - pcm->private_free = snd_cmipci_pcm_free; pcm->info_flags = 0; strcpy(pcm->name, "C-Media PCI 2nd DAC"); cm->pcm2 = pcm; @@ -1774,9 +1934,9 @@ static int __devinit snd_cmipci_pcm2_new(cmipci_t *cm, int device) return 0; } -static int __devinit snd_cmipci_pcm_spdif_new(cmipci_t *cm, int device) +static int __devinit snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device) { - snd_pcm_t *pcm; + struct snd_pcm *pcm; int err; err = snd_pcm_new(cm->card, cm->card->driver, device, 1, 1, &pcm); @@ -1787,7 +1947,6 @@ static int __devinit snd_cmipci_pcm_spdif_new(cmipci_t *cm, int device) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cmipci_capture_spdif_ops); pcm->private_data = cm; - pcm->private_free = snd_cmipci_pcm_free; pcm->info_flags = 0; strcpy(pcm->name, "C-Media PCI IEC958"); cm->pcm_spdif = pcm; @@ -1807,13 +1966,13 @@ static int __devinit snd_cmipci_pcm_spdif_new(cmipci_t *cm, int device) * - Output mute switches */ -static void snd_cmipci_mixer_write(cmipci_t *s, unsigned char idx, unsigned char data) +static void snd_cmipci_mixer_write(struct cmipci *s, unsigned char idx, unsigned char data) { outb(idx, s->iobase + CM_REG_SB16_ADDR); outb(data, s->iobase + CM_REG_SB16_DATA); } -static unsigned char snd_cmipci_mixer_read(cmipci_t *s, unsigned char idx) +static unsigned char snd_cmipci_mixer_read(struct cmipci *s, unsigned char idx) { unsigned char v; @@ -1825,13 +1984,13 @@ static unsigned char snd_cmipci_mixer_read(cmipci_t *s, unsigned char idx) /* * general mixer element */ -typedef struct cmipci_sb_reg { +struct cmipci_sb_reg { unsigned int left_reg, right_reg; unsigned int left_shift, right_shift; unsigned int mask; unsigned int invert: 1; unsigned int stereo: 1; -} cmipci_sb_reg_t; +}; #define COMPOSE_SB_REG(lreg,rreg,lshift,rshift,mask,invert,stereo) \ ((lreg) | ((rreg) << 8) | (lshift << 16) | (rshift << 19) | (mask << 24) | (invert << 22) | (stereo << 23)) @@ -1848,7 +2007,7 @@ typedef struct cmipci_sb_reg { #define CMIPCI_SB_SW_STEREO(xname,lshift,rshift) CMIPCI_DOUBLE(xname, SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, lshift, rshift, 1, 0, 1) #define CMIPCI_SB_SW_MONO(xname,shift) CMIPCI_DOUBLE(xname, SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, shift, shift, 1, 0, 0) -static void cmipci_sb_reg_decode(cmipci_sb_reg_t *r, unsigned long val) +static void cmipci_sb_reg_decode(struct cmipci_sb_reg *r, unsigned long val) { r->left_reg = val & 0xff; r->right_reg = (val >> 8) & 0xff; @@ -1859,9 +2018,10 @@ static void cmipci_sb_reg_decode(cmipci_sb_reg_t *r, unsigned long val) r->mask = (val >> 24) & 0xff; } -static int snd_cmipci_info_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_cmipci_info_volume(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { - cmipci_sb_reg_t reg; + struct cmipci_sb_reg reg; cmipci_sb_reg_decode(®, kcontrol->private_value); uinfo->type = reg.mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; @@ -1871,10 +2031,11 @@ static int snd_cmipci_info_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t return 0; } -static int snd_cmipci_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_cmipci_get_volume(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - cmipci_sb_reg_t reg; + struct cmipci *cm = snd_kcontrol_chip(kcontrol); + struct cmipci_sb_reg reg; int val; cmipci_sb_reg_decode(®, kcontrol->private_value); @@ -1893,10 +2054,11 @@ static int snd_cmipci_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t return 0; } -static int snd_cmipci_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_cmipci_put_volume(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - cmipci_sb_reg_t reg; + struct cmipci *cm = snd_kcontrol_chip(kcontrol); + struct cmipci_sb_reg reg; int change; int left, right, oleft, oright; @@ -1941,7 +2103,8 @@ static int snd_cmipci_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t .private_value = COMPOSE_SB_REG(SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, left_shift, right_shift, 1, 0, 1), \ } -static int snd_cmipci_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) +static int snd_cmipci_info_input_sw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 4; @@ -1950,10 +2113,11 @@ static int snd_cmipci_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info return 0; } -static int snd_cmipci_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_cmipci_get_input_sw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - cmipci_sb_reg_t reg; + struct cmipci *cm = snd_kcontrol_chip(kcontrol); + struct cmipci_sb_reg reg; int val1, val2; cmipci_sb_reg_decode(®, kcontrol->private_value); @@ -1968,10 +2132,11 @@ static int snd_cmipci_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value return 0; } -static int snd_cmipci_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_cmipci_put_input_sw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - cmipci_sb_reg_t reg; + struct cmipci *cm = snd_kcontrol_chip(kcontrol); + struct cmipci_sb_reg reg; int change; int val1, val2, oval1, oval2; @@ -2024,9 +2189,10 @@ static int snd_cmipci_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value .private_value = COMPOSE_SB_REG(reg, reg, shift, shift, mask, 0, 0), \ } -static int snd_cmipci_info_native_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +static int snd_cmipci_info_native_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { - cmipci_sb_reg_t reg; + struct cmipci_sb_reg reg; cmipci_sb_reg_decode(®, kcontrol->private_value); uinfo->type = reg.mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; @@ -2037,10 +2203,11 @@ static int snd_cmipci_info_native_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_i } -static int snd_cmipci_get_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_cmipci_get_native_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - cmipci_sb_reg_t reg; + struct cmipci *cm = snd_kcontrol_chip(kcontrol); + struct cmipci_sb_reg reg; unsigned char oreg, val; cmipci_sb_reg_decode(®, kcontrol->private_value); @@ -2060,10 +2227,11 @@ static int snd_cmipci_get_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_v return 0; } -static int snd_cmipci_put_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol) +static int snd_cmipci_put_native_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); - cmipci_sb_reg_t reg; + struct cmipci *cm = snd_kcontrol_chip(kcontrol); + struct cmipci_sb_reg reg; unsigned char oreg, nreg, val; cmipci_sb_reg_decode(®, kcontrol->private_value); @@ -2089,15 +2257,17 @@ static int snd_cmipci_put_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_v /* * special case - check mixer sensitivity */ -static int snd_cmipci_get_native_mixer_sensitive(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_get_native_mixer_sensitive(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - //cmipci_t *cm = snd_kcontrol_chip(kcontrol); + //struct cmipci *cm = snd_kcontrol_chip(kcontrol); return snd_cmipci_get_native_mixer(kcontrol, ucontrol); } -static int snd_cmipci_put_native_mixer_sensitive(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_put_native_mixer_sensitive(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); + struct cmipci *cm = snd_kcontrol_chip(kcontrol); if (cm->mixer_insensitive) { /* ignored */ return 0; @@ -2106,7 +2276,7 @@ static int snd_cmipci_put_native_mixer_sensitive(snd_kcontrol_t *kcontrol, snd_c } -static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = { +static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = { CMIPCI_SB_VOL_STEREO("Master Playback Volume", SB_DSP4_MASTER_DEV, 3, 31), CMIPCI_MIXER_SW_MONO("3D Control - Switch", CM_REG_MIXER1, CM_X3DEN_SHIFT, 0), CMIPCI_SB_VOL_STEREO("PCM Playback Volume", SB_DSP4_PCM_DEV, 3, 31), @@ -2132,7 +2302,7 @@ static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = { CMIPCI_SB_VOL_MONO("Mic Playback Volume", SB_DSP4_MIC_DEV, 3, 31), CMIPCI_SB_SW_MONO("Mic Playback Switch", 0), CMIPCI_DOUBLE("Mic Capture Switch", SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, 0, 0, 1, 0, 0), - CMIPCI_SB_VOL_MONO("PC Speaker Playback Volume", SB_DSP4_SPEAKER_DEV, 6, 3), + CMIPCI_SB_VOL_MONO("Beep Playback Volume", SB_DSP4_SPEAKER_DEV, 6, 3), CMIPCI_MIXER_VOL_STEREO("Aux Playback Volume", CM_REG_AUX_VOL, 4, 0, 15), CMIPCI_MIXER_SW_STEREO("Aux Playback Switch", CM_REG_MIXER2, CM_VAUXLM_SHIFT, CM_VAUXRM_SHIFT, 0), CMIPCI_MIXER_SW_STEREO("Aux Capture Switch", CM_REG_MIXER2, CM_RAUXLEN_SHIFT, CM_RAUXREN_SHIFT, 0), @@ -2140,7 +2310,7 @@ static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = { CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7), CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0), - CMIPCI_DOUBLE("PC Speaker Playnack Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), + CMIPCI_DOUBLE("Beep Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0), }; @@ -2148,27 +2318,24 @@ static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = { * other switches */ -typedef struct snd_cmipci_switch_args { +struct cmipci_switch_args { int reg; /* register index */ unsigned int mask; /* mask bits */ unsigned int mask_on; /* mask bits to turn on */ unsigned int is_byte: 1; /* byte access? */ - unsigned int ac3_sensitive: 1; /* access forbidden during non-audio operation? */ -} snd_cmipci_switch_args_t; + unsigned int ac3_sensitive: 1; /* access forbidden during + * non-audio operation? + */ +}; -static int snd_cmipci_uswitch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} +#define snd_cmipci_uswitch_info snd_ctl_boolean_mono_info -static int _snd_cmipci_uswitch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, snd_cmipci_switch_args_t *args) +static int _snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, + struct cmipci_switch_args *args) { unsigned int val; - cmipci_t *cm = snd_kcontrol_chip(kcontrol); + struct cmipci *cm = snd_kcontrol_chip(kcontrol); spin_lock_irq(&cm->reg_lock); if (args->ac3_sensitive && cm->mixer_insensitive) { @@ -2185,18 +2352,23 @@ static int _snd_cmipci_uswitch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ return 0; } -static int snd_cmipci_uswitch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - snd_cmipci_switch_args_t *args = (snd_cmipci_switch_args_t*)kcontrol->private_value; - snd_assert(args != NULL, return -EINVAL); + struct cmipci_switch_args *args; + args = (struct cmipci_switch_args *)kcontrol->private_value; + if (snd_BUG_ON(!args)) + return -EINVAL; return _snd_cmipci_uswitch_get(kcontrol, ucontrol, args); } -static int _snd_cmipci_uswitch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, snd_cmipci_switch_args_t *args) +static int _snd_cmipci_uswitch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, + struct cmipci_switch_args *args) { unsigned int val; int change; - cmipci_t *cm = snd_kcontrol_chip(kcontrol); + struct cmipci *cm = snd_kcontrol_chip(kcontrol); spin_lock_irq(&cm->reg_lock); if (args->ac3_sensitive && cm->mixer_insensitive) { @@ -2208,7 +2380,8 @@ static int _snd_cmipci_uswitch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ val = inb(cm->iobase + args->reg); else val = snd_cmipci_read(cm, args->reg); - change = (val & args->mask) != (ucontrol->value.integer.value[0] ? args->mask : 0); + change = (val & args->mask) != (ucontrol->value.integer.value[0] ? + args->mask_on : (args->mask & ~args->mask_on)); if (change) { val &= ~args->mask; if (ucontrol->value.integer.value[0]) @@ -2224,15 +2397,18 @@ static int _snd_cmipci_uswitch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ return change; } -static int snd_cmipci_uswitch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_uswitch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - snd_cmipci_switch_args_t *args = (snd_cmipci_switch_args_t*)kcontrol->private_value; - snd_assert(args != NULL, return -EINVAL); + struct cmipci_switch_args *args; + args = (struct cmipci_switch_args *)kcontrol->private_value; + if (snd_BUG_ON(!args)) + return -EINVAL; return _snd_cmipci_uswitch_put(kcontrol, ucontrol, args); } #define DEFINE_SWITCH_ARG(sname, xreg, xmask, xmask_on, xis_byte, xac3) \ -static snd_cmipci_switch_args_t cmipci_switch_arg_##sname = { \ +static struct cmipci_switch_args cmipci_switch_arg_##sname = { \ .reg = xreg, \ .mask = xmask, \ .mask_on = xmask_on, \ @@ -2267,8 +2443,8 @@ DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* rever DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0); #endif DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0); -// DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0); -// DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0); +// DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_REAR2LIN, 1, 0); +// DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_CENTR2LIN|CM_BASE2LIN, 0, 0); // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */ DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0); @@ -2289,7 +2465,8 @@ DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0 * callbacks for spdif output switch * needs toggle two registers.. */ -static int snd_cmipci_spdout_enable_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_spdout_enable_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { int changed; changed = _snd_cmipci_uswitch_get(kcontrol, ucontrol, &cmipci_switch_arg_spdif_enable); @@ -2297,9 +2474,10 @@ static int snd_cmipci_spdout_enable_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_v return changed; } -static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_spdout_enable_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *chip = snd_kcontrol_chip(kcontrol); + struct cmipci *chip = snd_kcontrol_chip(kcontrol); int changed; changed = _snd_cmipci_uswitch_put(kcontrol, ucontrol, &cmipci_switch_arg_spdif_enable); changed |= _snd_cmipci_uswitch_put(kcontrol, ucontrol, &cmipci_switch_arg_spdo2dac); @@ -2317,10 +2495,10 @@ static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v } -static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol, - snd_ctl_elem_info_t *uinfo) +static int snd_cmipci_line_in_mode_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); + struct cmipci *cm = snd_kcontrol_chip(kcontrol); static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; @@ -2331,24 +2509,24 @@ static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol, return 0; } -static inline unsigned int get_line_in_mode(cmipci_t *cm) +static inline unsigned int get_line_in_mode(struct cmipci *cm) { unsigned int val; if (cm->chip_version >= 39) { val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL); - if (val & CM_LINE_AS_BASS) + if (val & (CM_CENTR2LIN | CM_BASE2LIN)) return 2; } val = snd_cmipci_read_b(cm, CM_REG_MIXER1); - if (val & CM_SPK4) + if (val & CM_REAR2LIN) return 1; return 0; } -static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_line_in_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); + struct cmipci *cm = snd_kcontrol_chip(kcontrol); spin_lock_irq(&cm->reg_lock); ucontrol->value.enumerated.item[0] = get_line_in_mode(cm); @@ -2356,27 +2534,27 @@ static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol, return 0; } -static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_line_in_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); + struct cmipci *cm = snd_kcontrol_chip(kcontrol); int change; spin_lock_irq(&cm->reg_lock); if (ucontrol->value.enumerated.item[0] == 2) - change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); + change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN); else - change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS); + change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CENTR2LIN | CM_BASE2LIN); if (ucontrol->value.enumerated.item[0] == 1) - change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4); + change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN); else - change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4); + change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_REAR2LIN); spin_unlock_irq(&cm->reg_lock); return change; } -static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol, - snd_ctl_elem_info_t *uinfo) +static int snd_cmipci_mic_in_mode_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) { static char *texts[2] = { "Mic-In", "Center/LFE Output" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; @@ -2388,10 +2566,10 @@ static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol, return 0; } -static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_mic_in_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); + struct cmipci *cm = snd_kcontrol_chip(kcontrol); /* same bit as spdi_phase */ spin_lock_irq(&cm->reg_lock); ucontrol->value.enumerated.item[0] = @@ -2400,10 +2578,10 @@ static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol, return 0; } -static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol, - snd_ctl_elem_value_t *ucontrol) +static int snd_cmipci_mic_in_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - cmipci_t *cm = snd_kcontrol_chip(kcontrol); + struct cmipci *cm = snd_kcontrol_chip(kcontrol); int change; spin_lock_irq(&cm->reg_lock); @@ -2416,7 +2594,7 @@ static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol, } /* both for CM8338/8738 */ -static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = { +static struct snd_kcontrol_new snd_cmipci_mixer_switches[] __devinitdata = { DEFINE_MIXER_SWITCH("Four Channel Mode", fourch), { .name = "Line-In Mode", @@ -2428,11 +2606,11 @@ static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = { }; /* for non-multichannel chips */ -static snd_kcontrol_new_t snd_cmipci_nomulti_switch __devinitdata = +static struct snd_kcontrol_new snd_cmipci_nomulti_switch __devinitdata = DEFINE_MIXER_SWITCH("Exchange DAC", exchange_dac); /* only for CM8738 */ -static snd_kcontrol_new_t snd_cmipci_8738_mixer_switches[] __devinitdata = { +static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] __devinitdata = { #if 0 /* controlled in pcm device */ DEFINE_MIXER_SWITCH("IEC958 In Record", spdif_in), DEFINE_MIXER_SWITCH("IEC958 Out", spdif_out), @@ -2454,14 +2632,14 @@ static snd_kcontrol_new_t snd_cmipci_8738_mixer_switches[] __devinitdata = { }; /* only for model 033/037 */ -static snd_kcontrol_new_t snd_cmipci_old_mixer_switches[] __devinitdata = { +static struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] __devinitdata = { DEFINE_MIXER_SWITCH("IEC958 Mix Analog", spdif_dac_out), DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase), DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel1), }; /* only for model 039 or later */ -static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = { +static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] __devinitdata = { DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2), DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2), { @@ -2474,21 +2652,20 @@ static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = { }; /* card control switches */ -static snd_kcontrol_new_t snd_cmipci_control_switches[] __devinitdata = { - // DEFINE_CARD_SWITCH("Joystick", joystick), /* now module option */ - DEFINE_CARD_SWITCH("Modem", modem), -}; +static struct snd_kcontrol_new snd_cmipci_modem_switch __devinitdata = +DEFINE_CARD_SWITCH("Modem", modem); -static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device) +static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device) { - snd_card_t *card; - snd_kcontrol_new_t *sw; - snd_kcontrol_t *kctl; + struct snd_card *card; + struct snd_kcontrol_new *sw; + struct snd_kcontrol *kctl; unsigned int idx; int err; - snd_assert(cm != NULL && cm->card != NULL, return -EINVAL); + if (snd_BUG_ON(!cm || !cm->card)) + return -EINVAL; card = cm->card; @@ -2558,20 +2735,25 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device) } /* card switches */ - sw = snd_cmipci_control_switches; - for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_control_switches); idx++, sw++) { - err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm)); + /* + * newer chips don't have the register bits to force modem link + * detection; the bit that was FLINKON now mutes CH1 + */ + if (cm->chip_version < 39) { + err = snd_ctl_add(cm->card, + snd_ctl_new1(&snd_cmipci_modem_switch, cm)); if (err < 0) return err; } for (idx = 0; idx < CM_SAVED_MIXERS; idx++) { - snd_ctl_elem_id_t id; - snd_kcontrol_t *ctl; - memset(&id, 0, sizeof(id)); - id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - strcpy(id.name, cm_saved_mixer[idx].name); - if ((ctl = snd_ctl_find_id(cm->card, &id)) != NULL) + struct snd_ctl_elem_id elem_id; + struct snd_kcontrol *ctl; + memset(&elem_id, 0, sizeof(elem_id)); + elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + strcpy(elem_id.name, cm_saved_mixer[idx].name); + ctl = snd_ctl_find_id(cm->card, &elem_id); + if (ctl) cm->mixer_res_ctl[idx] = ctl; } @@ -2584,43 +2766,42 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device) */ #ifdef CONFIG_PROC_FS -static void snd_cmipci_proc_read(snd_info_entry_t *entry, - snd_info_buffer_t *buffer) +static void snd_cmipci_proc_read(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) { - cmipci_t *cm = entry->private_data; - int i; + struct cmipci *cm = entry->private_data; + int i, v; - snd_iprintf(buffer, "%s\n\n", cm->card->longname); - for (i = 0; i < 0x40; i++) { - int v = inb(cm->iobase + i); + snd_iprintf(buffer, "%s\n", cm->card->longname); + for (i = 0; i < 0x94; i++) { + if (i == 0x28) + i = 0x90; + v = inb(cm->iobase + i); if (i % 4 == 0) - snd_iprintf(buffer, "%02x: ", i); - snd_iprintf(buffer, "%02x", v); - if (i % 4 == 3) - snd_iprintf(buffer, "\n"); - else - snd_iprintf(buffer, " "); + snd_iprintf(buffer, "\n%02x:", i); + snd_iprintf(buffer, " %02x", v); } + snd_iprintf(buffer, "\n"); } -static void __devinit snd_cmipci_proc_init(cmipci_t *cm) +static void __devinit snd_cmipci_proc_init(struct cmipci *cm) { - snd_info_entry_t *entry; + struct snd_info_entry *entry; if (! snd_card_proc_new(cm->card, "cmipci", &entry)) - snd_info_set_text_ops(entry, cm, 1024, snd_cmipci_proc_read); + snd_info_set_text_ops(entry, cm, snd_cmipci_proc_read); } #else /* !CONFIG_PROC_FS */ -static inline void snd_cmipci_proc_init(cmipci_t *cm) {} +static inline void snd_cmipci_proc_init(struct cmipci *cm) {} #endif -static struct pci_device_id snd_cmipci_ids[] = { - {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_AL, PCI_DEVICE_ID_CMEDIA_CM8738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, +static DEFINE_PCI_DEVICE_TABLE(snd_cmipci_ids) = { + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A), 0}, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B), 0}, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738), 0}, + {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B), 0}, + {PCI_VDEVICE(AL, PCI_DEVICE_ID_CMEDIA_CM8738), 0}, {0,}, }; @@ -2629,7 +2810,7 @@ static struct pci_device_id snd_cmipci_ids[] = { * check chip version and capabilities * driver name is modified according to the chip model */ -static void __devinit query_chip(cmipci_t *cm) +static void __devinit query_chip(struct cmipci *cm) { unsigned int detect; @@ -2638,51 +2819,47 @@ static void __devinit query_chip(cmipci_t *cm) if (! detect) { /* check reg 08h, bit 24-28 */ detect = snd_cmipci_read(cm, CM_REG_CHFORMAT) & CM_CHIP_MASK1; - if (! detect) { + switch (detect) { + case 0: cm->chip_version = 33; - cm->max_channels = 2; if (cm->do_soft_ac3) cm->can_ac3_sw = 1; else cm->can_ac3_hw = 1; - cm->has_dual_dac = 1; - } else { + break; + case CM_CHIP_037: cm->chip_version = 37; - cm->max_channels = 2; cm->can_ac3_hw = 1; - cm->has_dual_dac = 1; + break; + default: + cm->chip_version = 39; + cm->can_ac3_hw = 1; + break; } + cm->max_channels = 2; } else { - /* check reg 0Ch, bit 26 */ - if (detect & CM_CHIP_8768) { - cm->chip_version = 68; - cm->max_channels = 8; - cm->can_ac3_hw = 1; - cm->has_dual_dac = 1; - cm->can_multi_ch = 1; - } else if (detect & CM_CHIP_055) { - cm->chip_version = 55; - cm->max_channels = 6; - cm->can_ac3_hw = 1; - cm->has_dual_dac = 1; - cm->can_multi_ch = 1; - } else if (detect & CM_CHIP_039) { + if (detect & CM_CHIP_039) { cm->chip_version = 39; if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */ cm->max_channels = 6; else cm->max_channels = 4; - cm->can_ac3_hw = 1; - cm->has_dual_dac = 1; - cm->can_multi_ch = 1; + } else if (detect & CM_CHIP_8768) { + cm->chip_version = 68; + cm->max_channels = 8; + cm->can_96k = 1; } else { - printk(KERN_ERR "chip %x version not supported\n", detect); + cm->chip_version = 55; + cm->max_channels = 6; + cm->can_96k = 1; } + cm->can_ac3_hw = 1; + cm->can_multi_ch = 1; } } #ifdef SUPPORT_JOYSTICK -static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev) +static int __devinit snd_cmipci_create_gameport(struct cmipci *cm, int dev) { static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */ struct gameport *gp; @@ -2712,8 +2889,7 @@ static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev) cm->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "cmipci: cannot allocate memory for gameport\n"); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); return -ENOMEM; } gameport_set_name(gp, "C-Media Gameport"); @@ -2729,7 +2905,7 @@ static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev) return 0; } -static void snd_cmipci_free_gameport(cmipci_t *cm) +static void snd_cmipci_free_gameport(struct cmipci *cm) { if (cm->gameport) { struct resource *r = gameport_get_port_data(cm->gameport); @@ -2738,16 +2914,15 @@ static void snd_cmipci_free_gameport(cmipci_t *cm) cm->gameport = NULL; snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN); - release_resource(r); - kfree_nocheck(r); + release_and_free_resource(r); } } #else -static inline int snd_cmipci_create_gameport(cmipci_t *cm, int dev) { return -ENOSYS; } -static inline void snd_cmipci_free_gameport(cmipci_t *cm) { } +static inline int snd_cmipci_create_gameport(struct cmipci *cm, int dev) { return -ENOSYS; } +static inline void snd_cmipci_free_gameport(struct cmipci *cm) { } #endif -static int snd_cmipci_free(cmipci_t *cm) +static int snd_cmipci_free(struct cmipci *cm) { if (cm->irq >= 0) { snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); @@ -2761,9 +2936,7 @@ static int snd_cmipci_free(cmipci_t *cm) /* reset mixer */ snd_cmipci_mixer_write(cm, 0, 0); - synchronize_irq(cm->irq); - - free_irq(cm->irq, (void *)cm); + free_irq(cm->irq, cm); } snd_cmipci_free_gameport(cm); @@ -2773,25 +2946,79 @@ static int snd_cmipci_free(cmipci_t *cm) return 0; } -static int snd_cmipci_dev_free(snd_device_t *device) +static int snd_cmipci_dev_free(struct snd_device *device) { - cmipci_t *cm = device->device_data; + struct cmipci *cm = device->device_data; return snd_cmipci_free(cm); } -static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, - int dev, cmipci_t **rcmipci) +static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port) +{ + long iosynth; + unsigned int val; + struct snd_opl3 *opl3; + int err; + + if (!fm_port) + goto disable_fm; + + if (cm->chip_version >= 39) { + /* first try FM regs in PCI port range */ + iosynth = cm->iobase + CM_REG_FM_PCI; + err = snd_opl3_create(cm->card, iosynth, iosynth + 2, + OPL3_HW_OPL3, 1, &opl3); + } else { + err = -EIO; + } + if (err < 0) { + /* then try legacy ports */ + val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL) & ~CM_FMSEL_MASK; + iosynth = fm_port; + switch (iosynth) { + case 0x3E8: val |= CM_FMSEL_3E8; break; + case 0x3E0: val |= CM_FMSEL_3E0; break; + case 0x3C8: val |= CM_FMSEL_3C8; break; + case 0x388: val |= CM_FMSEL_388; break; + default: + goto disable_fm; + } + snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); + /* enable FM */ + snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); + + if (snd_opl3_create(cm->card, iosynth, iosynth + 2, + OPL3_HW_OPL3, 0, &opl3) < 0) { + printk(KERN_ERR "cmipci: no OPL device at %#lx, " + "skipping...\n", iosynth); + goto disable_fm; + } + } + if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + printk(KERN_ERR "cmipci: cannot create OPL3 hwdep\n"); + return err; + } + return 0; + + disable_fm: + snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_FMSEL_MASK); + snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); + return 0; +} + +static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, + int dev, struct cmipci **rcmipci) { - cmipci_t *cm; + struct cmipci *cm; int err; - static snd_device_ops_t ops = { + static struct snd_device_ops ops = { .dev_free = snd_cmipci_dev_free, }; - unsigned int val = 0; - long iomidi = mpu_port[dev]; - long iosynth = fm_port[dev]; + unsigned int val; + long iomidi = 0; + int integrated_midi = 0; + char modelstr[16]; int pcm_index, pcm_spdif_index; - static struct pci_device_id intel_82437vx[] = { + static DEFINE_PCI_DEVICE_TABLE(intel_82437vx) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX) }, { }, }; @@ -2801,14 +3028,14 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, if ((err = pci_enable_device(pci)) < 0) return err; - cm = kcalloc(1, sizeof(*cm), GFP_KERNEL); + cm = kzalloc(sizeof(*cm), GFP_KERNEL); if (cm == NULL) { pci_disable_device(pci); return -ENOMEM; } spin_lock_init(&cm->reg_lock); - init_MUTEX(&cm->open_mutex); + mutex_init(&cm->open_mutex); cm->device = pci->device; cm->card = card; cm->pci = pci; @@ -2824,8 +3051,9 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, } cm->iobase = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_cmipci_interrupt, SA_INTERRUPT|SA_SHIRQ, card->driver, (void *)cm)) { - snd_printk("unable to grab IRQ %d\n", pci->irq); + if (request_irq(pci->irq, snd_cmipci_interrupt, + IRQF_SHARED, card->driver, cm)) { + snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_cmipci_free(cm); return -EBUSY; } @@ -2861,6 +3089,8 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, #endif /* initialize codec registers */ + snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_RESET); + snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_RESET); snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); /* disable ints */ snd_cmipci_ch_reset(cm, CM_CH_PLAY); snd_cmipci_ch_reset(cm, CM_CH_CAPT); @@ -2874,6 +3104,10 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, #else snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC); #endif + if (cm->chip_version) { + snd_cmipci_write_b(cm, CM_REG_EXT_MISC, 0x20); /* magic */ + snd_cmipci_write_b(cm, CM_REG_EXT_MISC + 1, 0x09); /* more magic */ + } /* Set Bus Master Request */ snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_BREQ); @@ -2888,56 +3122,82 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, break; } + if (cm->chip_version < 68) { + val = pci->device < 0x110 ? 8338 : 8738; + } else { + switch (snd_cmipci_read_b(cm, CM_REG_INT_HLDCLR + 3) & 0x03) { + case 0: + val = 8769; + break; + case 2: + val = 8762; + break; + default: + switch ((pci->subsystem_vendor << 16) | + pci->subsystem_device) { + case 0x13f69761: + case 0x584d3741: + case 0x584d3751: + case 0x584d3761: + case 0x584d3771: + case 0x72848384: + val = 8770; + break; + default: + val = 8768; + break; + } + } + } + sprintf(card->shortname, "C-Media CMI%d", val); + if (cm->chip_version < 68) + sprintf(modelstr, " (model %d)", cm->chip_version); + else + modelstr[0] = '\0'; + sprintf(card->longname, "%s%s at %#lx, irq %i", + card->shortname, modelstr, cm->iobase, cm->irq); + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, cm, &ops)) < 0) { snd_cmipci_free(cm); return err; } - /* set MPU address */ - switch (iomidi) { - case 0x320: val = CM_VMPU_320; break; - case 0x310: val = CM_VMPU_310; break; - case 0x300: val = CM_VMPU_300; break; - case 0x330: val = CM_VMPU_330; break; - default: - iomidi = 0; break; - } - if (iomidi > 0) { - snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); - /* enable UART */ - snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); - } - - /* set FM address */ - val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL) & ~CM_FMSEL_MASK; - switch (iosynth) { - case 0x3E8: val |= CM_FMSEL_3E8; break; - case 0x3E0: val |= CM_FMSEL_3E0; break; - case 0x3C8: val |= CM_FMSEL_3C8; break; - case 0x388: val |= CM_FMSEL_388; break; - default: - iosynth = 0; break; + if (cm->chip_version >= 39) { + val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1); + if (val != 0x00 && val != 0xff) { + iomidi = cm->iobase + CM_REG_MPU_PCI; + integrated_midi = 1; + } } - if (iosynth > 0) { - snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); - /* enable FM */ - snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); - - if (snd_opl3_create(card, iosynth, iosynth + 2, - OPL3_HW_OPL3, 0, &cm->opl3) < 0) { - printk(KERN_ERR "cmipci: no OPL device at 0x%lx, skipping...\n", iosynth); - iosynth = 0; - } else { - if ((err = snd_opl3_hwdep_new(cm->opl3, 0, 1, &cm->opl3hwdep)) < 0) { - printk(KERN_ERR "cmipci: cannot create OPL3 hwdep\n"); - return err; + if (!integrated_midi) { + val = 0; + iomidi = mpu_port[dev]; + switch (iomidi) { + case 0x320: val = CM_VMPU_320; break; + case 0x310: val = CM_VMPU_310; break; + case 0x300: val = CM_VMPU_300; break; + case 0x330: val = CM_VMPU_330; break; + default: + iomidi = 0; break; + } + if (iomidi > 0) { + snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val); + /* enable UART */ + snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_UART_EN); + if (inb(iomidi + 1) == 0xff) { + snd_printk(KERN_ERR "cannot enable MPU-401 port" + " at %#lx\n", iomidi); + snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, + CM_UART_EN); + iomidi = 0; } } } - if (! iosynth) { - /* disable FM */ - snd_cmipci_write(cm, CM_REG_LEGACY_CTRL, val & ~CM_FMSEL_MASK); - snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN); + + if (cm->chip_version < 68) { + err = snd_cmipci_create_fm(cm, fm_port[dev]); + if (err < 0) + return err; } /* reset mixer */ @@ -2950,11 +3210,9 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, if ((err = snd_cmipci_pcm_new(cm, pcm_index)) < 0) return err; pcm_index++; - if (cm->has_dual_dac) { - if ((err = snd_cmipci_pcm2_new(cm, pcm_index)) < 0) - return err; - pcm_index++; - } + if ((err = snd_cmipci_pcm2_new(cm, pcm_index)) < 0) + return err; + pcm_index++; if (cm->can_ac3_hw || cm->can_ac3_sw) { pcm_spdif_index = pcm_index; if ((err = snd_cmipci_pcm_spdif_new(cm, pcm_index)) < 0) @@ -2967,7 +3225,9 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci, if (iomidi > 0) { if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, - iomidi, 0, + iomidi, + (integrated_midi ? + MPU401_INFO_INTEGRATED : 0), cm->irq, 0, &cm->rmidi)) < 0) { printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi); } @@ -3001,8 +3261,8 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { static int dev; - snd_card_t *card; - cmipci_t *cm; + struct snd_card *card; + struct cmipci *cm; int err; if (dev >= SNDRV_CARDS) @@ -3012,9 +3272,9 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci, return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + if (err < 0) + return err; switch (pci->device) { case PCI_DEVICE_ID_CMEDIA_CM8738: @@ -3034,15 +3294,7 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci, snd_card_free(card); return err; } - - sprintf(card->shortname, "C-Media PCI %s", card->driver); - sprintf(card->longname, "%s (model %d) at 0x%lx, irq %i", - card->shortname, - cm->chip_version, - cm->iobase, - cm->irq); - - //snd_printd("%s is detected\n", card->longname); + card->private_data = cm; if ((err = snd_card_register(card)) < 0) { snd_card_free(card); @@ -3061,11 +3313,98 @@ static void __devexit snd_cmipci_remove(struct pci_dev *pci) } +#ifdef CONFIG_PM +/* + * power management + */ +static unsigned char saved_regs[] = { + CM_REG_FUNCTRL1, CM_REG_CHFORMAT, CM_REG_LEGACY_CTRL, CM_REG_MISC_CTRL, + CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_MIXER3, CM_REG_PLL, + CM_REG_CH0_FRAME1, CM_REG_CH0_FRAME2, + CM_REG_CH1_FRAME1, CM_REG_CH1_FRAME2, CM_REG_EXT_MISC, + CM_REG_INT_STATUS, CM_REG_INT_HLDCLR, CM_REG_FUNCTRL0, +}; + +static unsigned char saved_mixers[] = { + SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1, + SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1, + SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1, + SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1, + SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1, + SB_DSP4_MIC_DEV, SB_DSP4_SPEAKER_DEV, + CM_REG_EXTENT_IND, SB_DSP4_OUTPUT_SW, + SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, +}; + +static int snd_cmipci_suspend(struct pci_dev *pci, pm_message_t state) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct cmipci *cm = card->private_data; + int i; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + + snd_pcm_suspend_all(cm->pcm); + snd_pcm_suspend_all(cm->pcm2); + snd_pcm_suspend_all(cm->pcm_spdif); + + /* save registers */ + for (i = 0; i < ARRAY_SIZE(saved_regs); i++) + cm->saved_regs[i] = snd_cmipci_read(cm, saved_regs[i]); + for (i = 0; i < ARRAY_SIZE(saved_mixers); i++) + cm->saved_mixers[i] = snd_cmipci_mixer_read(cm, saved_mixers[i]); + + /* disable ints */ + snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); + + pci_disable_device(pci); + pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); + return 0; +} + +static int snd_cmipci_resume(struct pci_dev *pci) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct cmipci *cm = card->private_data; + int i; + + pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + if (pci_enable_device(pci) < 0) { + printk(KERN_ERR "cmipci: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(card); + return -EIO; + } + pci_set_master(pci); + + /* reset / initialize to a sane state */ + snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0); + snd_cmipci_ch_reset(cm, CM_CH_PLAY); + snd_cmipci_ch_reset(cm, CM_CH_CAPT); + snd_cmipci_mixer_write(cm, 0, 0); + + /* restore registers */ + for (i = 0; i < ARRAY_SIZE(saved_regs); i++) + snd_cmipci_write(cm, saved_regs[i], cm->saved_regs[i]); + for (i = 0; i < ARRAY_SIZE(saved_mixers); i++) + snd_cmipci_mixer_write(cm, saved_mixers[i], cm->saved_mixers[i]); + + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + return 0; +} +#endif /* CONFIG_PM */ + static struct pci_driver driver = { .name = "C-Media PCI", .id_table = snd_cmipci_ids, .probe = snd_cmipci_probe, .remove = __devexit_p(snd_cmipci_remove), +#ifdef CONFIG_PM + .suspend = snd_cmipci_suspend, + .resume = snd_cmipci_resume, +#endif }; static int __init alsa_card_cmipci_init(void)