Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
Linus Torvalds [Wed, 7 Apr 2010 15:42:25 +0000 (08:42 -0700)]
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: mixart: range checking proc file
  ALSA: hda - Fix a wrong array range check in patch_realtek.c
  ALSA: ASoC: move dma_data from snd_soc_dai to snd_soc_pcm_stream
  ALSA: hda - Enable amplifiers on Acer Inspire 6530G
  ASoC: Only do WM8994 bias off transition from standby
  ASoC: Don't use DCS_DATAPATH_BUSY for WM hubs devices
  ASoC: Don't do runtime wm_hubs DC servo updates if using offset correction
  ASoC: Support second DC servo readback method for wm_hubs
  ASoC: Avoid wraparound in wm_hubs DC servo correction
  ALSA: echoaudio - Eliminate use after free
  ALSA: i2c: cleanup: change parameter to pointer
  ALSA: hda - Add MSI blacklist for Aopen MZ915-M
  ASoC: OMAP: Fix capture pointer handling for OMAP1510 to work correctly with recent ALSA PCM code
  ALSA: hda - Update document about MSI and interrupts
  ALSA: hda: Fix 0 dB offset for Lenovo Thinkpad models using AD1981
  ALSA: hda - Add missing printk argument in previous patch
  ASoC: Fix passing platform_data to ac97 bus users and fix a leak
  ALSA: hda - Fix ADC/MUX assignment of ALC269 codec
  ALSA: hda - Fix invalid bit values passed to snd_hda_codec_amp_stereo()
  ASoC: wm8994: playback => capture

36 files changed:
Documentation/sound/alsa/HD-Audio.txt
include/sound/ak4113.h
include/sound/soc-dai.h
include/sound/soc.h
sound/i2c/other/ak4113.c
sound/pci/echoaudio/echoaudio.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_realtek.c
sound/pci/mixart/mixart.c
sound/soc/atmel/atmel-pcm.c
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/codecs/ac97.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm_hubs.c
sound/soc/codecs/wm_hubs.h
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-pcm.c
sound/soc/imx/imx-pcm-dma-mx2.c
sound/soc/imx/imx-ssi.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-pcm.c
sound/soc/pxa/pxa-ssp.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/s3c24xx/s3c-ac97.c
sound/soc/s3c24xx/s3c-dma.c
sound/soc/s3c24xx/s3c-i2s-v2.c
sound/soc/s3c24xx/s3c-pcm.c
sound/soc/s3c24xx/s3c24xx-i2s.c
sound/soc/s6000/s6000-i2s.c
sound/soc/s6000/s6000-pcm.c
sound/soc/soc-core.c

index f4dd3bf..98d14cb 100644 (file)
@@ -119,10 +119,18 @@ the codec slots 0 and 1 no matter what the hardware reports.
 
 Interrupt Handling
 ~~~~~~~~~~~~~~~~~~
-In rare but some cases, the interrupt isn't properly handled as
-default.  You would notice this by the DMA transfer error reported by
-ALSA PCM core, for example.  Using MSI might help in such a case.
-Pass `enable_msi=1` option for enabling MSI.
+HD-audio driver uses MSI as default (if available) since 2.6.33
+kernel as MSI works better on some machines, and in general, it's
+better for performance.  However, Nvidia controllers showed bad
+regressions with MSI (especially in a combination with AMD chipset),
+thus we disabled MSI for them.
+
+There seem also still other devices that don't work with MSI.  If you
+see a regression wrt the sound quality (stuttering, etc) or a lock-up
+in the recent kernel, try to pass `enable_msi=0` option to disable
+MSI.  If it works, you can add the known bad device to the blacklist
+defined in hda_intel.c.  In such a case, please report and give the
+patch back to the upstream developer. 
 
 
 HD-AUDIO CODEC
index 8988eda..2609048 100644 (file)
@@ -307,7 +307,7 @@ struct ak4113 {
 
 int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read,
                ak4113_write_t *write,
-               const unsigned char pgm[AK4113_WRITABLE_REGS],
+               const unsigned char *pgm,
                void *private_data, struct ak4113 **r_ak4113);
 void snd_ak4113_reg_write(struct ak4113 *ak4113, unsigned char reg,
                unsigned char mask, unsigned char val);
index 061f16d..0a0b019 100644 (file)
@@ -219,7 +219,6 @@ struct snd_soc_dai {
        struct snd_soc_codec *codec;
        unsigned int active;
        unsigned char pop_wait:1;
-       void *dma_data;
 
        /* DAI private data */
        void *private_data;
@@ -230,4 +229,21 @@ struct snd_soc_dai {
        struct list_head list;
 };
 
+static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
+                                            const struct snd_pcm_substream *ss)
+{
+       return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+               dai->playback.dma_data : dai->capture.dma_data;
+}
+
+static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai,
+                                           const struct snd_pcm_substream *ss,
+                                           void *data)
+{
+       if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dai->playback.dma_data = data;
+       else
+               dai->capture.dma_data = data;
+}
+
 #endif
index 5d234a8..a57fbfc 100644 (file)
@@ -375,6 +375,7 @@ struct snd_soc_pcm_stream {
        unsigned int channels_min;      /* min channels */
        unsigned int channels_max;      /* max channels */
        unsigned int active:1;          /* stream is in use */
+       void *dma_data;                 /* used by platform code */
 };
 
 /* SoC audio ops */
index fff62cc..971a84a 100644 (file)
@@ -70,7 +70,7 @@ static int snd_ak4113_dev_free(struct snd_device *device)
 }
 
 int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read,
