Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* '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
This commit is contained in:
Linus Torvalds 2010-04-07 08:42:25 -07:00
commit 84db18bbeb
36 changed files with 408 additions and 212 deletions

View 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

View 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);

View 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

View 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 */

View 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;

View 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);

View 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 */
{}
};

View 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;

View 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);
}
}

View 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;
}

View 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;

View 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);

View 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:

View 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));
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));
/* Disable main biases */
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
/* Disable main biases */
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
WM8994_BIAS_ENA |
WM8994_VMID_SEL_MASK, 0);
/* Discharge line */
snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
WM8994_LINEOUT1_DISCH |
WM8994_LINEOUT2_DISCH,
WM8994_LINEOUT1_DISCH |
WM8994_LINEOUT2_DISCH);
/* Discharge line */
snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
WM8994_LINEOUT1_DISCH |
WM8994_LINEOUT2_DISCH,
WM8994_LINEOUT1_DISCH |
WM8994_LINEOUT2_DISCH);
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);
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

View 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))

View 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;
};

View 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;

View 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]);

View 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];

View 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;

View 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 */

View 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 */

View 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) {

View 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;

View 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;

View 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;
}

View 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)) {

View 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)

View 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;
}

View 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.

View 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;

View 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)) {

View 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:

View 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;

View 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)

View 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);
}