Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 23 Jun 2009 17:45:39 +0000 (10:45 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 23 Jun 2009 17:45:39 +0000 (10:45 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: hda - Make jack-plug notification selectable
  ALSA: ctxfi - Add PM support
  sound: seq_midi_event: fix decoding of (N)RPN events
  ALSA: hda - Add digital-mic support to ALC262 auto model
  ALSA: hda - Fix check of input source type for realtek codecs
  ALSA: hda - Add quirk for Sony VAIO Z21MN
  ALSA: hda - Get back Input Source for ALC262 toshiba-s06 model
  ALSA: hda - Fix unsigned comparison in patch_sigmatel.c
  ALSA: via82xx: add option to disable 500ms delay in snd_via82xx_codec_wait
  sound: fix check for return value in snd_pcm_hw_refine
  ALSA: ctxfi - Allow unknown PCI SSIDs
  ASoC: Blackfin: update the bf5xx_i2s_resume parameters
  ASoC: Blackfin: keep better track of SPORT configuration state

17 files changed:
sound/core/pcm_native.c
sound/core/seq/seq_midi_event.c
sound/pci/ctxfi/ctatc.c
sound/pci/ctxfi/ctatc.h
sound/pci/ctxfi/cthardware.h
sound/pci/ctxfi/cthw20k1.c
sound/pci/ctxfi/cthw20k2.c
sound/pci/ctxfi/ctmixer.c
sound/pci/ctxfi/ctmixer.h
sound/pci/ctxfi/ctpcm.c
sound/pci/ctxfi/xfi.c
sound/pci/hda/Kconfig
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/via82xx.c
sound/soc/blackfin/bf5xx-i2s.c

index 84da3ba17c86911b0d48799772bd0c0960c90693..ac2150e0670d8541e4023fb21fdb600e4bef6df8 100644 (file)
@@ -320,7 +320,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
                     snd_mask_max(&params->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;
                }
        }
index 8284f176a342c6011f470a9d27581438ba23c73a..b5d6ea4904c091c9b2733308d380cdaa995fe98d 100644 (file)
@@ -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;
index b0adc8094009912d00db252f7388680299475f7e..a49c766473073e1a6d94b7ed75ed014fd0c2c293 100644 (file)
@@ -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)
index 9fe620ea5f3f3bc1ab38125e111c46e134fd2f34..9fd8a57089434d3c16b178664a8980aaa88836c7 100644 (file)
@@ -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
 };
 
 
index 4a8e04f090a4fd0737675db01e8cd3148b0ee69d..af55405f5dec81b0e5d4f7b7829c9ea981b5ee77 100644 (file)
@@ -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);
index cb69d9ddfbe3d2b61821bc7f700c3c84c05cd213..ad3e1d144464ce639ad8f01f6b5883ab495b2281 100644 (file)
@@ -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,
index 4493a51c6b018454eb3fbe200f7e8f43eb46485e..dec46d04b041c7e33072d484f6eedd70b0f4b974 100644 (file)
@@ -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,
index 666722d9de41ae0afca3b9378a24b6175bd27bbd..f26d7cd9db9f531a94ad28a16ff8d84f31c77cea 100644 (file)
@@ -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);
index e2d96ebde7460e39bb5ac71925a874f1eec90a73..b009e989e77ddcef32cc8451c8eb8b99102f67c0 100644 (file)
@@ -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,
index 9e5c0c4da7261166faa9659bbef57fd35f90c678..60ea23180acbe1f91443f5ad15b8939ec812698c 100644 (file)
@@ -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;
 }
index 2d3dd89af151d3d7de7927d79f6d76fc0bc2edf3..76541748e7bcf8ec43ccd5964d90faf4258f442a 100644 (file)
@@ -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)
index c710150d5065d8257c52d38a096e0e80e4d97a7e..04438f1d682dd22f4f24b2e9b518a0d158fdcf97 100644 (file)
@@ -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
index 4fcbe21829abfe27104f7dabeed8fb801a301537..ac868c59f9e334ad0dad50b00f0bb77b9bf59cdb 100644 (file)
@@ -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;
index bf4b78a74a8fec9e4437a74c9d9e097235dc643c..33453319742508251d3b9a96d2ca1c26312cdcd8 100644 (file)
@@ -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);
index 93e47c96a38bce1800a9df2dbfff5aaa85fd7b47..14f3c3e0f62dec7618b97b7d5872148da9d02ef3 100644 (file)
@@ -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) {
index 1ef58c51c21343c6d7721b5dedfa6c91ddc4071c..949fcaf6b70ed9454ecd373ec052e8e7b7800fc9 100644 (file)
@@ -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,
index 964824419678bfe361b77bab3ce538eb7af6bc38..af06904bab0f8411285fec191995499ffc8effde 100644 (file)
@@ -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 =