-               ak4113_write_t *write, const unsigned char pgm[5],
+               ak4113_write_t *write, const unsigned char *pgm,
                void *private_data, struct ak4113 **r_ak4113)
 {
        struct ak4113 *chip;
index 8dab82d..668a5ec 100644 (file)
@@ -2184,10 +2184,9 @@ static int __devinit snd_echo_probe(struct pci_dev *pci,
                        goto ctl_error;
 #endif
 
-       if ((err = snd_card_register(card)) < 0) {
-               snd_card_free(card);
+       err = snd_card_register(card);
+       if (err < 0)
                goto ctl_error;
-       }
        snd_printk(KERN_INFO "Card registered: %s\n", card->longname);
 
        pci_set_drvdata(pci, chip);
index 4bb9067..f8fd586 100644 (file)
@@ -2362,6 +2362,7 @@ static struct snd_pci_quirk msi_black_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
        SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */
        SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */
+       SND_PCI_QUIRK(0xa0a0, 0x0575, "Aopen MZ915-M", 0), /* ICH6 */
        {}
 };
 
index e6d1bdf..af34606 100644 (file)
@@ -1896,6 +1896,14 @@ static int patch_ad1981(struct hda_codec *codec)
        case AD1981_THINKPAD:
                spec->mixers[0] = ad1981_thinkpad_mixers;
                spec->input_mux = &ad1981_thinkpad_capture_source;
+               /* set the upper-limit for mixer amp to 0dB for avoiding the
+                * possible damage by overloading
+                */
+               snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT,
+                                         (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
+                                         (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+                                         (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+                                         (1 << AC_AMPCAP_MUTE_SHIFT));
                break;
        case AD1981_TOSHIBA:
                spec->mixers[0] = ad1981_hp_mixers;
index 9a23444..c7730db 100644 (file)
@@ -1621,6 +1621,11 @@ static struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
  */
 
 static struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
+/* Route to built-in subwoofer as well as speakers */
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 /* Bias voltage on for external mic port */
        {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
 /* Front Mic: set to PIN_IN (empty by default) */
@@ -1632,10 +1637,12 @@ static struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
 /* Enable speaker output */
        {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
        {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+       {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
 /* Enable headphone output */
        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
        {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
        { }
 };
 
@@ -4984,6 +4991,70 @@ static void set_capture_mixer(struct hda_codec *codec)
        }
 }
 
+/* fill adc_nids (and capsrc_nids) containing all active input pins */
+static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
+                                int num_nids)
+{
+       struct alc_spec *spec = codec->spec;
+       int n;
+       hda_nid_t fallback_adc = 0, fallback_cap = 0;
+
+       for (n = 0; n < num_nids; n++) {
+               hda_nid_t adc, cap;
+               hda_nid_t conn[HDA_MAX_NUM_INPUTS];
+               int nconns, i, j;
+
+               adc = nids[n];
+               if (get_wcaps_type(get_wcaps(codec, adc)) != AC_WID_AUD_IN)
+                       continue;
+               cap = adc;
+               nconns = snd_hda_get_connections(codec, cap, conn,
+                                                ARRAY_SIZE(conn));
+               if (nconns == 1) {
+                       cap = conn[0];
+                       nconns = snd_hda_get_connections(codec, cap, conn,
+                                                        ARRAY_SIZE(conn));
+               }
+               if (nconns <= 0)
+                       continue;
+               if (!fallback_adc) {
+                       fallback_adc = adc;
+                       fallback_cap = cap;
+               }
+               for (i = 0; i < AUTO_PIN_LAST; i++) {
+                       hda_nid_t nid = spec->autocfg.input_pins[i];
+                       if (!nid)
+                               continue;
+                       for (j = 0; j < nconns; j++) {
+                               if (conn[j] == nid)
+                                       break;
+                       }
+                       if (j >= nconns)
+                               break;
+               }
+               if (i >= AUTO_PIN_LAST) {
+                       int num_adcs = spec->num_adc_nids;
+                       spec->private_adc_nids[num_adcs] = adc;
+                       spec->private_capsrc_nids[num_adcs] = cap;
+                       spec->num_adc_nids++;
+                       spec->adc_nids = spec->private_adc_nids;
+                       if (adc != cap)
+                               spec->capsrc_nids = spec->private_capsrc_nids;
+               }
+       }
+       if (!spec->num_adc_nids) {
+               printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
+                      " using fallback 0x%x\n",
+                      codec->chip_name, fallback_adc);
+               spec->private_adc_nids[0] = fallback_adc;
+               spec->adc_nids = spec->private_adc_nids;
+               if (fallback_adc != fallback_cap) {
+                       spec->private_capsrc_nids[0] = fallback_cap;
+                       spec->capsrc_nids = spec->private_adc_nids;
+               }
+       }
+}
+
 #ifdef CONFIG_SND_HDA_INPUT_BEEP
 #define set_beep_amp(spec, nid, idx, dir) \
        ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
@@ -8398,9 +8469,7 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
 
 static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
        HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
        HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-       HDA_BIND_MUTE("LFE Playback Switch", 0x0f, 2, HDA_INPUT),
        HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
@@ -10041,13 +10110,12 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
        int idx;
 
        alc_set_pin_output(codec, nid, pin_type);
+       if (dac_idx >= spec->multiout.num_dacs)
+               return;
        if (spec->multiout.dac_nids[dac_idx] == 0x25)
                idx = 4;
-       else {
-               if (spec->multiout.num_dacs >= dac_idx)
-                       return;
+       else
                idx = spec->multiout.dac_nids[dac_idx] - 2;
-       }
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
 
 }
@@ -12459,11 +12527,11 @@ static void alc268_aspire_one_speaker_automute(struct hda_codec *codec)
        unsigned char bits;
 
        present = snd_hda_jack_detect(codec, 0x15);
-       bits = present ? AMP_IN_MUTE(0) : 0;
+       bits = present ? HDA_AMP_MUTE : 0;
        snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
 }
 
 static void alc268_acer_lc_unsol_event(struct hda_codec *codec,
@@ -13333,9 +13401,9 @@ static hda_nid_t alc269vb_capsrc_nids[1] = {
        0x22,
 };
 
-/* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24),
- *       not a mux!
- */
+static hda_nid_t alc269_adc_candidates[] = {
+       0x08, 0x09, 0x07,
+};
 
 #define alc269_modes           alc260_modes
 #define alc269_capture_source  alc880_lg_lw_capture_source
@@ -13482,11 +13550,11 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
        unsigned char bits;
 
        present = snd_hda_jack_detect(codec, 0x15);
-       bits = present ? AMP_IN_MUTE(0) : 0;
+       bits = present ? HDA_AMP_MUTE : 0;
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-                       AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-                       AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
 
        snd_hda_codec_write(codec, 0x20, 0,
                        AC_VERB_SET_COEF_INDEX, 0x0c);
@@ -13511,11 +13579,11 @@ static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
        /* Check port replicator headphone socket */
        present |= snd_hda_jack_detect(codec, 0x1a);
 
-       bits = present ? AMP_IN_MUTE(0) : 0;
+       bits = present ? HDA_AMP_MUTE : 0;
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-                       AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-                       AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
 
        snd_hda_codec_write(codec, 0x20, 0,
                        AC_VERB_SET_COEF_INDEX, 0x0c);
@@ -13646,11 +13714,11 @@ static void alc269_speaker_automute(struct hda_codec *codec)
        unsigned char bits;
 
        present = snd_hda_jack_detect(codec, nid);
-       bits = present ? AMP_IN_MUTE(0) : 0;
+       bits = present ? HDA_AMP_MUTE : 0;
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
 }
 
 /* unsolicited event for HP jack sensing */
@@ -13842,7 +13910,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
        int err;
        static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
-       hda_nid_t real_capsrc_nids;
 
        err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
                                           alc269_ignore);
