Loading sound/pci/ca0106/ca0106.h +57 −4 Original line number Diff line number Diff line /* * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit * Version: 0.0.20 * Version: 0.0.21 * * FEATURES currently supported: * See ca0106_main.c for features. Loading Loading @@ -45,6 +45,8 @@ * Added I2C and SPI registers. Filled in interrupt enable. * 0.0.20 * Added GPIO info for SB Live 24bit. * 0.0.21 * Implement support for Line-in capture on SB Live 24bit. * * * This code was initally based on code from ALSA's emu10k1x.c which is: Loading Loading @@ -475,9 +477,56 @@ /* Causes interrupts based on timer intervals. */ #define SPI 0x7a /* SPI: Serial Interface Register */ #define I2C_A 0x7b /* I2C Address. 32 bit */ #define I2C_0 0x7c /* I2C Data Port 0. 32 bit */ #define I2C_1 0x7d /* I2C Data Port 1. 32 bit */ #define I2C_D0 0x7c /* I2C Data Port 0. 32 bit */ #define I2C_D1 0x7d /* I2C Data Port 1. 32 bit */ //I2C values #define I2C_A_ADC_ADD_MASK 0x000000fe //The address is a 7 bit address #define I2C_A_ADC_RW_MASK 0x00000001 //bit mask for R/W #define I2C_A_ADC_TRANS_MASK 0x00000010 //Bit mask for I2c address DAC value #define I2C_A_ADC_ABORT_MASK 0x00000020 //Bit mask for I2C transaction abort flag #define I2C_A_ADC_LAST_MASK 0x00000040 //Bit mask for Last word transaction #define I2C_A_ADC_BYTE_MASK 0x00000080 //Bit mask for Byte Mode #define I2C_A_ADC_ADD 0x00000034 //This is the Device address for ADC #define I2C_A_ADC_READ 0x00000001 //To perform a read operation #define I2C_A_ADC_START 0x00000100 //Start I2C transaction #define I2C_A_ADC_ABORT 0x00000200 //I2C transaction abort #define I2C_A_ADC_LAST 0x00000400 //I2C last transaction #define I2C_A_ADC_BYTE 0x00000800 //I2C one byte mode #define I2C_D_ADC_REG_MASK 0xfe000000 //ADC address register #define I2C_D_ADC_DAT_MASK 0x01ff0000 //ADC data register #define ADC_TIMEOUT 0x00000007 //ADC Timeout Clock Disable #define ADC_IFC_CTRL 0x0000000b //ADC Interface Control #define ADC_MASTER 0x0000000c //ADC Master Mode Control #define ADC_POWER 0x0000000d //ADC PowerDown Control #define ADC_ATTEN_ADCL 0x0000000e //ADC Attenuation ADCL #define ADC_ATTEN_ADCR 0x0000000f //ADC Attenuation ADCR #define ADC_ALC_CTRL1 0x00000010 //ADC ALC Control 1 #define ADC_ALC_CTRL2 0x00000011 //ADC ALC Control 2 #define ADC_ALC_CTRL3 0x00000012 //ADC ALC Control 3 #define ADC_NOISE_CTRL 0x00000013 //ADC Noise Gate Control #define ADC_LIMIT_CTRL 0x00000014 //ADC Limiter Control #define ADC_MUX 0x00000015 //ADC Mux offset #if 0 /* FIXME: Not tested yet. */ #define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain #define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB #define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute #define ADC_MUTE 0x000000c0 //Value to mute ADC #define ADC_OSR 0x00000008 //Mask for ADC oversample rate select #define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock #define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter #define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window #endif #define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux #define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux #define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux #define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) #define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ #define PCM_FRONT_CHANNEL 0 Loading Loading @@ -513,6 +562,7 @@ typedef struct { char * name; int ac97; int gpio_type; int i2c_adc; } ca0106_details_t; // definition of the chip-specific record Loading Loading @@ -555,3 +605,6 @@ void snd_ca0106_ptr_write(ca0106_t *emu, unsigned int chn, unsigned int data); int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value); sound/pci/ca0106/ca0106_main.c +66 −4 Original line number Diff line number Diff line /* * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit * Version: 0.0.22 * Version: 0.0.23 * * FEATURES currently supported: * Front, Rear and Center/LFE. Loading Loading @@ -77,6 +77,8 @@ * Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.) * 0.0.22 * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 * 0.0.23 * Implement support for Line-in capture on SB Live 24bit. * * BUGS: * Some stability problems when unloading the snd-ca0106 kernel module. Loading Loading @@ -173,15 +175,18 @@ static ca0106_details_t ca0106_chip_details[] = { /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */ { .serial = 0x10061102, .name = "Live! 7.1 24bit [SB0410]", .gpio_type = 1 } , .gpio_type = 1, .i2c_adc = 1 } , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ { .serial = 0x10071102, .name = "Live! 7.1 24bit [SB0413]", .gpio_type = 1 } , .gpio_type = 1, .i2c_adc = 1 } , /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ { .serial = 0x10091462, .name = "MSI K8N Diamond MB [SB0438]", .gpio_type = 1 } , .gpio_type = 1, .i2c_adc = 1 } , { .serial = 0, .name = "AudigyLS [Unknown]" } }; Loading Loading @@ -257,6 +262,59 @@ void snd_ca0106_ptr_write(ca0106_t *emu, spin_unlock_irqrestore(&emu->emu_lock, flags); } int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value) { u32 tmp; int timeout=0; int status; int retry; if ((reg > 0x7f) || (value > 0x1ff)) { snd_printk("i2c_write: invalid values.\n"); return -EINVAL; } tmp = reg << 25 | value << 16; snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp); for(retry=0;retry<10;retry++) { /* Send the data to i2c */ tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); snd_ca0106_ptr_write(emu, I2C_A, 0, tmp); /* Wait till the transaction ends */ while(1) { status = snd_ca0106_ptr_read(emu, I2C_A, 0); //snd_printk("I2C:status=0x%x\n", status); timeout++; if((status & I2C_A_ADC_START)==0) break; if(timeout>1000) break; } //Read back and see if the transaction is successful if((status & I2C_A_ADC_ABORT)==0) break; } if(retry==10) { snd_printk("Writing to ADC failed!\n"); return -EINVAL; } return 0; } static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb) { unsigned long flags; Loading Loading @@ -1177,6 +1235,10 @@ static int __devinit snd_ca0106_create(snd_card_t *card, //outl(0x00000009, chip->port+HCFG); outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ } if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_ca0106_free(chip); Loading sound/pci/ca0106/ca0106_proc.c +25 −2 Original line number Diff line number Diff line /* * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit * Version: 0.0.17 * Version: 0.0.18 * * FEATURES currently supported: * See ca0106_main.c for features. Loading Loading @@ -39,6 +39,8 @@ * Modified Copyright message. * 0.0.17 * Add iec958 file in proc file system to show status of SPDIF in. * 0.0.18 * Implement support for Line-in capture on SB Live 24bit. * * This code was initally based on code from ALSA's emu10k1x.c which is: * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> Loading Loading @@ -407,6 +409,20 @@ static void snd_ca0106_proc_reg_write(snd_info_entry_t *entry, } } static void snd_ca0106_proc_i2c_write(snd_info_entry_t *entry, snd_info_buffer_t * buffer) { ca0106_t *emu = entry->private_data; char line[64]; unsigned int reg, val; while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; if ((reg <= 0x7f) || (val <= 0x1ff)) { snd_ca0106_i2c_write(emu, reg, val); } } } int __devinit snd_ca0106_proc_init(ca0106_t * emu) { Loading @@ -429,6 +445,13 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu) entry->c.text.write_size = 64; entry->c.text.write = snd_ca0106_proc_reg_write; entry->mode |= S_IWUSR; // entry->private_data = emu; } if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write); entry->c.text.write_size = 64; entry->c.text.write = snd_ca0106_proc_i2c_write; entry->mode |= S_IWUSR; // entry->private_data = emu; } if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) Loading Loading
sound/pci/ca0106/ca0106.h +57 −4 Original line number Diff line number Diff line /* * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit * Version: 0.0.20 * Version: 0.0.21 * * FEATURES currently supported: * See ca0106_main.c for features. Loading Loading @@ -45,6 +45,8 @@ * Added I2C and SPI registers. Filled in interrupt enable. * 0.0.20 * Added GPIO info for SB Live 24bit. * 0.0.21 * Implement support for Line-in capture on SB Live 24bit. * * * This code was initally based on code from ALSA's emu10k1x.c which is: Loading Loading @@ -475,9 +477,56 @@ /* Causes interrupts based on timer intervals. */ #define SPI 0x7a /* SPI: Serial Interface Register */ #define I2C_A 0x7b /* I2C Address. 32 bit */ #define I2C_0 0x7c /* I2C Data Port 0. 32 bit */ #define I2C_1 0x7d /* I2C Data Port 1. 32 bit */ #define I2C_D0 0x7c /* I2C Data Port 0. 32 bit */ #define I2C_D1 0x7d /* I2C Data Port 1. 32 bit */ //I2C values #define I2C_A_ADC_ADD_MASK 0x000000fe //The address is a 7 bit address #define I2C_A_ADC_RW_MASK 0x00000001 //bit mask for R/W #define I2C_A_ADC_TRANS_MASK 0x00000010 //Bit mask for I2c address DAC value #define I2C_A_ADC_ABORT_MASK 0x00000020 //Bit mask for I2C transaction abort flag #define I2C_A_ADC_LAST_MASK 0x00000040 //Bit mask for Last word transaction #define I2C_A_ADC_BYTE_MASK 0x00000080 //Bit mask for Byte Mode #define I2C_A_ADC_ADD 0x00000034 //This is the Device address for ADC #define I2C_A_ADC_READ 0x00000001 //To perform a read operation #define I2C_A_ADC_START 0x00000100 //Start I2C transaction #define I2C_A_ADC_ABORT 0x00000200 //I2C transaction abort #define I2C_A_ADC_LAST 0x00000400 //I2C last transaction #define I2C_A_ADC_BYTE 0x00000800 //I2C one byte mode #define I2C_D_ADC_REG_MASK 0xfe000000 //ADC address register #define I2C_D_ADC_DAT_MASK 0x01ff0000 //ADC data register #define ADC_TIMEOUT 0x00000007 //ADC Timeout Clock Disable #define ADC_IFC_CTRL 0x0000000b //ADC Interface Control #define ADC_MASTER 0x0000000c //ADC Master Mode Control #define ADC_POWER 0x0000000d //ADC PowerDown Control #define ADC_ATTEN_ADCL 0x0000000e //ADC Attenuation ADCL #define ADC_ATTEN_ADCR 0x0000000f //ADC Attenuation ADCR #define ADC_ALC_CTRL1 0x00000010 //ADC ALC Control 1 #define ADC_ALC_CTRL2 0x00000011 //ADC ALC Control 2 #define ADC_ALC_CTRL3 0x00000012 //ADC ALC Control 3 #define ADC_NOISE_CTRL 0x00000013 //ADC Noise Gate Control #define ADC_LIMIT_CTRL 0x00000014 //ADC Limiter Control #define ADC_MUX 0x00000015 //ADC Mux offset #if 0 /* FIXME: Not tested yet. */ #define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain #define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB #define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute #define ADC_MUTE 0x000000c0 //Value to mute ADC #define ADC_OSR 0x00000008 //Mask for ADC oversample rate select #define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock #define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter #define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window #endif #define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux #define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux #define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux #define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) #define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ #define PCM_FRONT_CHANNEL 0 Loading Loading @@ -513,6 +562,7 @@ typedef struct { char * name; int ac97; int gpio_type; int i2c_adc; } ca0106_details_t; // definition of the chip-specific record Loading Loading @@ -555,3 +605,6 @@ void snd_ca0106_ptr_write(ca0106_t *emu, unsigned int chn, unsigned int data); int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value);
sound/pci/ca0106/ca0106_main.c +66 −4 Original line number Diff line number Diff line /* * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit * Version: 0.0.22 * Version: 0.0.23 * * FEATURES currently supported: * Front, Rear and Center/LFE. Loading Loading @@ -77,6 +77,8 @@ * Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.) * 0.0.22 * Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901 * 0.0.23 * Implement support for Line-in capture on SB Live 24bit. * * BUGS: * Some stability problems when unloading the snd-ca0106 kernel module. Loading Loading @@ -173,15 +175,18 @@ static ca0106_details_t ca0106_chip_details[] = { /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */ { .serial = 0x10061102, .name = "Live! 7.1 24bit [SB0410]", .gpio_type = 1 } , .gpio_type = 1, .i2c_adc = 1 } , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ { .serial = 0x10071102, .name = "Live! 7.1 24bit [SB0413]", .gpio_type = 1 } , .gpio_type = 1, .i2c_adc = 1 } , /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ { .serial = 0x10091462, .name = "MSI K8N Diamond MB [SB0438]", .gpio_type = 1 } , .gpio_type = 1, .i2c_adc = 1 } , { .serial = 0, .name = "AudigyLS [Unknown]" } }; Loading Loading @@ -257,6 +262,59 @@ void snd_ca0106_ptr_write(ca0106_t *emu, spin_unlock_irqrestore(&emu->emu_lock, flags); } int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value) { u32 tmp; int timeout=0; int status; int retry; if ((reg > 0x7f) || (value > 0x1ff)) { snd_printk("i2c_write: invalid values.\n"); return -EINVAL; } tmp = reg << 25 | value << 16; snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp); for(retry=0;retry<10;retry++) { /* Send the data to i2c */ tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); snd_ca0106_ptr_write(emu, I2C_A, 0, tmp); /* Wait till the transaction ends */ while(1) { status = snd_ca0106_ptr_read(emu, I2C_A, 0); //snd_printk("I2C:status=0x%x\n", status); timeout++; if((status & I2C_A_ADC_START)==0) break; if(timeout>1000) break; } //Read back and see if the transaction is successful if((status & I2C_A_ADC_ABORT)==0) break; } if(retry==10) { snd_printk("Writing to ADC failed!\n"); return -EINVAL; } return 0; } static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb) { unsigned long flags; Loading Loading @@ -1177,6 +1235,10 @@ static int __devinit snd_ca0106_create(snd_card_t *card, //outl(0x00000009, chip->port+HCFG); outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ } if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_ca0106_free(chip); Loading
sound/pci/ca0106/ca0106_proc.c +25 −2 Original line number Diff line number Diff line /* * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit * Version: 0.0.17 * Version: 0.0.18 * * FEATURES currently supported: * See ca0106_main.c for features. Loading Loading @@ -39,6 +39,8 @@ * Modified Copyright message. * 0.0.17 * Add iec958 file in proc file system to show status of SPDIF in. * 0.0.18 * Implement support for Line-in capture on SB Live 24bit. * * This code was initally based on code from ALSA's emu10k1x.c which is: * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> Loading Loading @@ -407,6 +409,20 @@ static void snd_ca0106_proc_reg_write(snd_info_entry_t *entry, } } static void snd_ca0106_proc_i2c_write(snd_info_entry_t *entry, snd_info_buffer_t * buffer) { ca0106_t *emu = entry->private_data; char line[64]; unsigned int reg, val; while (!snd_info_get_line(buffer, line, sizeof(line))) { if (sscanf(line, "%x %x", ®, &val) != 2) continue; if ((reg <= 0x7f) || (val <= 0x1ff)) { snd_ca0106_i2c_write(emu, reg, val); } } } int __devinit snd_ca0106_proc_init(ca0106_t * emu) { Loading @@ -429,6 +445,13 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu) entry->c.text.write_size = 64; entry->c.text.write = snd_ca0106_proc_reg_write; entry->mode |= S_IWUSR; // entry->private_data = emu; } if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write); entry->c.text.write_size = 64; entry->c.text.write = snd_ca0106_proc_i2c_write; entry->mode |= S_IWUSR; // entry->private_data = emu; } if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) Loading