Newer
Older
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Driver for C-Media CMI8338 and 8738 PCI soundcards.
* Copyright (c) 2000 by Takashi Iwai <tiwai@suse.de>
*/
/* Does not work. Warning may block system in capture mode */
/* #define USE_VAR48KRATE */
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/rawmidi.h>
#include <sound/mpu401.h>
#include <sound/opl3.h>
#include <sound/sb.h>
#include <sound/asoundef.h>
#include <sound/initval.h>
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("C-Media CMI8x38 PCI");
MODULE_LICENSE("GPL");
#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK 1
#endif
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
static long fm_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1};
static bool soft_ac3[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1};
#ifdef SUPPORT_JOYSTICK
static int joystick_port[SNDRV_CARDS];
#endif
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for C-Media PCI soundcard.");
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for C-Media PCI soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable C-Media PCI soundcard.");
module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
module_param_hw_array(fm_port, long, ioport, NULL, 0444);
MODULE_PARM_DESC(fm_port, "FM port.");
module_param_array(soft_ac3, bool, NULL, 0444);
MODULE_PARM_DESC(soft_ac3, "Software-conversion of raw SPDIF packets (model 033 only).");
module_param_hw_array(joystick_port, int, ioport, NULL, 0444);
MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#endif
/*
* CM8x38 registers definition
*/
#define CM_REG_FUNCTRL0 0x00
#define CM_RST_CH1 0x00080000
#define CM_RST_CH0 0x00040000
#define CM_CHEN1 0x00020000 /* ch1: enable */
#define CM_CHEN0 0x00010000 /* ch0: enable */
#define CM_PAUSE1 0x00000008 /* ch1: pause */
#define CM_PAUSE0 0x00000004 /* ch0: pause */
#define CM_CHADC1 0x00000002 /* ch1, 0:playback, 1:record */
#define CM_CHADC0 0x00000001 /* ch0, 0:playback, 1:record */
#define CM_REG_FUNCTRL1 0x04
#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/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 /* 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_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 */ /* ??? */
#define CM_ADCBITLEN_MASK 0x0000C000
#define CM_ADCBITLEN_16 0x00000000
#define CM_ADCBITLEN_15 0x00004000
#define CM_ADCBITLEN_14 0x00008000
#define CM_ADCBITLEN_13 0x0000C000
#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_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_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 /* bit 3: 16 bits, bit 2: stereo */
#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_UNKNOWN_INT_EN 0x00080000 /* ? */
#define CM_TDMA_INT_EN 0x00040000
#define CM_CH1_INT_EN 0x00020000
#define CM_CH0_INT_EN 0x00010000
#define CM_REG_INT_STATUS 0x10
#define CM_INTR 0x80000000
#define CM_VCO 0x08000000 /* Voice Control? CMI8738 */
#define CM_MCBINT 0x04000000 /* Master Control Block abort cond.? */
#define CM_UARTINT 0x00010000
#define CM_LTDMAINT 0x00008000
#define CM_HTDMAINT 0x00004000
#define CM_XDO46 0x00000080 /* Modell 033? Direct programming EEPROM (read data register) */
#define CM_LHBTOG 0x00000040 /* High/Low status from DMA ctrl register */
#define CM_LEG_HDMA 0x00000020 /* Legacy is in High DMA channel */
#define CM_LEG_STEREO 0x00000010 /* Legacy is in Stereo mode */
#define CM_CH1BUSY 0x00000008
#define CM_CH0BUSY 0x00000004
#define CM_CHINT1 0x00000002
#define CM_CHINT0 0x00000001
#define CM_REG_LEGACY_CTRL 0x14
#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
#define CM_VSBSEL_260 0x08000000
#define CM_VSBSEL_280 0x0C000000
#define CM_FMSEL_MASK 0x03000000 /* FM OPL3 base address */
#define CM_FMSEL_388 0x00000000
#define CM_FMSEL_3C8 0x01000000
#define CM_FMSEL_3E0 0x02000000
#define CM_FMSEL_3E8 0x03000000
#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_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_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_PWD 0x80000000 /* power down */
#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 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-OUT -> int. IN */
#define CM_FM_EN 0x00080000 /* enable legacy FM */
#define CM_AC3EN2 0x00040000 /* enable AC3: model 039 */
#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 /* 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 /* 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 */
#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
#define CM_REFFREQ_XIN (315*1000*1000)/22 /* 14.31818 Mhz reference clock frequency pin XIN */
#define CM_ADCMULT_XIN 512 /* Guessed (487 best for 44.1kHz, not for 88/176kHz) */
#define CM_TOLERANCE_RATE 0.001 /* Tolerance sample rate pitch (1000ppm) */
#define CM_MAXIMUM_RATE 80000000 /* Note more than 80MHz */
#define CM_REG_MIXER1 0x24
#define CM_FMMUTE 0x80 /* mute FM */
#define CM_FMMUTE_SHIFT 7
#define CM_WSMUTE 0x40 /* mute PCM */
#define CM_WSMUTE_SHIFT 6
#define CM_REAR2LIN 0x20 /* lin-in -> rear line out */
#define CM_REAR2LIN_SHIFT 5
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
#define CM_REAR2FRONT 0x10 /* exchange rear/front */
#define CM_REAR2FRONT_SHIFT 4
#define CM_WAVEINL 0x08 /* digital wave rec. left chan */
#define CM_WAVEINL_SHIFT 3
#define CM_WAVEINR 0x04 /* digical wave rec. right */
#define CM_WAVEINR_SHIFT 2
#define CM_X3DEN 0x02 /* 3D surround enable */
#define CM_X3DEN_SHIFT 1
#define CM_CDPLAY 0x01 /* enable SPDIF/IN PCM -> DAC */
#define CM_CDPLAY_SHIFT 0
#define CM_REG_MIXER2 0x25
#define CM_RAUXREN 0x80 /* AUX right capture */
#define CM_RAUXREN_SHIFT 7
#define CM_RAUXLEN 0x40 /* AUX left capture */
#define CM_RAUXLEN_SHIFT 6
#define CM_VAUXRM 0x20 /* AUX right mute */
#define CM_VAUXRM_SHIFT 5
#define CM_VAUXLM 0x10 /* AUX left mute */
#define CM_VAUXLM_SHIFT 4
#define CM_VADMIC_MASK 0x0e /* mic gain level (0-3) << 1 */
#define CM_VADMIC_SHIFT 1
#define CM_MICGAINZ 0x01 /* mic boost */
#define CM_MICGAINZ_SHIFT 0
#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 /* SB16 DMA auto detect */
#define CM_REG_AC97 0x28 /* hmmm.. do we have ac97 link? */
/*
* For CMI-8338 (0x28 - 0x2b) .. is this valid for CMI-8738
* or identical with AC97 codec?
*/
#define CM_REG_EXTERN_CODEC CM_REG_AC97
/*
* MPU401 pci port index address 0x40 - 0x4f (CMI-8738 spec ver. 0.6)
*/
#define CM_REG_MPU_PCI 0x40
/*
* FM pci port index address 0x50 - 0x5f (CMI-8738 spec ver. 0.6)
*/
#define CM_REG_FM_PCI 0x50
/*
*/
#define CM_REG_EXTENT_IND 0xf0
#define CM_VPHONE_MASK 0xe0 /* Phone volume control (0-3) << 5 */
#define CM_VPHONE_SHIFT 5
#define CM_VPHOM 0x10 /* Phone mute control */
#define CM_VSPKM 0x08 /* Speaker mute control, default high */
#define CM_RLOOPREN 0x04 /* Rec. R-channel enable */
#define CM_RLOOPLEN 0x02 /* Rec. L-channel enable */
#define CM_VADMIC3 0x01 /* Mic record boost */
/*
* CMI-8338 spec ver 0.5 (this is not valid for CMI-8738):
* the 8 registers 0xf8 - 0xff are used for programming m/n counter by the PLL
* unit (readonly?).
*/
#define CM_REG_PLL 0xf8
/*
* extended registers
*/
#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_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 /* ? */
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
/*
* size of i/o region
*/
#define CM_EXTENT_CODEC 0x100
#define CM_EXTENT_MIDI 0x2
#define CM_EXTENT_SYNTH 0x4
/*
* channels for playback / capture
*/
#define CM_CH_PLAY 0
#define CM_CH_CAPT 1
/*
* flags to check device open/close
*/
#define CM_OPEN_NONE 0
#define CM_OPEN_CH_MASK 0x01
#define CM_OPEN_DAC 0x10
#define CM_OPEN_ADC 0x20
#define CM_OPEN_SPDIF 0x40
#define CM_OPEN_MCHAN 0x80
#define CM_OPEN_PLAYBACK (CM_CH_PLAY | CM_OPEN_DAC)
#define CM_OPEN_PLAYBACK2 (CM_CH_CAPT | CM_OPEN_DAC)
#define CM_OPEN_PLAYBACK_MULTI (CM_CH_PLAY | CM_OPEN_DAC | CM_OPEN_MCHAN)
#define CM_OPEN_CAPTURE (CM_CH_CAPT | CM_OPEN_ADC)
#define CM_OPEN_SPDIF_PLAYBACK (CM_CH_PLAY | CM_OPEN_DAC | CM_OPEN_SPDIF)
#define CM_OPEN_SPDIF_CAPTURE (CM_CH_CAPT | CM_OPEN_ADC | CM_OPEN_SPDIF)
#if CM_CH_PLAY == 1
#define CM_PLAYBACK_SRATE_176K CM_CH1_SRATE_176K
#define CM_PLAYBACK_SPDF CM_SPDF_1
#define CM_CAPTURE_SPDF CM_SPDF_0
#else
#define CM_PLAYBACK_SRATE_176K CM_CH0_SRATE_176K
#define CM_PLAYBACK_SPDF CM_SPDF_0
#define CM_CAPTURE_SPDF CM_SPDF_1
#endif
/*
* driver data
*/
struct cmipci_pcm {
struct snd_pcm_substream *substream;
u8 running; /* dac/adc running? */
u8 fmt; /* format bits */
u8 is_dac;
unsigned int shift;
unsigned int ch; /* channel (0/1) */
unsigned int offset; /* physical address of the buffer */
};
/* mixer elements toggled/resumed during ac3 playback */
struct cmipci_mixer_auto_switches {
const char *name; /* switch to toggle */
int toggle_on; /* value to change when ac3 mode */
};
static const struct cmipci_mixer_auto_switches cm_saved_mixer[] = {
{"PCM Playback Switch", 0},
{"IEC958 Output Switch", 1},
{"IEC958 Mix Analog", 0},
// {"IEC958 Out To DAC", 1}, // no longer used
{"IEC958 Loop", 0},
};
#define CM_SAVED_MIXERS ARRAY_SIZE(cm_saved_mixer)
struct cmipci {
struct snd_card *card;
struct pci_dev *pci;
unsigned int device; /* device ID */
int irq;
unsigned long iobase;
unsigned int ctrl; /* FUNCTRL0 current value */
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 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? */
unsigned int spdif_playback_enabled: 1; /* spdif switch enabled? */
int spdif_counter; /* for software AC3 */
unsigned int dig_status;
unsigned int dig_pcm_status;
struct snd_pcm_hardware *hw_info[3]; /* for playbacks */
struct snd_kcontrol *mixer_res_ctl[CM_SAVED_MIXERS];
struct cmipci_pcm channel[2]; /* ch0 - DAC, ch1 - ADC or 2nd DAC */
#ifdef SUPPORT_JOYSTICK
struct gameport *gameport;
#endif
spinlock_t reg_lock;
unsigned int saved_regs[0x20];
unsigned char saved_mixers[0x20];
#endif
};
/* read/write operations for dword register */
static inline void snd_cmipci_write(struct cmipci *cm, unsigned int cmd, unsigned int data)
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(struct cmipci *cm, unsigned int cmd, unsigned short data)
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(struct cmipci *cm, unsigned int cmd, unsigned char data)
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(struct cmipci *cm, unsigned int cmd, unsigned int flag)
unsigned int val, oval;
val = oval = inl(cm->iobase + cmd);
if (val == oval)
return 0;
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);
if (val == oval)
return 0;
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);
if (val == oval)
return 0;
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);
if (val == oval)
return 0;
}
/*
* PCM interface
*/
/*
* calculate frequency
*/
static const unsigned int rates[] = { 5512, 11025, 22050, 44100, 8000, 16000, 32000, 48000 };
static unsigned int snd_cmipci_rate_freq(unsigned int rate)
{
unsigned int i;
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
for (i = 0; i < ARRAY_SIZE(rates); i++) {
if (rates[i] == rate)
return i;
}
snd_BUG();
return 0;
}
#ifdef USE_VAR48KRATE
/*
* Determine PLL values for frequency setup, maybe the CMI8338 (CMI8738???)
* does it this way .. maybe not. Never get any information from C-Media about
* that <werner@suse.de>.
*/
static int snd_cmipci_pll_rmn(unsigned int rate, unsigned int adcmult, int *r, int *m, int *n)
{
unsigned int delta, tolerance;
int xm, xn, xr;
for (*r = 0; rate < CM_MAXIMUM_RATE/adcmult; *r += (1<<5))
rate <<= 1;
*n = -1;
if (*r > 0xff)
goto out;
tolerance = rate*CM_TOLERANCE_RATE;
for (xn = (1+2); xn < (0x1f+2); xn++) {
for (xm = (1+2); xm < (0xff+2); xm++) {
xr = ((CM_REFFREQ_XIN/adcmult) * xm) / xn;
if (xr < rate)
delta = rate - xr;
else
delta = xr - rate;
/*
* If we found one, remember this,
* and try to find a closer one
*/
if (delta < tolerance) {
tolerance = delta;
*m = xm - 2;
*n = xn - 2;
}
}
}
out:
return (*n > -1);
}
/*
* Program pll register bits, I assume that the 8 registers 0xf8 up to 0xff
* are mapped onto the 8 ADC/DAC sampling frequency which can be chosen
* at the register CM_REG_FUNCTRL1 (0x04).
* Problem: other ways are also possible (any information about that?)
*/
static void snd_cmipci_set_pll(struct cmipci *cm, unsigned int rate, unsigned int slot)
{
unsigned int reg = CM_REG_PLL + slot;
/*
* Guess that this programs at reg. 0x04 the pos 15:13/12:10
*/
/* FIXME: Init (Do we've to set an other register first before programming?) */
/* FIXME: Is this correct? Or shouldn't the m/n/r values be used for that? */
snd_cmipci_write_b(cm, reg, rate>>8);
snd_cmipci_write_b(cm, reg, rate&0xff);
/* FIXME: Setup (Do we've to set an other register first to enable this?) */
}
#endif /* USE_VAR48KRATE */
static int snd_cmipci_playback2_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
struct cmipci *cm = snd_pcm_substream_chip(substream);
return -EBUSY;
}
/* reserve the channel A */
cm->opened[CM_CH_PLAY] = CM_OPEN_PLAYBACK_MULTI;
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);
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset);
udelay(10);
}
/*
*/
static const unsigned int hw_channels[] = {1, 2, 4, 6, 8};
static const struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = {
.count = 3,
.list = hw_channels,
.mask = 0,
};
static const struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = {
static const struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = {
static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int channels)
if (!cm->can_multi_ch || !rec->ch)
return -EINVAL;
if (rec->fmt != 0x03) /* stereo 16bit only */
return -EINVAL;
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);
snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG);
snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC);
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);
} else {
snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C);
snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
}
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;
}
/*
* prepare playback/capture channel
* channel to be used must have been set in rec->ch.
*/
static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec,
struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
rec->fmt = 0;
rec->shift = 0;
if (snd_pcm_format_width(runtime->format) >= 16) {
rec->fmt |= 0x02;
if (snd_pcm_format_width(runtime->format) > 16)
rec->shift++; /* 24/32bit */
}
if (runtime->channels > 1)
rec->fmt |= 0x01;
if (rec->is_dac && set_dac_channels(cm, rec, runtime->channels) < 0) {
dev_dbg(cm->card->dev, "cannot set dac channels\n");
return -EINVAL;
}
rec->offset = runtime->dma_addr;
/* buffer and period sizes in frame */
rec->dma_size = runtime->buffer_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;
period_size = (period_size * runtime->channels) / 2;
}
spin_lock_irq(&cm->reg_lock);
/* set buffer address */
reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1;
snd_cmipci_write(cm, reg, rec->offset);
/* 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, period_size - 1);
/* set adc/dac flag */
val = rec->ch ? CM_CHADC1 : CM_CHADC0;
if (rec->is_dac)
cm->ctrl &= ~val;
else
cm->ctrl |= val;
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl);
/* dev_dbg(cm->card->dev, "functrl0 = %08x\n", cm->ctrl); */
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_DSFC_MASK;
val |= (freq << CM_DSFC_SHIFT) & CM_DSFC_MASK;
} else {
val &= ~CM_ASFC_MASK;
val |= (freq << CM_ASFC_SHIFT) & CM_ASFC_MASK;
dev_dbg(cm->card->dev, "functrl1 = %08x\n", val);
/* set format */
val = snd_cmipci_read(cm, CM_REG_CHFORMAT);
if (rec->ch) {
val &= ~CM_CH1FMT_MASK;
val |= rec->fmt << CM_CH1FMT_SHIFT;
} else {
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);
dev_dbg(cm->card->dev, "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);
return 0;
}
/*
* PCM trigger/stop
*/
static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec,
{
unsigned int inthld, chen, reset, pause;
int result = 0;
inthld = CM_CH0_INT_EN << rec->ch;
chen = CM_CHEN0 << rec->ch;
reset = CM_RST_CH0 << rec->ch;
pause = CM_PAUSE0 << rec->ch;
spin_lock(&cm->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
rec->running = 1;
/* set interrupt */
snd_cmipci_set_bit(cm, CM_REG_INT_HLDCLR, inthld);
cm->ctrl |= chen;
/* enable channel */
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl);
dev_dbg(cm->card->dev, "functrl0 = %08x\n", cm->ctrl);
break;
case SNDRV_PCM_TRIGGER_STOP:
rec->running = 0;
/* disable interrupt */
snd_cmipci_clear_bit(cm, CM_REG_INT_HLDCLR, inthld);
/* reset */
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;
cm->ctrl |= pause;
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl);
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
cm->ctrl &= ~pause;
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl);
break;
default:
result = -EINVAL;
break;
}
spin_unlock(&cm->reg_lock);
return result;
}
/*
* return the current pointer
*/
static snd_pcm_uframes_t snd_cmipci_pcm_pointer(struct cmipci *cm, struct cmipci_pcm *rec,
struct snd_pcm_substream *substream)
unsigned int reg, rem, tries;
if (!rec->running)
return 0;
#if 1 // this seems better..
reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2;
for (tries = 0; tries < 3; tries++) {
rem = snd_cmipci_read_w(cm, reg);
if (rem < rec->dma_size)
goto ok;
}
dev_err(cm->card->dev, "invalid PCM pointer: %#x\n", rem);
return SNDRV_PCM_POS_XRUN;
ok:
ptr = (rec->dma_size - (rem + 1)) >> rec->shift;
#else
reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1;
ptr = snd_cmipci_read(cm, reg) - rec->offset;
ptr = bytes_to_frames(substream->runtime, ptr);
#endif
if (substream->runtime->channels > 2)
ptr = (ptr * 2) / substream->runtime->channels;
return ptr;
}
/*
* playback
*/
static int snd_cmipci_playback_trigger(struct snd_pcm_substream *substream,
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(struct snd_pcm_substream *substream)
struct cmipci *cm = snd_pcm_substream_chip(substream);
return snd_cmipci_pcm_pointer(cm, &cm->channel[CM_CH_PLAY], substream);
}
/*
* capture
*/
static int snd_cmipci_capture_trigger(struct snd_pcm_substream *substream,
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(struct snd_pcm_substream *substream)
struct cmipci *cm = snd_pcm_substream_chip(substream);
return snd_cmipci_pcm_pointer(cm, &cm->channel[CM_CH_CAPT], substream);
}
/*
* hw preparation for spdif
*/
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(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
struct cmipci *chip = snd_kcontrol_chip(kcontrol);
int i;
spin_lock_irq(&chip->reg_lock);
for (i = 0; i < 4; i++)
ucontrol->value.iec958.status[i] = (chip->dig_status >> (i * 8)) & 0xff;
spin_unlock_irq(&chip->reg_lock);
return 0;
}