@@ -13866,18 +13933,19 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
 
        if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) {
                add_verb(spec, alc269vb_init_verbs);
-               real_capsrc_nids = alc269vb_capsrc_nids[0];
                alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
        } else {
                add_verb(spec, alc269_init_verbs);
-               real_capsrc_nids = alc269_capsrc_nids[0];
                alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
        }
 
        spec->num_mux_defs = 1;
        spec->input_mux = &spec->private_imux[0];
+       fillup_priv_adc_nids(codec, alc269_adc_candidates,
+                            sizeof(alc269_adc_candidates));
+
        /* set default input source */
-       snd_hda_codec_write_cache(codec, real_capsrc_nids,
+       snd_hda_codec_write_cache(codec, spec->capsrc_nids[0],
                                  0, AC_VERB_SET_CONNECT_SEL,
                                  spec->input_mux->items[0].index);
 
@@ -14156,14 +14224,16 @@ static int patch_alc269(struct hda_codec *codec)
        spec->stream_digital_playback = &alc269_pcm_digital_playback;
        spec->stream_digital_capture = &alc269_pcm_digital_capture;
 
-       if (!is_alc269vb) {
-               spec->adc_nids = alc269_adc_nids;
-               spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
-               spec->capsrc_nids = alc269_capsrc_nids;
-       } else {
-               spec->adc_nids = alc269vb_adc_nids;
-               spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
-               spec->capsrc_nids = alc269vb_capsrc_nids;
+       if (!spec->adc_nids) { /* wasn't filled automatically? use default */
+               if (!is_alc269vb) {
+                       spec->adc_nids = alc269_adc_nids;
+                       spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
+                       spec->capsrc_nids = alc269_capsrc_nids;
+               } else {
+                       spec->adc_nids = alc269vb_adc_nids;
+                       spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
+                       spec->capsrc_nids = alc269vb_capsrc_nids;
+               }
        }
 
        if (!spec->cap_mixer)
@@ -17115,9 +17185,9 @@ static void alc663_m51va_speaker_automute(struct hda_codec *codec)
        present = snd_hda_jack_detect(codec, 0x21);
        bits = present ? HDA_AMP_MUTE : 0;
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
 }
 
 static void alc663_21jd_two_speaker_automute(struct hda_codec *codec)
@@ -17128,13 +17198,13 @@ static void alc663_21jd_two_speaker_automute(struct hda_codec *codec)
        present = snd_hda_jack_detect(codec, 0x21);
        bits = present ? HDA_AMP_MUTE : 0;
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
 }
 
 static void alc663_15jd_two_speaker_automute(struct hda_codec *codec)
@@ -17145,13 +17215,13 @@ static void alc663_15jd_two_speaker_automute(struct hda_codec *codec)
        present = snd_hda_jack_detect(codec, 0x15);
        bits = present ? HDA_AMP_MUTE : 0;
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
-                               AMP_IN_MUTE(0), bits);
+                                HDA_AMP_MUTE, bits);
 }
 
 static void alc662_f5z_speaker_automute(struct hda_codec *codec)
@@ -17190,14 +17260,14 @@ static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
 
        if (present1 || present2) {
                snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-                               AMP_IN_MUTE(0), AMP_IN_MUTE(0));
+                                        HDA_AMP_MUTE, HDA_AMP_MUTE);
                snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-                               AMP_IN_MUTE(0), AMP_IN_MUTE(0));
+                                        HDA_AMP_MUTE, HDA_AMP_MUTE);
        } else {
                snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-                               AMP_IN_MUTE(0), 0);
+                                        HDA_AMP_MUTE, 0);
                snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-                               AMP_IN_MUTE(0), 0);
+                                        HDA_AMP_MUTE, 0);
        }
 }
 
index 55e9315..3be8f97 100644 (file)
@@ -1162,13 +1162,15 @@ static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private
                                unsigned long count, unsigned long pos)
 {
        struct mixart_mgr *mgr = entry->private_data;
+       unsigned long maxsize;
 
-       count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
-       if(count <= 0)
+       if (pos >= MIXART_BA0_SIZE)
                return 0;
-       if(pos + count > MIXART_BA0_SIZE)
-               count = (long)(MIXART_BA0_SIZE - pos);
-       if(copy_to_user_fromio(buf, MIXART_MEM( mgr, pos ), count))
+       maxsize = MIXART_BA0_SIZE - pos;
+       if (count > maxsize)
+               count = maxsize;
+       count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
+       if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count))
                return -EFAULT;
        return count;
 }
@@ -1181,13 +1183,15 @@ static long snd_mixart_BA1_read(struct snd_info_entry *entry, void *file_private
                                unsigned long count, unsigned long pos)
 {
        struct mixart_mgr *mgr = entry->private_data;
+       unsigned long maxsize;
 
-       count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
-       if(count <= 0)
+       if (pos > MIXART_BA1_SIZE)
                return 0;
-       if(pos + count > MIXART_BA1_SIZE)
-               count = (long)(MIXART_BA1_SIZE - pos);
-       if(copy_to_user_fromio(buf, MIXART_REG( mgr, pos ), count))
+       maxsize = MIXART_BA1_SIZE - pos;
+       if (count > maxsize)
+               count = maxsize;
+       count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
+       if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count))
                return -EFAULT;
        return count;
 }
