diff options
29 files changed, 553 insertions, 245 deletions
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index a311008af5e1..f23f8bf02b04 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1308,6 +1308,7 @@ #define PCI_SUBDEVICE_ID_CREATIVE_SB08801 0x0041 #define PCI_SUBDEVICE_ID_CREATIVE_SB08802 0x0042 #define PCI_SUBDEVICE_ID_CREATIVE_SB08803 0x0043 +#define PCI_SUBDEVICE_ID_CREATIVE_SB1270 0x0062 #define PCI_SUBDEVICE_ID_CREATIVE_HENDRIX 0x6000 #define PCI_VENDOR_ID_ECTIVA 0x1102 /* duplicate: CREATIVE */ diff --git a/sound/core/misc.c b/sound/core/misc.c index 2c41825c836e..eb9fe2e1d291 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -58,26 +58,6 @@ static const char *sanity_file_name(const char *path) else return path; } - -/* print file and line with a certain printk prefix */ -static int print_snd_pfx(unsigned int level, const char *path, int line, - const char *format) -{ - const char *file = sanity_file_name(path); - char tmp[] = "<0>"; - const char *pfx = level ? KERN_DEBUG : KERN_DEFAULT; - int ret = 0; - - if (format[0] == '<' && format[2] == '>') { - tmp[1] = format[1]; - pfx = tmp; - ret = 1; - } - printk("%sALSA %s:%d: ", pfx, file, line); - return ret; -} -#else -#define print_snd_pfx(level, path, line, format) 0 #endif #if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK) @@ -85,15 +65,29 @@ void __snd_printk(unsigned int level, const char *path, int line, const char *format, ...) { va_list args; - +#ifdef CONFIG_SND_VERBOSE_PRINTK + struct va_format vaf; + char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV"; +#endif + #ifdef CONFIG_SND_DEBUG if (debug < level) return; #endif + va_start(args, format); - if (print_snd_pfx(level, path, line, format)) - format += 3; /* skip the printk level-prefix */ +#ifdef CONFIG_SND_VERBOSE_PRINTK + vaf.fmt = format; + vaf.va = &args; + if (format[0] == '<' && format[2] == '>') { + memcpy(verbose_fmt, format, 3); + vaf.fmt = format + 3; + } else if (level) + memcpy(verbose_fmt, KERN_DEBUG, 3); + printk(verbose_fmt, sanity_file_name(path), line, &vaf); +#else vprintk(format, args); +#endif va_end(args); } EXPORT_SYMBOL_GPL(__snd_printk); diff --git a/sound/pci/ctxfi/ct20k2reg.h b/sound/pci/ctxfi/ct20k2reg.h index e0394e3996e8..ca501ba03d64 100644 --- a/sound/pci/ctxfi/ct20k2reg.h +++ b/sound/pci/ctxfi/ct20k2reg.h @@ -55,6 +55,7 @@ /* GPIO Registers */ #define GPIO_DATA 0x1B7020 #define GPIO_CTRL 0x1B7024 +#define GPIO_EXT_DATA 0x1B70A0 /* Virtual memory registers */ #define VMEM_PTPAL 0x1C6300 /* 0x1C6300 + (16 * Chn) */ diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 13f33c0719d3..d8a4423539ce 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -18,7 +18,6 @@ #include "ctatc.h" #include "ctpcm.h" #include "ctmixer.h" -#include "cthardware.h" #include "ctsrc.h" #include "ctamixer.h" #include "ctdaio.h" @@ -30,7 +29,6 @@ #include <sound/asoundef.h> #define MONO_SUM_SCALE 0x19a8 /* 2^(-0.5) in 14-bit floating format */ -#define DAIONUM 7 #define MAX_MULTI_CHN 8 #define IEC958_DEFAULT_CON ((IEC958_AES0_NONAUDIO \ @@ -53,6 +51,8 @@ static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = { static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760, "SB0760", CTSB0760), + SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270, + "SB1270", CTSB1270), SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08801, "SB0880", CTSB0880), SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB08802, @@ -75,6 +75,7 @@ static const char *ct_subsys_name[NUM_CTCARDS] = { [CTSB0760] = "SB076x", [CTHENDRIX] = "Hendrix", [CTSB0880] = "SB0880", + [CTSB1270] = "SB1270", [CT20K2_UNKNOWN] = "Unknown", }; @@ -459,12 +460,12 @@ static void setup_src_node_conf(struct ct_atc *atc, struct ct_atc_pcm *apcm, apcm->substream->runtime->rate); *n_srcc = 0; - if (1 == atc->msr) { + if (1 == atc->msr) { /* FIXME: do we really need SRC here if pitch==1 */ *n_srcc = apcm->substream->runtime->channels; conf[0].pitch = pitch; conf[0].mix_msr = conf[0].imp_msr = conf[0].msr = 1; conf[0].vo = 1; - } else if (2 == atc->msr) { + } else if (2 <= atc->msr) { if (0x8000000 < pitch) { /* Need two-stage SRCs, SRCIMPs and * AMIXERs for converting format */ @@ -970,11 +971,39 @@ static int atc_select_mic_in(struct ct_atc *atc) return 0; } -static int atc_have_digit_io_switch(struct ct_atc *atc) +static struct capabilities atc_capabilities(struct ct_atc *atc) { struct hw *hw = atc->hw; - return hw->have_digit_io_switch(hw); + return hw->capabilities(hw); +} + +static int atc_output_switch_get(struct ct_atc *atc) +{ + struct hw *hw = atc->hw; + + return hw->output_switch_get(hw); +} + +static int atc_output_switch_put(struct ct_atc *atc, int position) +{ + struct hw *hw = atc->hw; + + return hw->output_switch_put(hw, position); +} + +static int atc_mic_source_switch_get(struct ct_atc *atc) +{ + struct hw *hw = atc->hw; + + return hw->mic_source_switch_get(hw); +} + +static int atc_mic_source_switch_put(struct ct_atc *atc, int position) +{ + struct hw *hw = atc->hw; + + return hw->mic_source_switch_put(hw, position); } static int atc_select_digit_io(struct ct_atc *atc) @@ -1045,6 +1074,11 @@ static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state) return atc_daio_unmute(atc, state, LINEIM); } +static int atc_mic_unmute(struct ct_atc *atc, unsigned char state) +{ + return atc_daio_unmute(atc, state, MIC); +} + static int atc_spdif_out_unmute(struct ct_atc *atc, unsigned char state) { return atc_daio_unmute(atc, state, SPDIFOO); @@ -1331,17 +1365,20 @@ static int atc_get_resources(struct ct_atc *atc) struct srcimp_mgr *srcimp_mgr; struct sum_desc sum_dsc = {0}; struct sum_mgr *sum_mgr; - int err, i; + int err, i, num_srcs, num_daios; - atc->daios = kzalloc(sizeof(void *)*(DAIONUM), GFP_KERNEL); + num_daios = ((atc->model == CTSB1270) ? 8 : 7); + num_srcs = ((atc->model == CTSB1270) ? 6 : 4); + + atc->daios = kzalloc(sizeof(void *)*num_daios, GFP_KERNEL); if (!atc->daios) return -ENOMEM; - atc->srcs = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL); + atc->srcs = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL); if (!atc->srcs) return -ENOMEM; - atc->srcimps = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL); + atc->srcimps = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL); if (!atc->srcimps) return -ENOMEM; @@ -1351,8 +1388,9 @@ static int atc_get_resources(struct ct_atc *atc) daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; da_desc.msr = atc->msr; - for (i = 0, atc->n_daio = 0; i < DAIONUM-1; i++) { - da_desc.type = i; + for (i = 0, atc->n_daio = 0; i < num_daios; i++) { + da_desc.type = (atc->model != CTSB073X) ? i : + ((i == SPDIFIO) ? SPDIFI1 : i); err = daio_mgr->get_daio(daio_mgr, &da_desc, (struct daio **)&atc->daios[i]); if (err) { @@ -1362,23 +1400,12 @@ static int atc_get_resources(struct ct_atc *atc) } atc->n_daio++; } - if (atc->model == CTSB073X) - da_desc.type = SPDIFI1; - else - da_desc.type = SPDIFIO; - err = daio_mgr->get_daio(daio_mgr, &da_desc, - (struct daio **)&atc->daios[i]); - if (err) { - printk(KERN_ERR "ctxfi: Failed to get S/PDIF-in resource!!!\n"); - return err; - } - atc->n_daio++; src_mgr = atc->rsc_mgrs[SRC]; src_dsc.multi = 1; src_dsc.msr = atc->msr; src_dsc.mode = ARCRW; - for (i = 0, atc->n_src = 0; i < (2*2); i++) { + for (i = 0, atc->n_src = 0; i < num_srcs; i++) { err = src_mgr->get_src(src_mgr, &src_dsc, (struct src **)&atc->srcs[i]); if (err) @@ -1388,8 +1415,8 @@ static int atc_get_resources(struct ct_atc *atc) } srcimp_mgr = atc->rsc_mgrs[SRCIMP]; - srcimp_dsc.msr = 8; /* SRCIMPs for S/PDIFIn SRT */ - for (i = 0, atc->n_srcimp = 0; i < (2*1); i++) { + srcimp_dsc.msr = 8; + for (i = 0, atc->n_srcimp = 0; i < num_srcs; i++) { err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, (struct srcimp **)&atc->srcimps[i]); if (err) @@ -1397,15 +1424,6 @@ static int atc_get_resources(struct ct_atc *atc) atc->n_srcimp++; } - srcimp_dsc.msr = 8; /* SRCIMPs for LINE/MICIn SRT */ - for (i = 0; i < (2*1); i++) { - err = srcimp_mgr->get_srcimp(srcimp_mgr, &srcimp_dsc, - (struct srcimp **)&atc->srcimps[2*1+i]); - if (err) - return err; - - atc->n_srcimp++; - } sum_mgr = atc->rsc_mgrs[SUM]; sum_dsc.msr = atc->msr; @@ -1488,6 +1506,18 @@ static void atc_connect_resources(struct ct_atc *atc) src = atc->srcs[3]; mixer->set_input_right(mixer, MIX_LINE_IN, &src->rsc); + if (atc->model == CTSB1270) { + /* Titanium HD has a dedicated ADC for the Mic. */ + dai = container_of(atc->daios[MIC], struct dai, daio); + atc_connect_dai(atc->rsc_mgrs[SRC], dai, + (struct src **)&atc->srcs[4], + (struct srcimp **)&atc->srcimps[4]); + src = atc->srcs[4]; + mixer->set_input_left(mixer, MIX_MIC_IN, &src->rsc); + src = atc->srcs[5]; + mixer->set_input_right(mixer, MIX_MIC_IN, &src->rsc); + } + dai = container_of(atc->daios[SPDIFIO], struct dai, daio); atc_connect_dai(atc->rsc_mgrs[SRC], dai, (struct src **)&atc->srcs[0], @@ -1606,12 +1636,17 @@ static struct ct_atc atc_preset __devinitdata = { .line_clfe_unmute = atc_line_clfe_unmute, .line_rear_unmute = atc_line_rear_unmute, .line_in_unmute = atc_line_in_unmute, + .mic_unmute = atc_mic_unmute, .spdif_out_unmute = atc_spdif_out_unmute, .spdif_in_unmute = atc_spdif_in_unmute, .spdif_out_get_status = atc_spdif_out_get_status, .spdif_out_set_status = atc_spdif_out_set_status, .spdif_out_passthru = atc_spdif_out_passthru, - .have_digit_io_switch = atc_have_digit_io_switch, + .capabilities = atc_capabilities, + .output_switch_get = atc_output_switch_get, + .output_switch_put = atc_output_switch_put, + .mic_source_switch_get = atc_mic_source_switch_get, + .mic_source_switch_put = atc_mic_source_switch_put, #ifdef CONFIG_PM .suspend = atc_suspend, .resume = atc_resume, diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h index 7167c0185d52..3a0def656af0 100644 --- a/sound/pci/ctxfi/ctatc.h +++ b/sound/pci/ctxfi/ctatc.h @@ -25,6 +25,7 @@ #include <sound/core.h> #include "ctvmem.h" +#include "cthardware.h" #include "ctresource.h" enum CTALSADEVS { /* Types of alsa devices */ @@ -115,12 +116,17 @@ struct ct_atc { int (*line_clfe_unmute)(struct ct_atc *atc, unsigned char state); int (*line_rear_unmute)(struct ct_atc *atc, unsigned char state); int (*line_in_unmute)(struct ct_atc *atc, unsigned char state); + int (*mic_unmute)(struct ct_atc *atc, unsigned char state); int (*spdif_out_unmute)(struct ct_atc *atc, unsigned char state); int (*spdif_in_unmute)(struct ct_atc *atc, unsigned char state); int (*spdif_out_get_status)(struct ct_atc *atc, unsigned int *status); int (*spdif_out_set_status)(struct ct_atc *atc, unsigned int status); int (*spdif_out_passthru)(struct ct_atc *atc, unsigned char state); - int (*have_digit_io_switch)(struct ct_atc *atc); + struct capabilities (*capabilities)(struct ct_atc *atc); + int (*output_switch_get)(struct ct_atc *atc); + int (*output_switch_put)(struct ct_atc *atc, int position); + int (*mic_source_switch_get)(struct ct_atc *atc); + int (*mic_source_switch_put)(struct ct_atc *atc, int position); /* Don't touch! Used for internal object. */ void *rsc_mgrs[NUM_RSCTYP]; /* chip resource managers */ diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index 47d9ea97de02..0c00eb4088ef 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c @@ -22,20 +22,9 @@ #include <linux/slab.h> #include <linux/kernel.h> -#define DAIO_RESOURCE_NUM NUM_DAIOTYP #define DAIO_OUT_MAX SPDIFOO -union daio_usage { - struct { - unsigned short lineo1:1; - unsigned short lineo2:1; - unsigned short lineo3:1; - unsigned short lineo4:1; - unsigned short spdifoo:1; - unsigned short lineim:1; - unsigned short spdifio:1; - unsigned short spdifi1:1; - } bf; +struct daio_usage { unsigned short data; }; @@ -61,6 +50,7 @@ struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = { [LINEO3] = {.left = 0x50, .right = 0x51}, [LINEO4] = {.left = 0x70, .right = 0x71}, [LINEIM] = {.left = 0x45, .right = 0xc5}, + [MIC] = {.left = 0x55, .right = 0xd5}, [SPDIFOO] = {.left = 0x00, .right = 0x01}, [SPDIFIO] = {.left = 0x05, .right = 0x85}, }; @@ -138,6 +128,7 @@ static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw) case LINEO3: return 5; case LINEO4: return 6; case LINEIM: return 4; + case MIC: return 5; default: return -EINVAL; } default: @@ -519,17 +510,17 @@ static int dai_rsc_uninit(struct dai *dai) static int daio_mgr_get_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) { - if (((union daio_usage *)mgr->rscs)->data & (0x1 << type)) + if (((struct daio_usage *)mgr->rscs)->data & (0x1 << type)) return -ENOENT; - ((union daio_usage *)mgr->rscs)->data |= (0x1 << type); + ((struct daio_usage *)mgr->rscs)->data |= (0x1 << type); return 0; } static int daio_mgr_put_rsc(struct rsc_mgr *mgr, enum DAIOTYP type) { - ((union daio_usage *)mgr->rscs)->data &= ~(0x1 << type); + ((struct daio_usage *)mgr->rscs)->data &= ~(0x1 << type); return 0; } @@ -712,7 +703,7 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr) if (!daio_mgr) return -ENOMEM; - err = rsc_mgr_init(&daio_mgr->mgr, DAIO, DAIO_RESOURCE_NUM, hw); + err = rsc_mgr_init(&daio_mgr->mgr, DAIO, NUM_DAIOTYP, hw); if (err) goto error1; diff --git a/sound/pci/ctxfi/ctdaio.h b/sound/pci/ctxfi/ctdaio.h index 0f52ce571ee8..85ccb6ee1ab4 100644 --- a/sound/pci/ctxfi/ctdaio.h +++ b/sound/pci/ctxfi/ctdaio.h @@ -33,6 +33,7 @@ enum DAIOTYP { SPDIFOO, /* S/PDIF Out (Flexijack/Optical) */ LINEIM, SPDIFIO, /* S/PDIF In (Flexijack/Optical) on the card */ + MIC, /* Dedicated mic on Titanium HD */ SPDIFI1, /* S/PDIF In on internal Drive Bay */ NUM_DAIOTYP }; diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h index af55405f5dec..908315bec3b4 100644 --- a/sound/pci/ctxfi/cthardware.h +++ b/sound/pci/ctxfi/cthardware.h @@ -39,6 +39,7 @@ enum CTCARDS { CT20K2_MODEL_FIRST = CTSB0760, CTHENDRIX, CTSB0880, + CTSB1270, CT20K2_UNKNOWN, NUM_CTCARDS /* This should always be the last */ }; @@ -60,6 +61,13 @@ struct card_conf { unsigned int msr; /* master sample rate in rsrs */ }; +struct capabilities { + unsigned int digit_io_switch:1; + unsigned int dedicated_mic:1; + unsigned int output_switch:1; + unsigned int mic_source_switch:1; +}; + struct hw { int (*card_init)(struct hw *hw, struct card_conf *info); int (*card_stop)(struct hw *hw); @@ -70,7 +78,11 @@ struct hw { #endif int (*is_adc_source_selected)(struct hw *hw, enum ADCSRC source); int (*select_adc_source)(struct hw *hw, enum ADCSRC source); - int (*have_digit_io_switch)(struct hw *hw); + struct capabilities (*capabilities)(struct hw *hw); + int (*output_switch_get)(struct hw *hw); + int (*output_switch_put)(struct hw *hw, int position); + int (*mic_source_switch_get)(struct hw *hw); + int (*mic_source_switch_put)(struct hw *hw, int position); /* SRC operations */ int (*src_rsc_get_ctrl_blk)(void **rblk); diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index 284baf9660eb..a7df19791f5a 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c @@ -1777,10 +1777,17 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) return adc_init_SBx(hw, info->input, info->mic20db); } -static int hw_have_digit_io_switch(struct hw *hw) +static struct capabilities hw_capabilities(struct hw *hw) { + struct capabilities cap; + /* SB073x and Vista compatible cards have no digit IO switch */ - return !(hw->model == CTSB073X || hw->model == CTUAA); + cap.digit_io_switch = !(hw->model == CTSB073X || hw->model == CTUAA); + cap.dedicated_mic = 0; + cap.output_switch = 0; + cap.mic_source_switch = 0; + + return cap; } #define CTLBITS(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) @@ -2172,7 +2179,7 @@ static struct hw ct20k1_preset __devinitdata = { .pll_init = hw_pll_init, .is_adc_source_selected = hw_is_adc_input_selected, .select_adc_source = hw_adc_input_select, - .have_digit_io_switch = hw_have_digit_io_switch, + .capabilities = hw_capabilities, #ifdef CONFIG_PM .suspend = hw_suspend, .resume = hw_resume, diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 64f9ded85bbb..1aa083272703 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c @@ -8,7 +8,7 @@ * @File cthw20k2.c * * @Brief - * This file contains the implementation of hardware access methord for 20k2. + * This file contains the implementation of hardware access method for 20k2. * * @Author Liu Chun * @Date May 14 2008 @@ -38,6 +38,8 @@ struct hw20k2 { unsigned char dev_id; unsigned char addr_size; unsigned char data_size; + + int mic_source; }; static u32 hw_read_20kx(struct hw *hw, u32 reg); @@ -1163,7 +1165,12 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101); hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); } else if (2 == info->msr) { - hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111); + if (hw->model != CTSB1270) { + hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111); + } else { + /* PCM4220 on Titanium HD is different. */ + hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11011111); + } /* Specify all playing 96khz * EA [0] - Enabled * RTA [4:5] - 96kHz @@ -1175,6 +1182,10 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) * RTD [28:29] - 96kHz */ hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111); hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); + } else if ((4 == info->msr) && (hw->model == CTSB1270)) { + hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21011111); + hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121); + hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0); } else { printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n"); return -EINVAL; @@ -1182,6 +1193,8 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) for (i = 0; i < 8; i++) { if (i <= 3) { + /* This comment looks wrong since loop is over 4 */ + /* channels and emu20k2 supports 4 spdif IOs. */ /* 1st 3 channels are SPDIFs (SB0960) */ if (i == 3) data = 0x1001001; @@ -1206,12 +1219,16 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info) hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B); } else { + /* Again, loop is over 4 channels not 5. */ /* Next 5 channels are I2S (SB0960) */ data = 0x11; hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data); if (2 == info->msr) { /* Four channels per sample period */ data |= 0x1000; + } else if (4 == info->msr) { + /* FIXME: check this against the chip spec */ + data |= 0x2000; } hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data); } @@ -1557,7 +1574,7 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data) hw_write_20kx(hw, I2C_IF_STATUS, i2c_status); hw20k2_i2c_wait_data_ready(hw); - /* Dummy write to trigger the write oprtation */ + /* Dummy write to trigger the write operation */ hw_write_20kx(hw, I2C_IF_WDATA, 0); hw20k2_i2c_wait_data_ready(hw); @@ -1568,6 +1585,30 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data) return 0; } +static void hw_dac_stop(struct hw *hw) +{ + u32 data; + data = hw_read_20kx(hw, GPIO_DATA); + data &= 0xFFFFFFFD; + hw_write_20kx(hw, GPIO_DATA, data); + mdelay(10); +} + +static void hw_dac_start(struct hw *hw) +{ + u32 data; + data = hw_read_20kx(hw, GPIO_DATA); + data |= 0x2; + hw_write_20kx(hw, GPIO_DATA, data); + mdelay(50); +} + +static void hw_dac_reset(struct hw *hw) +{ + hw_dac_stop(hw); + hw_dac_start(hw); +} + static int hw_dac_init(struct hw *hw, const struct dac_conf *info) { int err; @@ -1594,6 +1635,21 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info) 0x00000000 /* Vol Control B4 */ }; + if (hw->model == CTSB1270) { + hw_dac_stop(hw); + data = hw_read_20kx(hw, GPIO_DATA); + data &= ~0x0600; + if (1 == info->msr) + data |= 0x0000; /* Single Speed Mode 0-50kHz */ + else if (2 == info->msr) + data |= 0x0200; /* Double Speed Mode 50-100kHz */ + else + data |= 0x0600; /* Quad Speed Mode 100-200kHz */ + hw_write_20kx(hw, GPIO_DATA, data); + hw_dac_start(hw); + return 0; + } + /* Set DAC reset bit as output */ data = hw_read_20kx(hw, GPIO_CTRL); data |= 0x02; @@ -1606,22 +1662,8 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info) for (i = 0; i < 2; i++) { /* Reset DAC twice just in-case the chip * didn't initialized properly */ - data = hw_read_20kx(hw, GPIO_DATA); - /* GPIO data bit 1 */ - data &= 0xFFFFFFFD; - hw_write_20kx(hw, GPIO_DATA, data); - mdelay(10); - data |= 0x2; - hw_write_20kx(hw, GPIO_DATA, data); - mdelay(50); - - /* Reset the 2nd time */ - data &= 0xFFFFFFFD; - hw_write_20kx(hw, GPIO_DATA, data); - mdelay(10); - data |= 0x2; - hw_write_20kx(hw, GPIO_DATA, data); - mdelay(50); + hw_dac_reset(hw); + hw_dac_reset(hw); if (hw20k2_i2c_read(hw, CS4382_MC1, &cs_read.mode_control_1)) continue; @@ -1725,7 +1767,11 @@ End: static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) { u32 data; - + if (hw->model == CTSB1270) { + /* Titanium HD has two ADC chips, one for line in and one */ + /* for MIC. We don't need to switch the ADC input. */ + return 1; + } data = hw_read_20kx(hw, GPIO_DATA); switch (type) { case ADC_MICIN: @@ -1742,35 +1788,47 @@ static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) #define MIC_BOOST_0DB 0xCF #define MIC_BOOST_STEPS_PER_DB 2 -#define MIC_BOOST_20DB (MIC_BOOST_0DB + 20 * MIC_BOOST_STEPS_PER_DB) + +static void hw_wm8775_input_select(struct hw *hw, u8 input, s8 gain_in_db) +{ + u32 adcmc, gain; + + if (input > 3) + input = 3; + + adcmc = ((u32)1 << input) | 0x100; /* Link L+R gain... */ + + hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, adcmc), + MAKE_WM8775_DATA(adcmc)); + + if (gain_in_db < -103) + gain_in_db = -103; + if (gain_in_db > 24) + gain_in_db = 24; + + gain = gain_in_db * MIC_BOOST_STEPS_PER_DB + MIC_BOOST_0DB; + + hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, gain), + MAKE_WM8775_DATA(gain)); + /* ...so there should be no need for the following. */ + hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, gain), + MAKE_WM8775_DATA(gain)); +} static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) { u32 data; - data = hw_read_20kx(hw, GPIO_DATA); switch (type) { case ADC_MICIN: data |= (0x1 << 14); hw_write_20kx(hw, GPIO_DATA, data); - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), - MAKE_WM8775_DATA(0x101)); /* Mic-in */ - hw20k2_i2c_write(hw, - MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB), - MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ - hw20k2_i2c_write(hw, - MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB), - MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ + hw_wm8775_input_select(hw, 0, 20); /* Mic, 20dB */ break; case ADC_LINEIN: data &= ~(0x1 << 14); hw_write_20kx(hw, GPIO_DATA, data); - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102), - MAKE_WM8775_DATA(0x102)); /* Line-in */ - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF), - MAKE_WM8775_DATA(0xCF)); /* No boost */ - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF), - MAKE_WM8775_DATA(0xCF)); /* No boost */ + hw_wm8775_input_select(hw, 1, 0); /* Line-in, 0dB */ break; default: break; @@ -1782,7 +1840,7 @@ static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) static int hw_adc_init(struct hw *hw, const struct adc_conf *info) { int err; - u32 mux = 2, data, ctl; + u32 data, ctl; /* Set ADC reset bit as output */ data = hw_read_20kx(hw, GPIO_CTRL); @@ -1796,19 +1854,42 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) goto error; } - /* Make ADC in normal operation */ + /* Reset the ADC (reset is active low). */ data = hw_read_20kx(hw, GPIO_DATA); data &= ~(0x1 << 15); + hw_write_20kx(hw, GPIO_DATA, data); + + if (hw->model == CTSB1270) { + /* Set up the PCM4220 ADC on Titanium HD */ + data &= ~0x0C; + if (1 == info->msr) + data |= 0x00; /* Single Speed Mode 32-50kHz */ + else if (2 == info->msr) + data |= 0x08; /* Double Speed Mode 50-108kHz */ + else + data |= 0x04; /* Quad Speed Mode 108kHz-216kHz */ + hw_write_20kx(hw, GPIO_DATA, data); + } + mdelay(10); + /* Return the ADC to normal operation. */ data |= (0x1 << 15); hw_write_20kx(hw, GPIO_DATA, data); mdelay(50); + /* I2C write to register offset 0x0B to set ADC LRCLK polarity */ + /* invert bit, interface format to I2S, word length to 24-bit, */ + /* enable ADC high pass filter. Fixes bug 5323? */ + hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_IC, 0x26), + MAKE_WM8775_DATA(0x26)); + /* Set the master mode (256fs) */ if (1 == info->msr) { + /* slave mode, 128x oversampling 256fs */ hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02), MAKE_WM8775_DATA(0x02)); - } else if (2 == info->msr) { + } else if ((2 == info->msr) || (4 == info->msr)) { + /* slave mode, 64x oversampling, 256fs */ hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A), MAKE_WM8775_DATA(0x0A)); } else { @@ -1818,55 +1899,113 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) goto error; } - /* Configure GPIO bit 14 change to line-in/mic-in */ - ctl = hw_read_20kx(hw, GPIO_CTRL); - ctl |= 0x1 << 14; - hw_write_20kx(hw, GPIO_CTRL, ctl); - - /* Check using Mic-in or Line-in */ - data = hw_read_20kx(hw, GPIO_DATA); - - if (mux == 1) { - /* Configures GPIO data to select Mic-in */ - data |= 0x1 << 14; - hw_write_20kx(hw, GPIO_DATA, data); - - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), - MAKE_WM8775_DATA(0x101)); /* Mic-in */ - hw20k2_i2c_write(hw, - MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB), - MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ - hw20k2_i2c_write(hw, - MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB), - MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ - } else if (mux == 2) { - /* Configures GPIO data to select Line-in */ - data &= ~(0x1 << 14); - hw_write_20kx(hw, GPIO_DATA, data); - - /* Setup ADC */ - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102), - MAKE_WM8775_DATA(0x102)); /* Line-in */ - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF), - MAKE_WM8775_DATA(0xCF)); /* No boost */ - hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF), - MAKE_WM8775_DATA(0xCF)); /* No boost */ + if (hw->model != CTSB1270) { + /* Configure GPIO bit 14 change to line-in/mic-in */ + ctl = hw_read_20kx(hw, GPIO_CTRL); + ctl |= 0x1 << 14; + hw_write_20kx(hw, GPIO_CTRL, ctl); + hw_adc_input_select(hw, ADC_LINEIN); } else { - printk(KERN_ALERT "ctxfi: ERROR!!! Invalid input mux!!!\n"); - err = -EINVAL; - goto error; + hw_wm8775_input_select(hw, 0, 0); } return 0; - error: hw20k2_i2c_uninit(hw); return err; } -static int hw_have_digit_io_switch(struct hw *hw) +static struct capabilities hw_capabilities(struct hw *hw) { - return 0; + struct capabilities cap; + + cap.digit_io_switch = 0; + cap.dedicated_mic = hw->model == CTSB1270; + cap.output_switch = hw->model == CTSB1270; + cap.mic_source_switch = hw->model == CTSB1270; + + return cap; +} + +static int hw_output_switch_get(struct hw *hw) +{ + u32 data = hw_read_20kx(hw, GPIO_EXT_DATA); + + switch (data & 0x30) { + case 0x00: + return 0; + case 0x10: + return 1; + case 0x20: + return 2; + default: + return 3; + } +} + +static int hw_output_switch_put(struct hw *hw, int position) +{ + u32 data; + + if (position == hw_output_switch_get(hw)) + return 0; + + /* Mute line and headphones (intended for anti-pop). */ + data = hw_read_20kx(hw, GPIO_DATA); + data |= (0x03 << 11); + hw_write_20kx(hw, GPIO_DATA, data); + + data = hw_read_20kx(hw, GPIO_EXT_DATA) & ~0x30; + switch (position) { + case 0: + break; + case 1: + data |= 0x10; + break; + default: + data |= 0x20; + } + hw_write_20kx(hw, GPIO_EXT_DATA, data); + + /* Unmute line and headphones. */ + data = hw_read_20kx(hw, GPIO_DATA); + data &= ~(0x03 << 11); + hw_write_20kx(hw, GPIO_DATA, data); + + return 1; +} + +static int hw_mic_source_switch_get(struct hw *hw) +{ + struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; + + return hw20k2->mic_source; +} + +static int hw_mic_source_switch_put(struct hw *hw, int position) +{ + struct hw20k2 *hw20k2 = (struct hw20k2 *)hw; + + if (position == hw20k2->mic_source) + return 0; + + switch (position) { + case 0: + hw_wm8775_input_select(hw, 0, 0); /* Mic, 0dB */ + break; + case 1: + hw_wm8775_input_select(hw, 1, 0); /* FP Mic, 0dB */ + break; + case 2: + hw_wm8775_input_select(hw, 3, 0); /* Aux Ext, 0dB */ + break; + default: + return 0; + } + + hw20k2->mic_source = position; + + return 1; } static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id) @@ -2023,13 +2162,16 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) /* Reset all SRC pending interrupts */ hw_write_20kx(hw, SRC_IP, 0); - /* TODO: detect the card ID and configure GPIO accordingly. */ - /* Configures GPIO (0xD802 0x98028) */ - /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ - /* Configures GPIO (SB0880) */ - /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ - hw_write_20kx(hw, GPIO_CTRL, 0xD802); - + if (hw->model != CTSB1270) { + /* TODO: detect the card ID and configure GPIO accordingly. */ + /* Configures GPIO (0xD802 0x98028) */ + /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/ + /* Configures GPIO (SB0880) */ + /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/ + hw_write_20kx(hw, GPIO_CTRL, 0xD802); + } else { + hw_write_20kx(hw, GPIO_CTRL, 0x9E5F); + } /* Enable audio ring */ hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01); @@ -2106,7 +2248,11 @@ static struct hw ct20k2_preset __devinitdata = { .pll_init = hw_pll_init, .is_adc_source_selected = hw_is_adc_input_selected, .select_adc_source = hw_adc_input_select, - .have_digit_io_switch = hw_have_digit_io_switch, + .capabilities = hw_capabilities, + .output_switch_get = hw_output_switch_get, + .output_switch_put = hw_output_switch_put, + .mic_source_switch_get = hw_mic_source_switch_get, + .mic_source_switch_put = hw_mic_source_switch_put, #ifdef CONFIG_PM .suspend = hw_suspend, .resume = hw_resume, diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index c3519ff42fbb..0cc13eeef8da 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c @@ -86,9 +86,7 @@ enum CTALSA_MIXER_CTL { MIXER_LINEIN_C_S, MIXER_MIC_C_S, MIXER_SPDIFI_C_S, - MIXER_LINEIN_P_S, MIXER_SPDIFO_P_S, - MIXER_SPDIFI_P_S, MIXER_WAVEF_P_S, MIXER_WAVER_P_S, MIXER_WAVEC_P_S, @@ -137,11 +135,11 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { }, [MIXER_LINEIN_P] = { .ctl = 1, - .name = "Line-in Playback Volume", + .name = "Line Playback Volume", }, [MIXER_LINEIN_C] = { .ctl = 1, - .name = "Line-in Capture Volume", + .name = "Line Capture Volume", }, [MIXER_MIC_P] = { .ctl = 1, @@ -153,15 +151,15 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { }, [MIXER_SPDIFI_P] = { .ctl = 1, - .name = "S/PDIF-in Playback Volume", + .name = "IEC958 Playback Volume", }, [MIXER_SPDIFI_C] = { .ctl = 1, - .name = "S/PDIF-in Capture Volume", + .name = "IEC958 Capture Volume", }, [MIXER_SPDIFO_P] = { .ctl = 1, - .name = "S/PDIF-out Playback Volume", + .name = "Digital Playback Volume", }, [MIXER_WAVEF_P] = { .ctl = 1, @@ -179,14 +177,13 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { .ctl = 1, .name = "Surround Playback Volume", }, - [MIXER_PCM_C_S] = { .ctl = 1, .name = "PCM Capture Switch", }, [MIXER_LINEIN_C_S] = { .ctl = 1, - .name = "Line-in Capture Switch", + .name = "Line Capture Switch", }, [MIXER_MIC_C_S] = { .ctl = 1, @@ -194,19 +191,11 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = { }, [MIXER_SPDIFI_C_S] = { .ctl = 1, - .name = "S/PDIF-in Capture Switch", - }, - [MIXER_LINEIN_P_S] = { - .ctl = 1, - .name = "Line-in Playback Switch", + .name = "IEC958 Capture Switch", }, [MIXER_SPDIFO_P_S] = { .ctl = 1, - .name = "S/PDIF-out Playback Switch", - }, - [MIXER_SPDIFI_P_S] = { - .ctl = 1, - .name = "S/PDIF-in Playback Switch", + .name = "Digital Playback Switch", }, [MIXER_WAVEF_P_S] = { .ctl = 1, @@ -236,6 +225,8 @@ ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); static void ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); +/* FIXME: this static looks like it would fail if more than one card was */ +/* installed. */ static struct snd_kcontrol *kctls[2] = {NULL}; static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index) @@ -420,6 +411,77 @@ static struct snd_kcontrol_new vol_ctl = { .tlv = { .p = ct_vol_db_scale }, }; +static int output_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + static const char *const names[3] = { + "FP Headphones", "Headphones", "Speakers" + }; + + return snd_ctl_enum_info(info, 1, 3, names); +} + +static int output_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct ct_atc *atc = snd_kcontrol_chip(kcontrol); + ucontrol->value.enumerated.item[0] = atc->output_switch_get(atc); + return 0; +} + +static int output_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct ct_atc *atc = snd_kcontrol_chip(kcontrol); + if (ucontrol->value.enumerated.item[0] > 2) + return -EINVAL; + return atc->output_switch_put(atc, ucontrol->value.enumerated.item[0]); +} + +static struct snd_kcontrol_new output_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog Output Playback Enum", + .info = output_switch_info, + .get = output_switch_get, + .put = output_switch_put, +}; + +static int mic_source_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *info) +{ + static const char *const names[3] = { + "Mic", "FP Mic", "Aux" + }; + + return snd_ctl_enum_info(info, 1, 3, names); +} + +static int mic_source_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct ct_atc *atc = snd_kcontrol_chip(kcontrol); + ucontrol->value.enumerated.item[0] = atc->mic_source_switch_get(atc); + return 0; +} + +static int mic_source_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct ct_atc *atc = snd_kcontrol_chip(kcontrol); + if (ucontrol->value.enumerated.item[0] > 2) + return -EINVAL; + return atc->mic_source_switch_put(atc, + ucontrol->value.enumerated.item[0]); +} + +static struct snd_kcontrol_new mic_source_ctl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Mic Source Capture Enum", + .info = mic_source_switch_info, + .get = mic_source_switch_get, + .put = mic_source_switch_put, +}; + static void do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type) { @@ -465,6 +527,7 @@ do_digit_io_switch(struct ct_atc *atc, int state) static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) { struct ct_mixer *mixer = atc->mixer; + struct capabilities cap = atc->capabilities(atc); /* Do changes in mixer. */ if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { @@ -477,8 +540,17 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) } } /* Do changes out of mixer. */ - if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) - do_line_mic_switch(atc, type); + if (!cap.dedicated_mic && + (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) { + if (state) + do_line_mic_switch(atc, type); + atc->line_in_unmute(atc, state); + } else if (cap.dedicated_mic && (MIXER_LINEIN_C_S == type)) + atc->line_in_unmute(atc, state); + else if (cap.dedicated_mic && (MIXER_MIC_C_S == type)) + atc->mic_unmute(atc, state); + else if (MIXER_SPDIFI_C_S == type) + atc->spdif_in_unmute(atc, state); else if (MIXER_WAVEF_P_S == type) atc->line_front_unmute(atc, state); else if (MIXER_WAVES_P_S == type) @@ -487,12 +559,8 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) atc->line_clfe_unmute(atc, state); else if (MIXER_WAVER_P_S == type) atc->line_rear_unmute(atc, state); - else if (MIXER_LINEIN_P_S == type) - atc->line_in_unmute(atc, state); else if (MIXER_SPDIFO_P_S == type) atc->spdif_out_unmute(atc, state); - else if (MIXER_SPDIFI_P_S == type) - atc->spdif_in_unmute(atc, state); else if (MIXER_DIGITAL_IO_S == type) do_digit_io_switch(atc, state); @@ -671,6 +739,7 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) { enum CTALSA_MIXER_CTL type; struct ct_atc *atc = mixer->atc; + struct capabilities cap = atc->capabilities(atc); int err; /* Create snd kcontrol instances on demand */ @@ -684,8 +753,8 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) } } - ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = - atc->have_digit_io_switch(atc); + ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = cap.digit_io_switch; + for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) { if (ct_kcontrol_init_table[type].ctl) { swh_ctl.name = ct_kcontrol_init_table[type].name; @@ -708,6 +777,17 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) if (err) return err; + if (cap.output_switch) { + err = ct_mixer_kcontrol_new(mixer, &output_ctl); + if (err) + return err; + } + + if (cap.mic_source_switch) { + err = ct_mixer_kcontrol_new(mixer, &mic_source_ctl); + if (err) + return err; + } atc->line_front_unmute(atc, 1); set_switch_state(mixer, MIXER_WAVEF_P_S, 1); atc->line_surround_unmute(atc, 0); @@ -719,13 +799,12 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer) atc->spdif_out_unmute(atc, 0); set_switch_state(mixer, MIXER_SPDIFO_P_S, 0); atc->line_in_unmute(atc, 0); - set_switch_state(mixer, MIXER_LINEIN_P_S, 0); + if (cap.dedicated_mic) + atc->mic_unmute(atc, 0); atc->spdif_in_unmute(atc, 0); - set_switch_state(mixer, MIXER_SPDIFI_P_S, 0); - - set_switch_state(mixer, MIXER_PCM_C_S, 1); - set_switch_state(mixer, MIXER_LINEIN_C_S, 1); - set_switch_state(mixer, MIXER_SPDIFI_C_S, 1); + set_switch_state(mixer, MIXER_PCM_C_S, 0); + set_switch_state(mixer, MIXER_LINEIN_C_S, 0); + set_switch_state(mixer, MIXER_SPDIFI_C_S, 0); return 0; } diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index d20ddfee2c1f..b259aa03a3a9 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c @@ -80,11 +80,11 @@ ct_card_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) "are 48000 and 44100, Value 48000 is assumed.\n"); reference_rate = 48000; } - if ((multiple != 1) && (multiple != 2)) { + if ((multiple != 1) && (multiple != 2) && (multiple != 4)) { printk(KERN_ERR "ctxfi: Invalid multiple value %u!!!\n", multiple); printk(KERN_ERR "ctxfi: The valid values for multiple are " - "1 and 2, Value 2 is assumed.\n"); + "1, 2 and 4, Value 2 is assumed.\n"); multiple = 2; } err = ct_atc_create(card, pci, reference_rate, multiple, diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 8733790af90a..fcd4935766b2 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1440,6 +1440,14 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0102_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ + /* EMU0404 PCIe */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102, + .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]", + .id = "EMU0404", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */ /* Note that all E-mu cards require kernel 2.6 or newer. */ {.vendor = 0x1102, .device = 0x0008, .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index f1de1bac042c..4967eabe774e 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -50,7 +50,12 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable); int snd_hda_attach_beep_device(struct hda_codec *codec, int nid); void snd_hda_detach_beep_device(struct hda_codec *codec); #else -#define snd_hda_attach_beep_device(...) 0 -#define snd_hda_detach_beep_device(...) +static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) +{ + return 0; +} +void snd_hda_detach_beep_device(struct hda_codec *codec) +{ +} #endif #endif diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 3e6b9a8539c2..694b9daf691f 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3102,6 +3102,7 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */ + SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO), {} }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7a4e10002f56..61a774b3d3cb 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1141,6 +1141,13 @@ static void update_speakers(struct hda_codec *codec) struct alc_spec *spec = codec->spec; int on; + /* Control HP pins/amps depending on master_mute state; + * in general, HP pins/amps control should be enabled in all cases, + * but currently set only for master_mute, just to be safe + */ + do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins), + spec->autocfg.hp_pins, spec->master_mute, true); + if (!spec->automute) on = 0; else @@ -6201,11 +6208,6 @@ static const struct snd_kcontrol_new alc260_input_mixer[] = { /* update HP, line and mono out pins according to the master switch */ static void alc260_hp_master_update(struct hda_codec *codec) { - struct alc_spec *spec = codec->spec; - - /* change HP pins */ - do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins), - spec->autocfg.hp_pins, spec->master_mute, true); update_speakers(codec); } @@ -11924,7 +11926,7 @@ static const struct hda_verb alc262_nec_verbs[] = { * 0x1b = port replicator headphone out */ -#define ALC_HP_EVENT 0x37 +#define ALC_HP_EVENT ALC880_HP_EVENT static const struct hda_verb alc262_fujitsu_unsol_verbs[] = { {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, @@ -13314,9 +13316,8 @@ static void alc268_acer_lc_setup(struct hda_codec *codec) struct alc_spec *spec = codec->spec; spec->autocfg.hp_pins[0] = 0x15; spec->autocfg.speaker_pins[0] = 0x14; - spec->automute_mixer_nid[0] = 0x0f; spec->automute = 1; - spec->automute_mode = ALC_AUTOMUTE_MIXER; + spec->automute_mode = ALC_AUTOMUTE_AMP; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; @@ -13860,6 +13861,7 @@ static const struct snd_pci_quirk alc268_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One", ALC268_ACER_ASPIRE_ONE), SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL), + SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO), SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0, "Dell Inspiron Mini9/Vostro A90", ALC268_DELL), /* almost compatible with toshiba but with optional digital outs; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 32d0c9c35007..c640f47b48bd 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -521,6 +521,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) /* revisions >= 230 indicate AES32 card */ +#define HDSPM_MADI_OLD_REV 207 #define HDSPM_MADI_REV 210 #define HDSPM_RAYDAT_REV 211 #define HDSPM_AIO_REV 212 @@ -1143,7 +1144,7 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) /* if wordclock has synced freq and wordclock is valid */ if ((status2 & HDSPM_wcLock) != 0 && - (status & HDSPM_SelSyncRef0) == 0) { + (status2 & HDSPM_SelSyncRef0) == 0) { rate_bits = status2 & HDSPM_wcFreqMask; @@ -1639,12 +1640,14 @@ static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) } } hmidi->pending = 0; + spin_unlock_irqrestore(&hmidi->lock, flags); + spin_lock_irqsave(&hmidi->hdspm->lock, flags); hmidi->hdspm->control_register |= hmidi->ie; hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register); + spin_unlock_irqrestore(&hmidi->hdspm->lock, flags); - spin_unlock_irqrestore (&hmidi->lock, flags); return snd_hdspm_midi_output_write (hmidi); } @@ -6377,6 +6380,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, switch (hdspm->firmware_rev) { case HDSPM_MADI_REV: + case HDSPM_MADI_OLD_REV: hdspm->io_type = MADI; hdspm->card_name = "RME MADI"; hdspm->midiPorts = 3; diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index 7fbfa051f6e1..eda955b15834 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -848,9 +848,10 @@ int atmel_ssc_set_audio(int ssc_id) if (IS_ERR(ssc)) pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n", PTR_ERR(ssc)); - else + else { ssc_pdev->dev.parent = &(ssc->pdev->dev); - ssc_free(ssc); + ssc_free(ssc); + } ret = platform_device_add(ssc_pdev); if (ret < 0) diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index ea4951cf5526..f79d1655e035 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c @@ -75,7 +75,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { .cpu_dai_name = "bfin-tdm.0", .codec_dai_name = "ad1836-hifi", .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "ad1836.0", + .codec_name = "spi0.4", .ops = &bf5xx_ad1836_ops, }, { @@ -84,7 +84,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { .cpu_dai_name = "bfin-tdm.1", .codec_dai_name = "ad1836-hifi", .platform_name = "bfin-tdm-pcm-audio", - .codec_name = "ad1836.0", + .codec_name = "spi0.4", .ops = &bf5xx_ad1836_ops, }, }; diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index ab63d52e36e1..754c496412bd 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -145,22 +145,22 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - word_len = 3; + word_len = AD1836_WORD_LEN_16; break; case SNDRV_PCM_FORMAT_S20_3LE: - word_len = 1; + word_len = AD1836_WORD_LEN_20; break; case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S32_LE: - word_len = 0; + word_len = AD1836_WORD_LEN_24; break; } - snd_soc_update_bits(codec, AD1836_DAC_CTRL1, - AD1836_DAC_WORD_LEN_MASK, word_len); + snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK, + word_len << AD1836_DAC_WORD_LEN_OFFSET); - snd_soc_update_bits(codec, AD1836_ADC_CTRL2, - AD1836_ADC_WORD_LEN_MASK, word_len); + snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK, + word_len << AD1836_ADC_WORD_OFFSET); return 0; } diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h index 845596717fdf..9d6a3f8f8aaf 100644 --- a/sound/soc/codecs/ad1836.h +++ b/sound/soc/codecs/ad1836.h @@ -25,6 +25,7 @@ #define AD1836_DAC_SERFMT_PCK256 (0x4 << 5) #define AD1836_DAC_SERFMT_PCK128 (0x5 << 5) #define AD1836_DAC_WORD_LEN_MASK 0x18 +#define AD1836_DAC_WORD_LEN_OFFSET 3 #define AD1836_DAC_CTRL2 1 #define AD1836_DACL1_MUTE 0 @@ -51,6 +52,7 @@ #define AD1836_ADCL2_MUTE 2 #define AD1836_ADCR2_MUTE 3 #define AD1836_ADC_WORD_LEN_MASK 0x30 +#define AD1836_ADC_WORD_OFFSET 5 #define AD1836_ADC_SERFMT_MASK (7 << 6) #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) @@ -60,4 +62,8 @@ #define AD1836_NUM_REGS 16 +#define AD1836_WORD_LEN_24 0x0 +#define AD1836_WORD_LEN_20 0x1 +#define AD1836_WORD_LEN_16 0x2 + #endif diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 6785688f8806..9a5e67c5a6bd 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c @@ -680,20 +680,25 @@ static struct snd_soc_dai_ops wm8804_dai_ops = { #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE) +#define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ + SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) + static struct snd_soc_dai_driver wm8804_dai = { .name = "wm8804-spdif", .playback = { .stream_name = "Playback", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = WM8804_RATES, .formats = WM8804_FORMATS, }, .capture = { .stream_name = "Capture", .channels_min = 2, .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, + .rates = WM8804_RATES, .formats = WM8804_FORMATS, }, .ops = &wm8804_dai_ops, diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c index a0b1a7278284..e2ab4fac2819 100644 --- a/sound/soc/codecs/wm8915.c +++ b/sound/soc/codecs/wm8915.c @@ -1839,7 +1839,7 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai, int old; /* Disable SYSCLK while we reconfigure */ - old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1); + old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA; snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, WM8915_SYSCLK_ENA, 0); @@ -2038,6 +2038,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source, break; case WM8915_FLL_MCLK2: reg = 1; + break; case WM8915_FLL_DACLRCLK1: reg = 2; break; diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index f90ae427242b..5e05eed96c38 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1999,12 +1999,12 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, return 0; /* If the left PGA is enabled hit that VU bit... */ - if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTL_PGA_ENA) + if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA) return snd_soc_write(codec, WM8962_HPOUTL_VOLUME, reg_cache[WM8962_HPOUTL_VOLUME]); /* ...otherwise the right. The VU is stereo. */ - if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTR_PGA_ENA) + if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA) return snd_soc_write(codec, WM8962_HPOUTR_VOLUME, reg_cache[WM8962_HPOUTR_VOLUME]); diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 15dac0f20cd8..6680c0b4d203 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -310,7 +310,7 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, * should allocate a DMA buffer only for the streams that are valid. */ - if (dai->driver->playback.channels_min) { + if (pcm->streams[0].substream) { ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, fsl_dma_hardware.buffer_bytes_max, &pcm->streams[0].substream->dma_buffer); @@ -320,13 +320,13 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, } } - if (dai->driver->capture.channels_min) { + if (pcm->streams[1].substream) { ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, fsl_dma_hardware.buffer_bytes_max, &pcm->streams[1].substream->dma_buffer); if (ret) { - snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); dev_err(card->dev, "can't alloc capture dma buffer\n"); + snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); return ret; } } @@ -449,7 +449,8 @@ static int fsl_dma_open(struct snd_pcm_substream *substream) dma_private->ld_buf_phys = ld_buf_phys; dma_private->dma_buf_phys = substream->dma_buffer.addr; - ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private); + ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "fsldma-audio", + dma_private); if (ret) { dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n", dma_private->irq, ret); diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index ffa09b3b2caa..992a732b5211 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -191,7 +191,7 @@ static inline bool tx_active(struct i2s_dai *i2s) if (!i2s) return false; - active = readl(i2s->addr + I2SMOD); + active = readl(i2s->addr + I2SCON); if (is_secondary(i2s)) active &= CON_TXSDMA_ACTIVE; @@ -223,7 +223,7 @@ static inline bool rx_active(struct i2s_dai *i2s) if (!i2s) return false; - active = readl(i2s->addr + I2SMOD) & CON_RXDMA_ACTIVE; + active = readl(i2s->addr + I2SCON) & CON_RXDMA_ACTIVE; return active ? true : false; } diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 06b7b81a1601..c005ceb70c9d 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -466,6 +466,9 @@ static bool snd_soc_set_cache_val(void *base, unsigned int idx, static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx, unsigned int word_size) { + if (!base) + return -1; + switch (word_size) { case 1: { const u8 *cache = base; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 776e6f418306..32ab7fc4579a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -350,9 +350,9 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm, } /* create new dapm mixer control */ -static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, - struct snd_soc_dapm_widget *w) +static int dapm_new_mixer(struct snd_soc_dapm_widget *w) { + struct snd_soc_dapm_context *dapm = w->dapm; int i, ret = 0; size_t name_len, prefix_len; struct snd_soc_dapm_path *path; @@ -450,9 +450,9 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, } /* create new dapm mux control */ -static int dapm_new_mux(struct snd_soc_dapm_context *dapm, - struct snd_soc_dapm_widget *w) +static int dapm_new_mux(struct snd_soc_dapm_widget *w) { + struct snd_soc_dapm_context *dapm = w->dapm; struct snd_soc_dapm_path *path = NULL; struct snd_kcontrol *kcontrol; struct snd_card *card = dapm->card->snd_card; @@ -535,8 +535,7 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm, } /* create new dapm volume control */ -static int dapm_new_pga(struct snd_soc_dapm_context *dapm, - struct snd_soc_dapm_widget *w) +static int dapm_new_pga(struct snd_soc_dapm_widget *w) { if (w->num_kcontrols) dev_err(w->dapm->dev, @@ -1826,13 +1825,13 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) case snd_soc_dapm_mixer: case snd_soc_dapm_mixer_named_ctl: w->power_check = dapm_generic_check_power; - dapm_new_mixer(dapm, w); + dapm_new_mixer(w); break; case snd_soc_dapm_mux: case snd_soc_dapm_virt_mux: case snd_soc_dapm_value_mux: w->power_check = dapm_generic_check_power; - dapm_new_mux(dapm, w); + dapm_new_mux(w); break; case snd_soc_dapm_adc: case snd_soc_dapm_aif_out: @@ -1845,7 +1844,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm) case snd_soc_dapm_pga: case snd_soc_dapm_out_drv: w->power_check = dapm_generic_check_power; - dapm_new_pga(dapm, w); + dapm_new_pga(w); break; case snd_soc_dapm_input: case snd_soc_dapm_output: diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index a91719d5918b..1e3ae3327dd3 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c @@ -270,7 +270,6 @@ static int usb6fire_fw_ezusb_upload( data = 0x00; /* resume ezusb cpu */ ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1); if (ret < 0) { - release_firmware(fw); snd_printk(KERN_ERR PREFIX "unable to upload ezusb " "firmware %s: end message.\n", fwname); return ret; |