diff options
-rw-r--r-- | sound/core/pcm_native.c | 2 | ||||
-rw-r--r-- | sound/core/seq/seq_midi_event.c | 8 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctatc.c | 206 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctatc.h | 7 | ||||
-rw-r--r-- | sound/pci/ctxfi/cthardware.h | 7 | ||||
-rw-r--r-- | sound/pci/ctxfi/cthw20k1.c | 83 | ||||
-rw-r--r-- | sound/pci/ctxfi/cthw20k2.c | 65 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctmixer.c | 92 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctmixer.h | 3 | ||||
-rw-r--r-- | sound/pci/ctxfi/ctpcm.c | 4 | ||||
-rw-r--r-- | sound/pci/ctxfi/xfi.c | 22 | ||||
-rw-r--r-- | sound/pci/hda/Kconfig | 9 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 109 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 10 | ||||
-rw-r--r-- | sound/pci/via82xx.c | 6 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-i2s.c | 10 |
17 files changed, 464 insertions, 183 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 84da3ba..ac2150e 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -320,7 +320,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, snd_mask_max(¶ms->masks[SNDRV_PCM_HW_PARAM_CHANNELS])) { changed = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_FIFO_SIZE, params); - if (params < 0) + if (changed < 0) return changed; } } diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 8284f17..b5d6ea4 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c @@ -504,10 +504,10 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, if (dev->nostat && count < 12) return -ENOMEM; cmd = MIDI_CMD_CONTROL|(ev->data.control.channel & 0x0f); - bytes[0] = ev->data.control.param & 0x007f; - bytes[1] = (ev->data.control.param & 0x3f80) >> 7; - bytes[2] = ev->data.control.value & 0x007f; - bytes[3] = (ev->data.control.value & 0x3f80) >> 7; + bytes[0] = (ev->data.control.param & 0x3f80) >> 7; + bytes[1] = ev->data.control.param & 0x007f; + bytes[2] = (ev->data.control.value & 0x3f80) >> 7; + bytes[3] = ev->data.control.value & 0x007f; if (cmd != dev->lastcmd && !dev->nostat) { if (count < 9) return -ENOMEM; diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index b0adc80..a49c766 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -46,8 +46,6 @@ static struct snd_pci_quirk __devinitdata subsys_20k1_list[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0031, "SB073x", CTSB073X), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_CREATIVE, 0xf000, 0x6000, "UAA", CTUAA), - SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_CREATIVE, - "Unknown", CT20K1_UNKNOWN), { } /* terminator */ }; @@ -67,13 +65,16 @@ static struct snd_pci_quirk __devinitdata subsys_20k2_list[] = { }; static const char *ct_subsys_name[NUM_CTCARDS] = { + /* 20k1 models */ [CTSB055X] = "SB055x", [CTSB073X] = "SB073x", - [CTSB0760] = "SB076x", [CTUAA] = "UAA", [CT20K1_UNKNOWN] = "Unknown", + /* 20k2 models */ + [CTSB0760] = "SB076x", [CTHENDRIX] = "Hendrix", [CTSB0880] = "SB0880", + [CT20K2_UNKNOWN] = "Unknown", }; static struct { @@ -260,13 +261,8 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) int device = apcm->substream->pcm->device; unsigned int pitch; - if (NULL != apcm->src) { - /* Prepared pcm playback */ - return 0; - } - /* first release old resources */ - atc->pcm_release_resources(atc, apcm); + atc_pcm_release_resources(atc, apcm); /* Get SRC resource */ desc.multi = apcm->substream->runtime->channels; @@ -660,10 +656,7 @@ static int atc_pcm_capture_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) unsigned int pitch; int mix_base = 0, imp_base = 0; - if (NULL != apcm->src) { - /* Prepared pcm capture */ - return 0; - } + atc_pcm_release_resources(atc, apcm); /* Get needed resources. */ err = atc_pcm_capture_get_resources(atc, apcm); @@ -866,7 +859,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) struct dao *dao = container_of(atc->daios[SPDIFOO], struct dao, daio); unsigned int rate = apcm->substream->runtime->rate; unsigned int status; - int err; + int err = 0; unsigned char iec958_con_fs; switch (rate) { @@ -907,8 +900,7 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) int err; int i; - if (NULL != apcm->src) - return 0; + atc_pcm_release_resources(atc, apcm); /* Configure SPDIFOO and PLL to passthrough mode; * determine pll_rate. */ @@ -1115,32 +1107,20 @@ static int atc_spdif_out_passthru(struct ct_atc *atc, unsigned char state) return err; } -static int ct_atc_destroy(struct ct_atc *atc) +static int atc_release_resources(struct ct_atc *atc) { - struct daio_mgr *daio_mgr; - struct dao *dao; - struct dai *dai; - struct daio *daio; - struct sum_mgr *sum_mgr; - struct src_mgr *src_mgr; - struct srcimp_mgr *srcimp_mgr; - struct srcimp *srcimp; - struct ct_mixer *mixer; - int i = 0; - - if (NULL == atc) - return 0; - - if (atc->timer) { - ct_timer_free(atc->timer); - atc->timer = NULL; - } - - /* Stop hardware and disable all interrupts */ - if (NULL != atc->hw) - ((struct hw *)atc->hw)->card_stop(atc->hw); - - /* Destroy internal mixer objects */ + int i; + struct daio_mgr *daio_mgr = NULL; + struct dao *dao = NULL; + struct dai *dai = NULL; + struct daio *daio = NULL; + struct sum_mgr *sum_mgr = NULL; + struct src_mgr *src_mgr = NULL; + struct srcimp_mgr *srcimp_mgr = NULL; + struct srcimp *srcimp = NULL; + struct ct_mixer *mixer = NULL; + + /* disconnect internal mixer objects */ if (NULL != atc->mixer) { mixer = atc->mixer; mixer->set_input_left(mixer, MIX_LINE_IN, NULL); @@ -1149,7 +1129,6 @@ static int ct_atc_destroy(struct ct_atc *atc) mixer->set_input_right(mixer, MIX_MIC_IN, NULL); mixer->set_input_left(mixer, MIX_SPDIF_IN, NULL); mixer->set_input_right(mixer, MIX_SPDIF_IN, NULL); - ct_mixer_destroy(atc->mixer); } if (NULL != atc->daios) { @@ -1167,6 +1146,7 @@ static int ct_atc_destroy(struct ct_atc *atc) daio_mgr->put_daio(daio_mgr, daio); } kfree(atc->daios); + atc->daios = NULL; } if (NULL != atc->pcm) { @@ -1175,6 +1155,7 @@ static int ct_atc_destroy(struct ct_atc *atc) sum_mgr->put_sum(sum_mgr, atc->pcm[i]); kfree(atc->pcm); + atc->pcm = NULL; } if (NULL != atc->srcs) { @@ -1183,6 +1164,7 @@ static int ct_atc_destroy(struct ct_atc *atc) src_mgr->put_src(src_mgr, atc->srcs[i]); kfree(atc->srcs); + atc->srcs = NULL; } if (NULL != atc->srcimps) { @@ -1193,8 +1175,30 @@ static int ct_atc_destroy(struct ct_atc *atc) srcimp_mgr->put_srcimp(srcimp_mgr, atc->srcimps[i]); } kfree(atc->srcimps); + atc->srcimps = NULL; + } + + return 0; +} + +static int ct_atc_destroy(struct ct_atc *atc) +{ + int i = 0; + + if (NULL == atc) + return 0; + + if (atc->timer) { + ct_timer_free(atc->timer); + atc->timer = NULL; } + atc_release_resources(atc); + + /* Destroy internal mixer objects */ + if (NULL != atc->mixer) + ct_mixer_destroy(atc->mixer); + for (i = 0; i < NUM_RSCTYP; i++) { if ((NULL != rsc_mgr_funcs[i].destroy) && (NULL != atc->rsc_mgrs[i])) @@ -1240,9 +1244,21 @@ static int __devinit atc_identify_card(struct ct_atc *atc) return -ENOENT; } p = snd_pci_quirk_lookup(atc->pci, list); - if (!p) - return -ENOENT; - atc->model = p->value; + if (p) { + if (p->value < 0) { + printk(KERN_ERR "ctxfi: " + "Device %04x:%04x is black-listed\n", + atc->pci->subsystem_vendor, + atc->pci->subsystem_device); + return -ENOENT; + } + atc->model = p->value; + } else { + if (atc->chip_type == ATC20K1) + atc->model = CT20K1_UNKNOWN; + else + atc->model = CT20K2_UNKNOWN; + } atc->model_name = ct_subsys_name[atc->model]; snd_printd("ctxfi: chip %s model %s (%04x:%04x) is found\n", atc->chip_name, atc->model_name, @@ -1310,7 +1326,7 @@ static int __devinit atc_create_hw_devs(struct ct_atc *atc) return 0; } -static int __devinit atc_get_resources(struct ct_atc *atc) +static int atc_get_resources(struct ct_atc *atc) { struct daio_desc da_desc = {0}; struct daio_mgr *daio_mgr; @@ -1407,16 +1423,10 @@ static int __devinit atc_get_resources(struct ct_atc *atc) atc->n_pcm++; } - err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer); - if (err) { - printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n"); - return err; - } - return 0; } -static void __devinit +static void atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai, struct src **srcs, struct srcimp **srcimps) { @@ -1455,7 +1465,7 @@ atc_connect_dai(struct src_mgr *src_mgr, struct dai *dai, src_mgr->commit_write(src_mgr); /* Synchronously enable SRCs */ } -static void __devinit atc_connect_resources(struct ct_atc *atc) +static void atc_connect_resources(struct ct_atc *atc) { struct dai *dai; struct dao *dao; @@ -1501,6 +1511,84 @@ static void __devinit atc_connect_resources(struct ct_atc *atc) } } +#ifdef CONFIG_PM +static int atc_suspend(struct ct_atc *atc, pm_message_t state) +{ + int i; + struct hw *hw = atc->hw; + + snd_power_change_state(atc->card, SNDRV_CTL_POWER_D3hot); + + for (i = FRONT; i < NUM_PCMS; i++) { + if (!atc->pcms[i]) + continue; + + snd_pcm_suspend_all(atc->pcms[i]); + } + + atc_release_resources(atc); + + hw->suspend(hw, state); + + return 0; +} + +static int atc_hw_resume(struct ct_atc *atc) +{ + struct hw *hw = atc->hw; + struct card_conf info = {0}; + + /* Re-initialize card hardware. */ + info.rsr = atc->rsr; + info.msr = atc->msr; + info.vm_pgt_phys = atc_get_ptp_phys(atc, 0); + return hw->resume(hw, &info); +} + +static int atc_resources_resume(struct ct_atc *atc) +{ + struct ct_mixer *mixer; + int err = 0; + + /* Get resources */ + err = atc_get_resources(atc); + if (err < 0) { + atc_release_resources(atc); + return err; + } + + /* Build topology */ + atc_connect_resources(atc); + + mixer = atc->mixer; + mixer->resume(mixer); + + return 0; +} + +static int atc_resume(struct ct_atc *atc) +{ + int err = 0; + + /* Do hardware resume. */ + err = atc_hw_resume(atc); + if (err < 0) { + printk(KERN_ERR "ctxfi: pci_enable_device failed, " + "disabling device\n"); + snd_card_disconnect(atc->card); + return err; + } + + err = atc_resources_resume(atc); + if (err < 0) + return err; + + snd_power_change_state(atc->card, SNDRV_CTL_POWER_D0); + + return 0; +} +#endif + static struct ct_atc atc_preset __devinitdata = { .map_audio_buffer = ct_map_audio_buffer, .unmap_audio_buffer = ct_unmap_audio_buffer, @@ -1529,6 +1617,10 @@ static struct ct_atc atc_preset __devinitdata = { .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, +#ifdef CONFIG_PM + .suspend = atc_suspend, + .resume = atc_resume, +#endif }; /** @@ -1587,6 +1679,12 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, if (err < 0) goto error1; + err = ct_mixer_create(atc, (struct ct_mixer **)&atc->mixer); + if (err) { + printk(KERN_ERR "ctxfi: Failed to create mixer obj!!!\n"); + goto error1; + } + /* Get resources */ err = atc_get_resources(atc); if (err < 0) diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h index 9fe620ea..9fd8a57 100644 --- a/sound/pci/ctxfi/ctatc.h +++ b/sound/pci/ctxfi/ctatc.h @@ -136,6 +136,13 @@ struct ct_atc { unsigned char n_pcm; struct ct_timer *timer; + +#ifdef CONFIG_PM + int (*suspend)(struct ct_atc *atc, pm_message_t state); + int (*resume)(struct ct_atc *atc); +#define NUM_PCMS (NUM_CTALSADEVS - 1) + struct snd_pcm *pcms[NUM_PCMS]; +#endif }; diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h index 4a8e04f..af55405 100644 --- a/sound/pci/ctxfi/cthardware.h +++ b/sound/pci/ctxfi/cthardware.h @@ -30,13 +30,16 @@ enum CHIPTYP { enum CTCARDS { /* 20k1 models */ CTSB055X, + CT20K1_MODEL_FIRST = CTSB055X, CTSB073X, CTUAA, CT20K1_UNKNOWN, /* 20k2 models */ CTSB0760, + CT20K2_MODEL_FIRST = CTSB0760, CTHENDRIX, CTSB0880, + CT20K2_UNKNOWN, NUM_CTCARDS /* This should always be the last */ }; @@ -61,6 +64,10 @@ struct hw { int (*card_init)(struct hw *hw, struct card_conf *info); int (*card_stop)(struct hw *hw); int (*pll_init)(struct hw *hw, unsigned int rsr); +#ifdef CONFIG_PM + int (*suspend)(struct hw *hw, pm_message_t state); + int (*resume)(struct hw *hw, struct card_conf *info); +#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); diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index cb69d9d..ad3e1d1 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c @@ -1911,9 +1911,17 @@ static int hw_card_start(struct hw *hw) goto error1; } - err = pci_request_regions(pci, "XFi"); - if (err < 0) - goto error1; + if (!hw->io_base) { + err = pci_request_regions(pci, "XFi"); + if (err < 0) + goto error1; + + if (hw->model == CTUAA) + hw->io_base = pci_resource_start(pci, 5); + else + hw->io_base = pci_resource_start(pci, 0); + + } /* Switch to X-Fi mode from UAA mode if neeeded */ if (hw->model == CTUAA) { @@ -1921,18 +1929,17 @@ static int hw_card_start(struct hw *hw) if (err) goto error2; - hw->io_base = pci_resource_start(pci, 5); - } else { - hw->io_base = pci_resource_start(pci, 0); } - err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, - "ctxfi", hw); - if (err < 0) { - printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); - goto error2; + if (hw->irq < 0) { + err = request_irq(pci->irq, ct_20k1_interrupt, IRQF_SHARED, + "ctxfi", hw); + if (err < 0) { + printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); + goto error2; + } + hw->irq = pci->irq; } - hw->irq = pci->irq; pci_set_master(pci); @@ -1948,6 +1955,15 @@ error1: static int hw_card_stop(struct hw *hw) { + unsigned int data; + + /* disable transport bus master and queueing of request */ + hw_write_20kx(hw, TRNCTL, 0x00); + + /* disable pll */ + data = hw_read_20kx(hw, PLLCTL); + hw_write_20kx(hw, PLLCTL, (data & (~(0x0F<<12)))); + /* TODO: Disable interrupt and so on... */ if (hw->irq >= 0) synchronize_irq(hw->irq); @@ -1987,11 +2003,9 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) struct trn_conf trn_info = {0}; /* Get PCI io port base address and do Hendrix switch if needed. */ - if (!hw->io_base) { - err = hw_card_start(hw); - if (err) - return err; - } + err = hw_card_start(hw); + if (err) + return err; /* PLL init */ err = hw_pll_init(hw, info->rsr); @@ -2064,6 +2078,37 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) return 0; } +#ifdef CONFIG_PM +static int hw_suspend(struct hw *hw, pm_message_t state) +{ + struct pci_dev *pci = hw->pci; + + hw_card_stop(hw); + + if (hw->model == CTUAA) { + /* Switch to UAA config space. */ + pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x0); + } + + pci_disable_device(pci); + pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); + + return 0; +} + +static int hw_resume(struct hw *hw, struct card_conf *info) +{ + struct pci_dev *pci = hw->pci; + + pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + + /* Re-initialize card hardware. */ + return hw_card_init(hw, info); +} +#endif + static u32 hw_read_20kx(struct hw *hw, u32 reg) { u32 value; @@ -2128,6 +2173,10 @@ static struct hw ct20k1_preset __devinitdata = { .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, +#ifdef CONFIG_PM + .suspend = hw_suspend, + .resume = hw_resume, +#endif .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 4493a51..dec46d0 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c @@ -1860,16 +1860,18 @@ static int hw_card_start(struct hw *hw) goto error1; } - err = pci_request_regions(pci, "XFi"); - if (err < 0) - goto error1; + if (!hw->io_base) { + err = pci_request_regions(pci, "XFi"); + if (err < 0) + goto error1; - hw->io_base = pci_resource_start(hw->pci, 2); - hw->mem_base = (unsigned long)ioremap(hw->io_base, + hw->io_base = pci_resource_start(hw->pci, 2); + hw->mem_base = (unsigned long)ioremap(hw->io_base, pci_resource_len(hw->pci, 2)); - if (NULL == (void *)hw->mem_base) { - err = -ENOENT; - goto error2; + if (NULL == (void *)hw->mem_base) { + err = -ENOENT; + goto error2; + } } /* Switch to 20k2 mode from UAA mode. */ @@ -1901,6 +1903,15 @@ error1: static int hw_card_stop(struct hw *hw) { + unsigned int data; + + /* disable transport bus master and queueing of request */ + hw_write_20kx(hw, TRANSPORT_CTL, 0x00); + + /* disable pll */ + data = hw_read_20kx(hw, PLL_ENB); + hw_write_20kx(hw, PLL_ENB, (data & (~0x07))); + /* TODO: Disable interrupt and so on... */ return 0; } @@ -1939,11 +1950,9 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) /* Get PCI io port/memory base address and * do 20kx core switch if needed. */ - if (!hw->io_base) { - err = hw_card_start(hw); - if (err) - return err; - } + err = hw_card_start(hw); + if (err) + return err; /* PLL init */ err = hw_pll_init(hw, info->rsr); @@ -2006,6 +2015,32 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) return 0; } +#ifdef CONFIG_PM +static int hw_suspend(struct hw *hw, pm_message_t state) +{ + struct pci_dev *pci = hw->pci; + + hw_card_stop(hw); + + pci_disable_device(pci); + pci_save_state(pci); + pci_set_power_state(pci, pci_choose_state(pci, state)); + + return 0; +} + +static int hw_resume(struct hw *hw, struct card_conf *info) +{ + struct pci_dev *pci = hw->pci; + + pci_set_power_state(pci, PCI_D0); + pci_restore_state(pci); + + /* Re-initialize card hardware. */ + return hw_card_init(hw, info); +} +#endif + static u32 hw_read_20kx(struct hw *hw, u32 reg) { return readl((void *)(hw->mem_base + reg)); @@ -2025,6 +2060,10 @@ static struct hw ct20k2_preset __devinitdata = { .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, +#ifdef CONFIG_PM + .suspend = hw_suspend, + .resume = hw_resume, +#endif .src_rsc_get_ctrl_blk = src_get_rsc_ctrl_blk, .src_rsc_put_ctrl_blk = src_put_rsc_ctrl_blk, diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index 666722d..f26d7cd 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c @@ -462,6 +462,43 @@ do_digit_io_switch(struct ct_atc *atc, int state) return; } +static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) +{ + struct ct_mixer *mixer = atc->mixer; + + /* Do changes in mixer. */ + if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { + if (state) { + ct_mixer_recording_select(mixer, + get_amixer_index(type)); + } else { + ct_mixer_recording_unselect(mixer, + get_amixer_index(type)); + } + } + /* Do changes out of mixer. */ + if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) + do_line_mic_switch(atc, type); + else if (MIXER_WAVEF_P_S == type) + atc->line_front_unmute(atc, state); + else if (MIXER_WAVES_P_S == type) + atc->line_surround_unmute(atc, state); + else if (MIXER_WAVEC_P_S == type) + 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); + + return; +} + static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -498,35 +535,7 @@ static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol, return 0; set_switch_state(mixer, type, state); - /* Do changes in mixer. */ - if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { - if (state) { - ct_mixer_recording_select(mixer, - get_amixer_index(type)); - } else { - ct_mixer_recording_unselect(mixer, - get_amixer_index(type)); - } - } - /* Do changes out of mixer. */ - if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) - do_line_mic_switch(atc, type); - else if (MIXER_WAVEF_P_S == type) - atc->line_front_unmute(atc, state); - else if (MIXER_WAVES_P_S == type) - atc->line_surround_unmute(atc, state); - else if (MIXER_WAVEC_P_S == type) - 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); + do_switch(atc, type, state); return 1; } @@ -1039,6 +1048,28 @@ mixer_set_input_right(struct ct_mixer *mixer, return 0; } +#ifdef CONFIG_PM +static int mixer_resume(struct ct_mixer *mixer) +{ + int i, state; + struct amixer *amixer; + + /* resume topology and volume gain. */ + for (i = 0; i < NUM_CT_AMIXERS*CHN_NUM; i++) { + amixer = mixer->amixers[i]; + amixer->ops->commit_write(amixer); + } + + /* resume switch state. */ + for (i = SWH_MIXER_START; i <= SWH_MIXER_END; i++) { + state = get_switch_state(mixer, i); + do_switch(mixer->atc, i, state); + } + + return 0; +} +#endif + int ct_mixer_destroy(struct ct_mixer *mixer) { struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM]; @@ -1087,6 +1118,9 @@ int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer) mixer->get_output_ports = mixer_get_output_ports; mixer->set_input_left = mixer_set_input_left; mixer->set_input_right = mixer_set_input_right; +#ifdef CONFIG_PM + mixer->resume = mixer_resume; +#endif /* Allocate chip resources for mixer obj */ err = ct_mixer_get_resources(mixer); diff --git a/sound/pci/ctxfi/ctmixer.h b/sound/pci/ctxfi/ctmixer.h index e2d96eb..b009e98 100644 --- a/sound/pci/ctxfi/ctmixer.h +++ b/sound/pci/ctxfi/ctmixer.h @@ -56,6 +56,9 @@ struct ct_mixer { enum MIXER_PORT_T type, struct rsc *rsc); int (*set_input_right)(struct ct_mixer *mixer, enum MIXER_PORT_T type, struct rsc *rsc); +#ifdef CONFIG_PM + int (*resume)(struct ct_mixer *mixer); +#endif }; int ct_alsa_mix_create(struct ct_atc *atc, diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index 9e5c0c4..60ea231 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c @@ -422,5 +422,9 @@ int ct_alsa_pcm_create(struct ct_atc *atc, snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(atc->pci), 128*1024, 128*1024); +#ifdef CONFIG_PM + atc->pcms[device] = pcm; +#endif + return 0; } diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index 2d3dd89..7654174 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c @@ -121,11 +121,33 @@ static void __devexit ct_card_remove(struct pci_dev *pci) pci_set_drvdata(pci, NULL); } +#ifdef CONFIG_PM +static int ct_card_suspend(struct pci_dev *pci, pm_message_t state) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct ct_atc *atc = card->private_data; + + return atc->suspend(atc, state); +} + +static int ct_card_resume(struct pci_dev *pci) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct ct_atc *atc = card->private_data; + + return atc->resume(atc); +} +#endif + static struct pci_driver ct_driver = { .name = "SB-XFi", .id_table = ct_pci_dev_ids, .probe = ct_card_probe, .remove = __devexit_p(ct_card_remove), +#ifdef CONFIG_PM + .suspend = ct_card_suspend, + .resume = ct_card_resume, +#endif }; static int __init ct_card_init(void) diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index c710150..04438f1 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -2,7 +2,6 @@ menuconfig SND_HDA_INTEL tristate "Intel HD Audio" select SND_PCM select SND_VMASTER - select SND_JACK if INPUT=y || INPUT=SND help Say Y here to include support for Intel "High Definition Audio" (Azalia) and its compatible devices. @@ -39,6 +38,14 @@ config SND_HDA_INPUT_BEEP Say Y here to build a digital beep interface for HD-audio driver. This interface is used to generate digital beeps. +config SND_HDA_INPUT_JACK + bool "Support jack plugging notification via input layer" + depends on INPUT=y || INPUT=SND_HDA_INTEL + select SND_JACK + help + Say Y here to enable the jack plugging notification via + input layer. + config SND_HDA_CODEC_REALTEK bool "Build Realtek HD-audio codec support" default y diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 4fcbe21..ac868c5 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -349,7 +349,7 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, &spec->cur_mux[adc_idx]); } -#ifdef CONFIG_SND_JACK +#ifdef CONFIG_SND_HDA_INPUT_JACK static void conexant_free_jack_priv(struct snd_jack *jack) { struct conexant_jack *jacks = jack->private_data; @@ -463,7 +463,7 @@ static int conexant_init(struct hda_codec *codec) static void conexant_free(struct hda_codec *codec) { -#ifdef CONFIG_SND_JACK +#ifdef CONFIG_SND_HDA_INPUT_JACK struct conexant_spec *spec = codec->spec; if (spec->jacks.list) { struct conexant_jack *jacks = spec->jacks.list; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bf4b78a..3345331 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -250,13 +250,6 @@ enum { ALC883_MODEL_LAST, }; -/* styles of capture selection */ -enum { - CAPT_MUX = 0, /* only mux based */ - CAPT_MIX, /* only mixer based */ - CAPT_1MUX_MIX, /* first mux and other mixers */ -}; - /* for GPIO Poll */ #define GPIO_MASK 0x03 @@ -306,7 +299,6 @@ struct alc_spec { hda_nid_t *adc_nids; hda_nid_t *capsrc_nids; hda_nid_t dig_in_nid; /* digital-in NID; optional */ - int capture_style; /* capture style (CAPT_*) */ /* capture source */ unsigned int num_mux_defs; @@ -420,12 +412,13 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, unsigned int mux_idx; hda_nid_t nid = spec->capsrc_nids ? spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx]; + unsigned int type; mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; imux = &spec->input_mux[mux_idx]; - if (spec->capture_style && - !(spec->capture_style == CAPT_1MUX_MIX && !adc_idx)) { + type = (get_wcaps(codec, nid) & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + if (type == AC_WID_AUD_MIX) { /* Matrix-mixer style (e.g. ALC882) */ unsigned int *cur_val = &spec->cur_mux[adc_idx]; unsigned int i, idx; @@ -7557,7 +7550,6 @@ static int patch_alc882(struct hda_codec *codec) spec->stream_digital_playback = &alc882_pcm_digital_playback; spec->stream_digital_capture = &alc882_pcm_digital_capture; - spec->capture_style = CAPT_MIX; /* matrix-style capture */ if (!spec->adc_nids && spec->input_mux) { /* check whether NID 0x07 is valid */ unsigned int wcap = get_wcaps(codec, 0x07); @@ -9781,7 +9773,6 @@ static int patch_alc883(struct hda_codec *codec) } if (!spec->capsrc_nids) spec->capsrc_nids = alc883_capsrc_nids; - spec->capture_style = CAPT_MIX; /* matrix-style capture */ spec->init_amp = ALC_INIT_DEFAULT; /* always initialize */ break; case 0x10ec0889: @@ -9791,8 +9782,6 @@ static int patch_alc883(struct hda_codec *codec) } if (!spec->capsrc_nids) spec->capsrc_nids = alc889_capsrc_nids; - spec->capture_style = CAPT_1MUX_MIX; /* 1mux/Nmix-style - capture */ break; default: if (!spec->num_adc_nids) { @@ -9801,7 +9790,6 @@ static int patch_alc883(struct hda_codec *codec) } if (!spec->capsrc_nids) spec->capsrc_nids = alc883_capsrc_nids; - spec->capture_style = CAPT_MIX; /* matrix-style capture */ break; } @@ -10913,9 +10901,27 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, return 0; } -/* identical with ALC880 */ -#define alc262_auto_create_analog_input_ctls \ - alc880_auto_create_analog_input_ctls +static int alc262_auto_create_analog_input_ctls(struct alc_spec *spec, + const struct auto_pin_cfg *cfg) +{ + int err; + + err = alc880_auto_create_analog_input_ctls(spec, cfg); + if (err < 0) + return err; + /* digital-mic input pin is excluded in alc880_auto_create..() + * because it's under 0x18 + */ + if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || + cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { + struct hda_input_mux *imux = &spec->private_imux[0]; + imux->items[imux->num_items].label = "Int Mic"; + imux->items[imux->num_items].index = 0x09; + imux->num_items++; + } + return 0; +} + /* * generic initialization of ADC, input mixers and output mixers @@ -11332,6 +11338,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO), SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD), SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */ + SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06), SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO", ALC262_SONY_ASSAMD), SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", @@ -11539,6 +11546,7 @@ static struct alc_config_preset alc262_presets[] = { .capsrc_nids = alc262_dmic_capsrc_nids, .dac_nids = alc262_dac_nids, .adc_nids = alc262_dmic_adc_nids, /* ADC0 */ + .num_adc_nids = 1, /* single ADC */ .dig_out_nid = ALC262_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc262_modes), .channel_mode = alc262_modes, @@ -11640,21 +11648,36 @@ static int patch_alc262(struct hda_codec *codec) spec->stream_digital_playback = &alc262_pcm_digital_playback; spec->stream_digital_capture = &alc262_pcm_digital_capture; - spec->capture_style = CAPT_MIX; if (!spec->adc_nids && spec->input_mux) { - /* check whether NID 0x07 is valid */ - unsigned int wcap = get_wcaps(codec, 0x07); - - /* get type */ - wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; - if (wcap != AC_WID_AUD_IN) { - spec->adc_nids = alc262_adc_nids_alt; - spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt); - spec->capsrc_nids = alc262_capsrc_nids_alt; + int i; + /* check whether the digital-mic has to be supported */ + for (i = 0; i < spec->input_mux->num_items; i++) { + if (spec->input_mux->items[i].index >= 9) + break; + } + if (i < spec->input_mux->num_items) { + /* use only ADC0 */ + spec->adc_nids = alc262_dmic_adc_nids; + spec->num_adc_nids = 1; + spec->capsrc_nids = alc262_dmic_capsrc_nids; } else { - spec->adc_nids = alc262_adc_nids; - spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids); - spec->capsrc_nids = alc262_capsrc_nids; + /* all analog inputs */ + /* check whether NID 0x07 is valid */ + unsigned int wcap = get_wcaps(codec, 0x07); + + /* get type */ + wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + if (wcap != AC_WID_AUD_IN) { + spec->adc_nids = alc262_adc_nids_alt; + spec->num_adc_nids = + ARRAY_SIZE(alc262_adc_nids_alt); + spec->capsrc_nids = alc262_capsrc_nids_alt; + } else { + spec->adc_nids = alc262_adc_nids; + spec->num_adc_nids = + ARRAY_SIZE(alc262_adc_nids); + spec->capsrc_nids = alc262_capsrc_nids; + } } } if (!spec->cap_mixer && !spec->no_analog) @@ -13244,26 +13267,8 @@ static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec, return 0; } -static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec, - const struct auto_pin_cfg *cfg) -{ - int err; - - err = alc880_auto_create_analog_input_ctls(spec, cfg); - if (err < 0) - return err; - /* digital-mic input pin is excluded in alc880_auto_create..() - * because it's under 0x18 - */ - if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || - cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { - struct hda_input_mux *imux = &spec->private_imux[0]; - imux->items[imux->num_items].label = "Int Mic"; - imux->items[imux->num_items].index = 0x05; - imux->num_items++; - } - return 0; -} +#define alc269_auto_create_analog_input_ctls \ + alc262_auto_create_analog_input_ctls #ifdef CONFIG_SND_HDA_POWER_SAVE #define alc269_loopbacks alc880_loopbacks @@ -15554,7 +15559,6 @@ static int patch_alc861vd(struct hda_codec *codec) spec->adc_nids = alc861vd_adc_nids; spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids); spec->capsrc_nids = alc861vd_capsrc_nids; - spec->capture_style = CAPT_MIX; set_capture_mixer(spec); set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); @@ -17474,7 +17478,6 @@ static int patch_alc662(struct hda_codec *codec) spec->adc_nids = alc662_adc_nids; spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids); spec->capsrc_nids = alc662_capsrc_nids; - spec->capture_style = CAPT_MIX; if (!spec->cap_mixer) set_capture_mixer(spec); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 93e47c9..14f3c3e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -639,7 +639,7 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, static unsigned int stac92xx_vref_set(struct hda_codec *codec, hda_nid_t nid, unsigned int new_vref) { - unsigned int error; + int error; unsigned int pincfg; pincfg = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); @@ -2703,7 +2703,7 @@ static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int new_vref = 0; - unsigned int error; + int error; hda_nid_t nid = kcontrol->private_value; if (ucontrol->value.enumerated.item[0] == 0) @@ -4035,7 +4035,7 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ } -#ifdef CONFIG_SND_JACK +#ifdef CONFIG_SND_HDA_INPUT_JACK static void stac92xx_free_jack_priv(struct snd_jack *jack) { struct sigmatel_jack *jacks = jack->private_data; @@ -4047,7 +4047,7 @@ static void stac92xx_free_jack_priv(struct snd_jack *jack) static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type) { -#ifdef CONFIG_SND_JACK +#ifdef CONFIG_SND_HDA_INPUT_JACK struct sigmatel_spec *spec = codec->spec; struct sigmatel_jack *jack; int def_conf = snd_hda_codec_get_pincfg(codec, nid); @@ -4336,7 +4336,7 @@ static int stac92xx_init(struct hda_codec *codec) static void stac92xx_free_jacks(struct hda_codec *codec) { -#ifdef CONFIG_SND_JACK +#ifdef CONFIG_SND_HDA_INPUT_JACK /* free jack instances manually when clearing/reconfiguring */ struct sigmatel_spec *spec = codec->spec; if (!codec->bus->shutdown && spec->jacks.list) { diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 1ef58c5..949fcaf 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -85,6 +85,7 @@ static int joystick; static int ac97_clock = 48000; static char *ac97_quirk; static int dxs_support; +static int nodelay; module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge."); @@ -102,6 +103,8 @@ module_param(ac97_quirk, charp, 0444); MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); module_param(dxs_support, int, 0444); MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)"); +module_param(nodelay, int, 0444); +MODULE_PARM_DESC(nodelay, "Disable 500ms init delay"); /* just for backward compatibility */ static int enable; @@ -549,7 +552,8 @@ static void snd_via82xx_codec_wait(struct snd_ac97 *ac97) int err; err = snd_via82xx_codec_ready(chip, ac97->num); /* here we need to wait fairly for long time.. */ - msleep(500); + if (!nodelay) + msleep(500); } static void snd_via82xx_codec_write(struct snd_ac97 *ac97, diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index 9648244..af06904 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c @@ -50,6 +50,7 @@ struct bf5xx_i2s_port { u16 tcr2; u16 rcr2; int counter; + int configured; }; static struct bf5xx_i2s_port bf5xx_i2s; @@ -168,7 +169,7 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, break; } - if (bf5xx_i2s.counter == 1) { + if (!bf5xx_i2s.configured) { /* * TX and RX are not independent,they are enabled at the * same time, even if only one side is running. So, we @@ -177,6 +178,7 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, * * CPU DAI:slave mode. */ + bf5xx_i2s.configured = 1; ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1, bf5xx_i2s.rcr2, 0, 0); if (ret) { @@ -200,6 +202,9 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, { pr_debug("%s enter\n", __func__); bf5xx_i2s.counter--; + /* No active stream, SPORT is allowed to be configured again. */ + if (!bf5xx_i2s.counter) + bf5xx_i2s.configured = 0; } static int bf5xx_i2s_probe(struct platform_device *pdev, @@ -244,8 +249,7 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) return 0; } -static int bf5xx_i2s_resume(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int bf5xx_i2s_resume(struct snd_soc_dai *dai) { int ret; struct sport_device *sport = |