index 9ef6b96..3e6628c 100644 (file)
@@ -180,7 +180,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
        runtime->dma_bytes = params_buffer_bytes(params);
 
-       prtd->params = rtd->dai->cpu_dai->dma_data;
+       prtd->params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
        prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
 
        prtd->dma_buffer = runtime->dma_addr;
index e588e63..0b59806 100644 (file)
@@ -363,12 +363,12 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
        ssc_p->dma_params[dir] = dma_params;
 
        /*
-        * The cpu_dai->dma_data field is only used to communicate the
-        * appropriate DMA parameters to the pcm driver hw_params()
+        * The snd_soc_pcm_stream->dma_data field is only used to communicate
+        * the appropriate DMA parameters to the pcm driver hw_params()
         * function.  It should not be used for other purposes
         * as it is common to all substreams.
         */
-       rtd->dai->cpu_dai->dma_data = dma_params;
+       snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_params);
 
        channels = params_channels(params);
 
index fd101d4..1f5e57a 100644 (file)
@@ -81,9 +81,11 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
 static int ac97_soc_probe(struct platform_device *pdev)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_card *card = socdev->card;
        struct snd_soc_codec *codec;
        struct snd_ac97_bus *ac97_bus;
        struct snd_ac97_template ac97_template;
+       int i;
        int ret = 0;
 
        printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
@@ -103,12 +105,6 @@ static int ac97_soc_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&codec->dapm_widgets);
        INIT_LIST_HEAD(&codec->dapm_paths);
 
-       ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
-       if (ret < 0) {
-               printk(KERN_ERR "ASoC: failed to init gen ac97 glue\n");
-               goto err;
-       }
-
        /* register pcms */
        ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
        if (ret < 0)
@@ -124,6 +120,13 @@ static int ac97_soc_probe(struct platform_device *pdev)
        if (ret < 0)
                goto bus_err;
 
+       for (i = 0; i < card->num_links; i++) {
+               if (card->dai_link[i].codec_dai->ac97_control) {
+                       snd_ac97_dev_add_pdata(codec->ac97,
+                               card->dai_link[i].cpu_dai->ac97_pdata);
+               }
+       }
+
        return 0;
 
 bus_err:
index 8d1c637..9da0724 100644 (file)
@@ -3008,34 +3008,39 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
                break;
 
        case SND_SOC_BIAS_OFF:
-               /* Switch over to startup biases */
-               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-                                   WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA |
-                                   WM8994_VMID_BUF_ENA |
-                                   WM8994_VMID_RAMP_MASK,
-                                   WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA |
-                                   WM8994_VMID_BUF_ENA |
-                                   (1 << WM8994_VMID_RAMP_SHIFT));
-
-               /* Disable main biases */
-               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                   WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
+               if (codec->bias_level == SND_SOC_BIAS_STANDBY) {
+                       /* Switch over to startup biases */
+                       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                           WM8994_BIAS_SRC |
+                                           WM8994_STARTUP_BIAS_ENA |
+                                           WM8994_VMID_BUF_ENA |
+                                           WM8994_VMID_RAMP_MASK,
+                                           WM8994_BIAS_SRC |
+                                           WM8994_STARTUP_BIAS_ENA |
+                                           WM8994_VMID_BUF_ENA |
+                                           (1 << WM8994_VMID_RAMP_SHIFT));
 
-               /* Discharge line */
-               snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
-                                   WM8994_LINEOUT1_DISCH |
-                                   WM8994_LINEOUT2_DISCH,
-                                   WM8994_LINEOUT1_DISCH |
-                                   WM8994_LINEOUT2_DISCH);
+                       /* Disable main biases */
+                       snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+                                           WM8994_BIAS_ENA |
+                                           WM8994_VMID_SEL_MASK, 0);
 
-               msleep(5);
+                       /* Discharge line */
+                       snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+                                           WM8994_LINEOUT1_DISCH |
+                                           WM8994_LINEOUT2_DISCH,
+                                           WM8994_LINEOUT1_DISCH |
+                                           WM8994_LINEOUT2_DISCH);
 
-               /* Switch off startup biases */
-               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-                                   WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA |
-                                   WM8994_VMID_BUF_ENA |
-                                   WM8994_VMID_RAMP_MASK, 0);
+                       msleep(5);
 
+                       /* Switch off startup biases */
+                       snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+                                           WM8994_BIAS_SRC |
+                                           WM8994_STARTUP_BIAS_ENA |
+                                           WM8994_VMID_BUF_ENA |
+                                           WM8994_VMID_RAMP_MASK, 0);
+               }
                break;
        }
        codec->bias_level = level;
@@ -3402,7 +3407,7 @@ struct snd_soc_dai wm8994_dai[] = {
                        .rates = WM8994_RATES,
                        .formats = WM8994_FORMATS,
                },
-               .playback = {
+               .capture = {
                        .stream_name = "AIF3 Capture",
                        .channels_min = 2,
                        .channels_max = 2,
@@ -3731,11 +3736,12 @@ static int wm8994_codec_probe(struct platform_device *pdev)
        case 3:
                wm8994->hubs.dcs_codes = -5;
                wm8994->hubs.hp_startup_mode = 1;
+               wm8994->hubs.dcs_readback_mode = 1;
                break;
        default:
+               wm8994->hubs.dcs_readback_mode = 1;
                break;
        }
-                          
 
        /* Remember if AIFnLRCLK is configured as a GPIO.  This should be
         * configured on init - if a system wants to do this dynamically
index 486bdd2..e1f225a 100644 (file)
@@ -62,21 +62,27 @@ static const char *speaker_mode_text[] = {
 static const struct soc_enum speaker_mode =
        SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text);
 
-static void wait_for_dc_servo(struct snd_soc_codec *codec)
+static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
 {
        unsigned int reg;
        int count = 0;
+       unsigned int val;
+
+       val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1;
+
+       /* Trigger the command */
+       snd_soc_write(codec, WM8993_DC_SERVO_0, val);
 
        dev_dbg(codec->dev, "Waiting for DC servo...\n");
 
        do {
                count++;
                msleep(1);
-               reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0);
+               reg = snd_soc_read(codec, WM8993_DC_SERVO_0);
                dev_dbg(codec->dev, "DC servo: %x\n", reg);
-       } while (reg & WM8993_DCS_DATAPATH_BUSY && count < 400);
+       } while (reg & op && count < 400);
 
-       if (reg & WM8993_DCS_DATAPATH_BUSY)
+       if (reg & op)
                dev_err(codec->dev, "Timed out waiting for DC Servo\n");
 }
 
@@ -86,51 +92,58 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec)
 static void calibrate_dc_servo(struct snd_soc_codec *codec)
 {
        struct wm_hubs_data *hubs = codec->private_data;
-       u16 reg, dcs_cfg;
+       u16 reg, reg_l, reg_r, dcs_cfg;
 
        /* Set for 32 series updates */
        snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
                            WM8993_DCS_SERIES_NO_01_MASK,
                            32 << WM8993_DCS_SERIES_NO_01_SHIFT);
-
-       /* Enable the DC servo.  Write all bits to avoid triggering startup
-        * or write calibration.
-        */
-       snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
-                           0xFFFF,
-                           WM8993_DCS_ENA_CHAN_0 |
-                           WM8993_DCS_ENA_CHAN_1 |
-                           WM8993_DCS_TRIG_SERIES_1 |
-                           WM8993_DCS_TRIG_SERIES_0);
-
-       wait_for_dc_servo(codec);
+       wait_for_dc_servo(codec,
+                         WM8993_DCS_TRIG_SERIES_0 | WM8993_DCS_TRIG_SERIES_1);
 
        /* Apply correction to DC servo result */
        if (hubs->dcs_codes) {
                dev_dbg(codec->dev, "Applying %d code DC servo correction\n",
                        hubs->dcs_codes);
 
+               /* Different chips in the family support different
+                * readback methods.
+                */
+               switch (hubs->dcs_readback_mode) {
+               case 0:
+                       reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1)
+                               & WM8993_DCS_INTEG_CHAN_0_MASK;;
+                       reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2)
+                               & WM8993_DCS_INTEG_CHAN_1_MASK;
+                       break;
+               case 1:
+                       reg = snd_soc_read(codec, WM8993_DC_SERVO_3);
+                       reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
+                               >> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
+                       reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
+                       break;
+               default:
+                       WARN(1, "Unknown DCS readback method");
+                       break;
+               }
+
                /* HPOUT1L */
-               reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) &
-                       WM8993_DCS_INTEG_CHAN_0_MASK;;
-               reg += hubs->dcs_codes;
-               dcs_cfg = reg << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
+               if (reg_l + hubs->dcs_codes > 0 &&
+                   reg_l + hubs->dcs_codes < 0xff)
+                       reg_l += hubs->dcs_codes;
+               dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
 
                /* HPOUT1R */
-               reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) &
-                       WM8993_DCS_INTEG_CHAN_1_MASK;
-               reg += hubs->dcs_codes;
-               dcs_cfg |= reg;
+               if (reg_r + hubs->dcs_codes > 0 &&
+                   reg_r + hubs->dcs_codes < 0xff)
+                       reg_r += hubs->dcs_codes;
+               dcs_cfg |= reg_r;
 
                /* Do it */
                snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg);
-               snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
-                                   WM8993_DCS_TRIG_DAC_WR_0 |
-                                   WM8993_DCS_TRIG_DAC_WR_1,
-                                   WM8993_DCS_TRIG_DAC_WR_0 |
-                                   WM8993_DCS_TRIG_DAC_WR_1);
-
-               wait_for_dc_servo(codec);
+               wait_for_dc_servo(codec,
+                                 WM8993_DCS_TRIG_DAC_WR_0 |
+                                 WM8993_DCS_TRIG_DAC_WR_1);
        }
 }
 
@@ -141,10 +154,16 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
                               struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm_hubs_data *hubs = codec->private_data;
        int ret;
 
        ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
 
+       /* If we're applying an offset correction then updating the
+        * callibration would be likely to introduce further offsets. */
+       if (hubs->dcs_codes)
+               return ret;
+
        /* Only need to do this if the outputs are active */
        if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1)
            & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA))
index 420104f..e51c166 100644 (file)
@@ -21,6 +21,7 @@ extern const unsigned int wm_hubs_spkmix_tlv[];
 /* This *must* be the first element of the codec->private_data struct */
 struct wm_hubs_data {
        int dcs_codes;
+       int dcs_readback_mode;
        int hp_startup_mode;
 };
 
index 62af7e0..adadcd3 100644 (file)
@@ -586,7 +586,8 @@ static int davinci_i2s_probe(struct platform_device *pdev)
        dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
 
        davinci_i2s_dai.private_data = dev;
-       davinci_i2s_dai.dma_data = dev->dma_params;
+       davinci_i2s_dai.capture.dma_data = dev->dma_params;
+       davinci_i2s_dai.playback.dma_data = dev->dma_params;
        ret = snd_soc_register_dai(&davinci_i2s_dai);
        if (ret != 0)
                goto err_free_mem;
index 6c80cc3..79f0f4a 100644 (file)
@@ -918,7 +918,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
        dma_data->channel = res->start;
        davinci_mcasp_dai[pdata->op_mode].private_data = dev;
-       davinci_mcasp_dai[pdata->op_mode].dma_data = dev->dma_params;
+       davinci_mcasp_dai[pdata->op_mode].capture.dma_data = dev->dma_params;
+       davinci_mcasp_dai[pdata->op_mode].playback.dma_data = dev->dma_params;
        davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev;
        ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]);
 
index 80c7fdf..2dc406f 100644 (file)
@@ -649,8 +649,10 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
        struct snd_pcm_hardware *ppcm;
        int ret = 0;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->dma_data;
+       struct davinci_pcm_dma_params *pa;
        struct davinci_pcm_dma_params *params;
+
+       pa = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
        if (!pa)
                return -ENODEV;
        params = &pa[substream->stream];
index 86668ab..2e79d71 100644 (file)
@@ -84,11 +84,13 @@ static void snd_imx_dma_err_callback(int channel, void *data, int err)
 static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
+       struct imx_pcm_dma_params *dma_params;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
        int ret;
 
+       dma_params = snd_soc_get_dma_data(rtd->dai->cpu_dai, substream);
+
        iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH);
        if (iprtd->dma < 0) {
                pr_err("Failed to claim the audio DMA\n");
@@ -193,10 +195,12 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
+       struct imx_pcm_dma_params *dma_params;
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
        int err;
 
+       dma_params = snd_soc_get_dma_data(rtd->dai->cpu_dai, substream);
+
        iprtd->substream = substream;
        iprtd->buf = (unsigned int *)substream->dma_buffer.area;
        iprtd->period_cnt = 0;
index 6546b06..0bcc6d7 100644 (file)
@@ -235,17 +235,20 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *cpu_dai)
 {
        struct imx_ssi *ssi = cpu_dai->private_data;
+       struct imx_pcm_dma_params *dma_data;
        u32 reg, sccr;
 
        /* Tx/Rx config */
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                reg = SSI_STCCR;
-               cpu_dai->dma_data = &ssi->dma_params_tx;
+               dma_data = &ssi->dma_params_tx;
        } else {
                reg = SSI_SRCCR;
-               cpu_dai->dma_data = &ssi->dma_params_rx;
+               dma_data = &ssi->dma_params_rx;
        }
 
+       snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
+
        sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK;
 
        /* DAI data (word) size */
index e814a95..8ad9dc9 100644 (file)
@@ -297,7 +297,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
        omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
        omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
                                                        OMAP_DMA_DATA_TYPE_S16;
-       cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
+
+       snd_soc_dai_set_dma_data(cpu_dai, substream,
+               &omap_mcbsp_dai_dma_params[id][substream->stream]);
 
        if (mcbsp_data->configured) {
                /* McBSP already configured by another stream */
index 25f19e4..b7f4f7e 100644 (file)
@@ -150,7 +150,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
        int stream = substream->stream;
        int channels, err, link_mask = 0;
 
-       cpu_dai->dma_data = &omap_mcpdm_dai_dma_params[stream];
+       snd_soc_dai_set_dma_data(cpu_dai, substream,
+                                &omap_mcpdm_dai_dma_params[stream]);
 
        channels = params_channels(params);
        switch (channels) {
index ba8acbb..1e52190 100644 (file)
@@ -61,12 +61,11 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
        struct omap_runtime_data *prtd = runtime->private_data;
        unsigned long flags;
 
-       if ((cpu_is_omap1510()) &&
-                       (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) {
+       if ((cpu_is_omap1510())) {
                /*
                 * OMAP1510 doesn't fully support DMA progress counter
                 * and there is no software emulation implemented yet,
-                * so have to maintain our own playback progress counter
+                * so have to maintain our own progress counters
                 * that can be used by omap_pcm_pointer() instead.
                 */
                spin_lock_irqsave(&prtd->lock, flags);
@@ -101,9 +100,11 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct omap_runtime_data *prtd = runtime->private_data;
-       struct omap_pcm_dma_data *dma_data = rtd->dai->cpu_dai->dma_data;
+       struct omap_pcm_dma_data *dma_data;
        int err = 0;
 
+       dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+
        /* return if this is a bufferless transfer e.g.
         * codec <--> BT codec or GSM modem -- lg FIXME */
        if (!dma_data)
@@ -190,8 +191,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
        dma_params.frame_count  = runtime->periods;
        omap_set_dma_params(prtd->dma_ch, &dma_params);
 
-       if ((cpu_is_omap1510()) &&
-                       (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
+       if ((cpu_is_omap1510()))
                omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
                              OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
        else
@@ -249,14 +249,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
        dma_addr_t ptr;
        snd_pcm_uframes_t offset;
 
-       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+       if (cpu_is_omap1510()) {
+               offset = prtd->period_index * runtime->period_size;
+       } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
                ptr = omap_get_dma_dst_pos(prtd->dma_ch);
                offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
-       } else if (!(cpu_is_omap1510())) {
+       } else {
                ptr = omap_get_dma_src_pos(prtd->dma_ch);
                offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
-       } else
-               offset = prtd->period_index * runtime->period_size;
+       }
 
        if (offset >= runtime->buffer_size)
                offset = 0;
index d5fc52d..544fd95 100644 (file)
@@ -122,10 +122,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
                ssp_disable(ssp);
        }
 
-       if (cpu_dai->dma_data) {
-               kfree(cpu_dai->dma_data);
-               cpu_dai->dma_data = NULL;
-       }
+       kfree(snd_soc_dai_get_dma_data(cpu_dai, substream));
+       snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
+
        return ret;
 }
 
@@ -142,10 +141,8 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
                clk_disable(ssp->clk);
        }
 
-       if (cpu_dai->dma_data) {
-               kfree(cpu_dai->dma_data);
-               cpu_dai->dma_data = NULL;
-       }
+       kfree(snd_soc_dai_get_dma_data(cpu_dai, substream));
+       snd_soc_dai_set_dma_data(cpu_dai, substream, NULL);
 }
 
 #ifdef CONFIG_PM
@@ -570,19 +567,23 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
        u32 sspsp;
        int width = snd_pcm_format_physical_width(params_format(params));
        int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf;
+       struct pxa2xx_pcm_dma_params *dma_data;
+
+       dma_data = snd_soc_dai_get_dma_data(dai, substream);
 
        /* generate correct DMA params */
-       if (cpu_dai->dma_data)
-               kfree(cpu_dai->dma_data);
+       kfree(dma_data);
 
        /* Network mode with one active slot (ttsa == 1) can be used
         * to force 16-bit frame width on the wire (for S16_LE), even
         * with two channels. Use 16-bit DMA transfers for this case.
         */
-       cpu_dai->dma_data = ssp_get_dma_params(ssp,
+       dma_data = ssp_get_dma_params(ssp,
                        ((chn == 2) && (ttsa != 1)) || (width == 32),
                        substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 
+       snd_soc_dai_set_dma_data(dai, substream, dma_data);
+
        /* we can only change the settings if the port is not in use */
        if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
                return 0;
index e9ae7b3..d314115 100644 (file)
@@ -122,11 +122,14 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct pxa2xx_pcm_dma_params *dma_data;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
+               dma_data = &pxa2xx_ac97_pcm_stereo_out;
        else
-               cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in;
+               dma_data = &pxa2xx_ac97_pcm_stereo_in;
+
+       snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
 
        return 0;
 }
@@ -137,11 +140,14 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct pxa2xx_pcm_dma_params *dma_data;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
+               dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
        else
-               cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
+               dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
+
+       snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
 
        return 0;
 }
@@ -156,7 +162,8 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                return -ENODEV;
        else
-               cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in;
+               snd_soc_dai_set_dma_data(cpu_dai, substream,
+                                        &pxa2xx_ac97_pcm_mic_mono_in);
 
        return 0;
 }
index 6b8f655..c1a5275 100644 (file)
@@ -164,6 +164,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct pxa2xx_pcm_dma_params *dma_data;
 
        BUG_ON(IS_ERR(clk_i2s));
        clk_enable(clk_i2s);
@@ -171,9 +172,11 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
        pxa_i2s_wait();
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
+               dma_data = &pxa2xx_i2s_pcm_stereo_out;
        else
-               cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in;
+               dma_data = &pxa2xx_i2s_pcm_stereo_in;
+
+       snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
 
        /* is port used by another stream */
        if (!(SACR0 & SACR0_ENB)) {
index d38e395..adc7e6f 100644 (file)
@@ -25,9 +25,11 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct pxa2xx_runtime_data *prtd = runtime->private_data;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
+       struct pxa2xx_pcm_dma_params *dma;
        int ret;
 
+       dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+
        /* return if this is a bufferless transfer e.g.
         * codec <--> BT codec or GSM modem -- lg FIXME */
        if (!dma)
index ee8ed9d..ecf4fd0 100644 (file)
@@ -224,11 +224,14 @@ static int s3c_ac97_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct s3c_dma_params *dma_data;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               cpu_dai->dma_data = &s3c_ac97_pcm_out;
+               dma_data = &s3c_ac97_pcm_out;
        else
-               cpu_dai->dma_data = &s3c_ac97_pcm_in;
+               dma_data = &s3c_ac97_pcm_in;
+
+       snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
 
        return 0;
 }
@@ -238,8 +241,8 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
 {
        u32 ac_glbctrl;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       int channel = ((struct s3c_dma_params *)
-                 rtd->dai->cpu_dai->dma_data)->channel;
+       struct s3c_dma_params *dma_data =
+               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
 
        ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
@@ -265,7 +268,7 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
 
        writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-       s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
+       s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
 
        return 0;
 }
@@ -280,7 +283,7 @@ static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream,
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                return -ENODEV;
        else
-               cpu_dai->dma_data = &s3c_ac97_mic_in;
+               snd_soc_dai_set_dma_data(cpu_dai, substream, &s3c_ac97_mic_in);
 
        return 0;
 }
@@ -290,8 +293,8 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
 {
        u32 ac_glbctrl;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       int channel = ((struct s3c_dma_params *)
-                 rtd->dai->cpu_dai->dma_data)->channel;
+       struct s3c_dma_params *dma_data =
+               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
 
        ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
        ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK;
@@ -311,7 +314,7 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
 
        writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
-       s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
+       s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
 
        return 0;
 }
index 7725e26..1b61c23 100644 (file)
@@ -145,10 +145,12 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct s3c24xx_runtime_data *prtd = runtime->private_data;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct s3c_dma_params *dma = rtd->dai->cpu_dai->dma_data;
        unsigned long totbytes = params_buffer_bytes(params);
+       struct s3c_dma_params *dma =
+               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
        int ret = 0;
 
+
        pr_debug("Entered %s\n", __func__);
 
        /* return if this is a bufferless transfer e.g.
index e994d83..8851594 100644 (file)
@@ -339,14 +339,17 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai_link *dai = rtd->dai;
        struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai);
+       struct s3c_dma_params *dma_data;
        u32 iismod;
 
        pr_debug("Entered %s\n", __func__);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               dai->cpu_dai->dma_data = i2s->dma_playback;
+               dma_data = i2s->dma_playback;
        else
-               dai->cpu_dai->dma_data = i2s->dma_capture;
+               dma_data = i2s->dma_capture;
+
+       snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data);
 
        /* Working copies of register */
        iismod = readl(i2s->regs + S3C2412_IISMOD);
@@ -394,8 +397,8 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
        int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
        unsigned long irqs;
        int ret = 0;
-       int channel = ((struct s3c_dma_params *)
-                 rtd->dai->cpu_dai->dma_data)->channel;
+       struct s3c_dma_params *dma_data =
+               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
 
        pr_debug("Entered %s\n", __func__);
 
@@ -431,7 +434,7 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                 * of the auto reload mechanism of S3C24XX.
                 * This call won't bother S3C64XX.
                 */
-               s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
+               s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
 
                break;
 
index a98f40c..326f0a9 100644 (file)
@@ -178,6 +178,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai_link *dai = rtd->dai;
        struct s3c_pcm_info *pcm = to_info(dai->cpu_dai);
+       struct s3c_dma_params *dma_data;
        void __iomem *regs = pcm->regs;
        struct clk *clk;
        int sclk_div, sync_div;
@@ -187,9 +188,11 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
        dev_dbg(pcm->dev, "Entered %s\n", __func__);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               dai->cpu_dai->dma_data = pcm->dma_playback;
+               dma_data = pcm->dma_playback;
        else
-               dai->cpu_dai->dma_data = pcm->dma_capture;
+               dma_data = pcm->dma_capture;
+
+       snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data);
 
        /* Strictly check for sample size */
        switch (params_format(params)) {
index 0bc5950..c3ac890 100644 (file)
@@ -242,14 +242,17 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct s3c_dma_params *dma_data;
        u32 iismod;
 
        pr_debug("Entered %s\n", __func__);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out;
+               dma_data = &s3c24xx_i2s_pcm_stereo_out;
        else
-               rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_in;
+               dma_data = &s3c24xx_i2s_pcm_stereo_in;
+
+       snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_data);
 
        /* Working copies of register */
        iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -258,13 +261,11 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
                iismod &= ~S3C2410_IISMOD_16BIT;
-               ((struct s3c_dma_params *)
-                 rtd->dai->cpu_dai->dma_data)->dma_size = 1;
+               dma_data->dma_size = 1;
                break;
        case SNDRV_PCM_FORMAT_S16_LE:
                iismod |= S3C2410_IISMOD_16BIT;
-               ((struct s3c_dma_params *)
-                 rtd->dai->cpu_dai->dma_data)->dma_size = 2;
+               dma_data->dma_size = 2;
                break;
        default:
                return -EINVAL;
@@ -280,8 +281,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 {
        int ret = 0;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       int channel = ((struct s3c_dma_params *)
-                 rtd->dai->cpu_dai->dma_data)->channel;
+       struct s3c_dma_params *dma_data =
+               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
 
        pr_debug("Entered %s\n", __func__);
 
@@ -300,7 +301,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                else
                        s3c24xx_snd_txctrl(1);
 
-               s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
+               s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
index 0664fac..5b9ac17 100644 (file)
@@ -519,7 +519,8 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
 
        s6000_i2s_dai.dev = &pdev->dev;
        s6000_i2s_dai.private_data = dev;
-       s6000_i2s_dai.dma_data = &dev->dma_params;
+       s6000_i2s_dai.capture.dma_data = &dev->dma_params;
+       s6000_i2s_dai.playback.dma_data = &dev->dma_params;
 
        dev->sifbase = sifmem->start;
        dev->scbbase = mmio;
index 1d61109..9c7f7f0 100644 (file)
@@ -58,13 +58,15 @@ static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct s6000_runtime_data *prtd = runtime->private_data;
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *par;
        int channel;
        unsigned int period_size;
        unsigned int dma_offset;
        dma_addr_t dma_pos;
        dma_addr_t src, dst;
 
+       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+
        period_size = snd_pcm_lib_period_bytes(substream);
        dma_offset = prtd->period * period_size;
        dma_pos = runtime->dma_addr + dma_offset;
@@ -101,7 +103,8 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
 {
        struct snd_pcm *pcm = data;
        struct snd_soc_pcm_runtime *runtime = pcm->private_data;
-       struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *params =
+               snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
        struct s6000_runtime_data *prtd;
        unsigned int has_xrun;
        int i, ret = IRQ_NONE;
@@ -172,11 +175,13 @@ static int s6000_pcm_start(struct snd_pcm_substream *substream)
 {
        struct s6000_runtime_data *prtd = substream->runtime->private_data;
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *par;
        unsigned long flags;
        int srcinc;
        u32 dma;
 
+       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+
        spin_lock_irqsave(&prtd->lock, flags);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -212,10 +217,12 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream)
 {
        struct s6000_runtime_data *prtd = substream->runtime->private_data;
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *par;
        unsigned long flags;
        u32 channel;
 
+       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                channel = par->dma_out;
        else
@@ -236,9 +243,11 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream)
 static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *par;
        int ret;
 
+       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+
        ret = par->trigger(substream, cmd, 0);
        if (ret < 0)
                return ret;
@@ -275,13 +284,15 @@ static int s6000_pcm_prepare(struct snd_pcm_substream *substream)
 static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *par;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct s6000_runtime_data *prtd = runtime->private_data;
        unsigned long flags;
        unsigned int offset;
        dma_addr_t count;
 
+       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+
        spin_lock_irqsave(&prtd->lock, flags);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -305,11 +316,12 @@ static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)
 static int s6000_pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *par;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct s6000_runtime_data *prtd;
        int ret;
 
+       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
        snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware);
 
        ret = snd_pcm_hw_constraint_step(runtime, 0,
@@ -364,7 +376,7 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *hw_params)
 {
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *par;
        int ret;
        ret = snd_pcm_lib_malloc_pages(substream,
                                       params_buffer_bytes(hw_params));
@@ -373,6 +385,8 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
                return ret;
        }
 
+       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+
        if (par->same_rate) {
                spin_lock(&par->lock);
                if (par->rate == -1 ||
@@ -392,7 +406,8 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
 static int s6000_pcm_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *par =
+               snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
 
        spin_lock(&par->lock);
        par->in_use &= ~(1 << substream->stream);
@@ -417,7 +432,8 @@ static struct snd_pcm_ops s6000_pcm_ops = {
 static void s6000_pcm_free(struct snd_pcm *pcm)
 {
        struct snd_soc_pcm_runtime *runtime = pcm->private_data;
-       struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *params =
+               snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
 
        free_irq(params->irq, pcm);
        snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -429,9 +445,11 @@ static int s6000_pcm_new(struct snd_card *card,
                         struct snd_soc_dai *dai, struct snd_pcm *pcm)
 {
        struct snd_soc_pcm_runtime *runtime = pcm->private_data;
-       struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data;
+       struct s6000_pcm_dma_params *params;
        int res;
 
+       params = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &s6000_pcm_dmamask;
        if (!card->dev->coherent_dma_mask)
index 2320153..ad7f952 100644 (file)
@@ -1549,7 +1549,8 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
                        mutex_unlock(&codec->mutex);
                        return ret;
                }
-               if (card->dai_link[i].codec_dai->ac97_control) {
+               /* Check for codec->ac97 to handle the ac97.c fun */
+               if (card->dai_link[i].codec_dai->ac97_control && codec->ac97) {
                        snd_ac97_dev_add_pdata(codec->ac97,
                                card->dai_link[i].cpu_dai->ac97_pdata);
                }