diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-01-07 14:14:15 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-01-07 14:14:15 +0100 |
commit | 1c2a48cf65580a276552151eb8f78d78c55b828e (patch) | |
tree | 68ed0628a276b33cb5aa0ad4899c1afe0a33a69d /sound | |
parent | 0aa002fe602939370e9476e5ec32b562000a0425 (diff) | |
parent | cb600d2f83c854ec3d6660063e4466431999489b (diff) |
Merge branch 'linus' into x86/apic-cleanups
Conflicts:
arch/x86/include/asm/io_apic.h
Merge reason: Resolve the conflict, update to a more recent -rc base
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'sound')
92 files changed, 860 insertions, 650 deletions
diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c index f2f41c854221..6e2409181895 100644 --- a/sound/atmel/abdac.c +++ b/sound/atmel/abdac.c @@ -420,9 +420,9 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev) return PTR_ERR(pclk); } sample_clk = clk_get(&pdev->dev, "sample_clk"); - if (IS_ERR(pclk)) { + if (IS_ERR(sample_clk)) { dev_dbg(&pdev->dev, "no sample clock\n"); - retval = PTR_ERR(pclk); + retval = PTR_ERR(sample_clk); goto out_put_pclk; } clk_enable(pclk); diff --git a/sound/core/info.c b/sound/core/info.c index b70564ed8b37..7077f601da5a 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -23,7 +23,6 @@ #include <linux/time.h> #include <linux/mm.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/string.h> #include <sound/core.h> #include <sound/minors.h> diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 5c8c7dff8ede..b753ec661fcf 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1510,16 +1510,19 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file) { struct snd_pcm_substream *substream; + struct snd_pcm_runtime *runtime; + int i; - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; - if (substream != NULL) { - snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); - substream->runtime->oss.prepare = 1; - } - substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; - if (substream != NULL) { + for (i = 0; i < 2; i++) { + substream = pcm_oss_file->streams[i]; + if (!substream) + continue; + runtime = substream->runtime; snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); - substream->runtime->oss.prepare = 1; + runtime->oss.prepare = 1; + runtime->oss.buffer_used = 0; + runtime->oss.prev_hw_ptr_period = 0; + runtime->oss.period_ptr = 0; } return 0; } diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index a1707cca9c66..11446a1506da 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -223,7 +223,7 @@ static void xrun_log(struct snd_pcm_substream *substream, entry->jiffies = jiffies; entry->pos = pos; entry->period_size = runtime->period_size; - entry->buffer_size = runtime->buffer_size;; + entry->buffer_size = runtime->buffer_size; entry->old_hw_ptr = runtime->status->hw_ptr; entry->hw_ptr_base = runtime->hw_ptr_base; log->idx = (log->idx + 1) % XRUN_LOG_CNT; @@ -1070,8 +1070,10 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, struct snd_pcm_hw_rule *new; unsigned int new_rules = constrs->rules_all + 16; new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL); - if (!new) + if (!new) { + va_end(args); return -ENOMEM; + } if (constrs->rules) { memcpy(new, constrs->rules, constrs->rules_num * sizeof(*c)); @@ -1087,8 +1089,10 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, c->private = private; k = 0; while (1) { - if (snd_BUG_ON(k >= ARRAY_SIZE(c->deps))) + if (snd_BUG_ON(k >= ARRAY_SIZE(c->deps))) { + va_end(args); return -EINVAL; + } c->deps[k++] = dep; if (dep < 0) break; @@ -1097,7 +1101,7 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, constrs->rules_num++; va_end(args); return 0; -} +} EXPORT_SYMBOL(snd_pcm_hw_rule_add); diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 8bc7cb3db330..e82c1f97d99e 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -22,7 +22,6 @@ #include <linux/mm.h> #include <linux/file.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/time.h> #include <linux/pm_qos_params.h> #include <linux/uio.h> diff --git a/sound/core/sound.c b/sound/core/sound.c index 62a093efb453..66691fe437e6 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -21,7 +21,6 @@ #include <linux/init.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/time.h> #include <linux/device.h> #include <linux/moduleparam.h> diff --git a/sound/oss/dev_table.c b/sound/oss/dev_table.c index 727bdb9ba2dc..d8cf3e58dc76 100644 --- a/sound/oss/dev_table.c +++ b/sound/oss/dev_table.c @@ -71,7 +71,7 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, if (sound_nblocks >= MAX_MEM_BLOCKS) sound_nblocks = MAX_MEM_BLOCKS - 1; - op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_operations))); + op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct audio_operations))); sound_nblocks++; if (sound_nblocks >= MAX_MEM_BLOCKS) sound_nblocks = MAX_MEM_BLOCKS - 1; @@ -81,7 +81,6 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, sound_unload_audiodev(num); return -(ENOMEM); } - memset((char *) op, 0, sizeof(struct audio_operations)); init_waitqueue_head(&op->in_sleeper); init_waitqueue_head(&op->out_sleeper); init_waitqueue_head(&op->poll_sleeper); @@ -128,7 +127,7 @@ int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, /* FIXME: This leaks a mixer_operations struct every time its called until you unload sound! */ - op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations))); + op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vzalloc(sizeof(struct mixer_operations))); sound_nblocks++; if (sound_nblocks >= MAX_MEM_BLOCKS) sound_nblocks = MAX_MEM_BLOCKS - 1; @@ -137,7 +136,6 @@ int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); return -ENOMEM; } - memset((char *) op, 0, sizeof(struct mixer_operations)); memcpy((char *) op, (char *) driver, driver_size); strlcpy(op->name, name, sizeof(op->name)); diff --git a/sound/oss/midibuf.c b/sound/oss/midibuf.c index 782b3b84dac6..ceedb1eff203 100644 --- a/sound/oss/midibuf.c +++ b/sound/oss/midibuf.c @@ -178,7 +178,7 @@ int MIDIbuf_open(int dev, struct file *file) return err; parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT; - midi_in_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf)); + midi_in_buf[dev] = vmalloc(sizeof(struct midi_buf)); if (midi_in_buf[dev] == NULL) { @@ -188,7 +188,7 @@ int MIDIbuf_open(int dev, struct file *file) } midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0; - midi_out_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf)); + midi_out_buf[dev] = vmalloc(sizeof(struct midi_buf)); if (midi_out_buf[dev] == NULL) { diff --git a/sound/oss/pss.c b/sound/oss/pss.c index e19dd5dcc2de..9b800ce5100e 100644 --- a/sound/oss/pss.c +++ b/sound/oss/pss.c @@ -859,7 +859,7 @@ static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, return 0; case SNDCTL_COPR_LOAD: - buf = (copr_buffer *) vmalloc(sizeof(copr_buffer)); + buf = vmalloc(sizeof(copr_buffer)); if (buf == NULL) return -ENOSPC; if (copy_from_user(buf, arg, sizeof(copr_buffer))) { @@ -871,7 +871,7 @@ static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, return err; case SNDCTL_COPR_SENDMSG: - mbuf = (copr_msg *)vmalloc(sizeof(copr_msg)); + mbuf = vmalloc(sizeof(copr_msg)); if (mbuf == NULL) return -ENOSPC; if (copy_from_user(mbuf, arg, sizeof(copr_msg))) { @@ -895,7 +895,7 @@ static int pss_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, case SNDCTL_COPR_RCVMSG: err = 0; - mbuf = (copr_msg *)vmalloc(sizeof(copr_msg)); + mbuf = vmalloc(sizeof(copr_msg)); if (mbuf == NULL) return -ENOSPC; data = (unsigned short *)mbuf->data; diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c index e85789e53816..5ea1098ac427 100644 --- a/sound/oss/sequencer.c +++ b/sound/oss/sequencer.c @@ -1646,13 +1646,13 @@ void sequencer_init(void) { if (sequencer_ok) return; - queue = (unsigned char *)vmalloc(SEQ_MAX_QUEUE * EV_SZ); + queue = vmalloc(SEQ_MAX_QUEUE * EV_SZ); if (queue == NULL) { printk(KERN_ERR "sequencer: Can't allocate memory for sequencer output queue\n"); return; } - iqueue = (unsigned char *)vmalloc(SEQ_MAX_QUEUE * IEV_SZ); + iqueue = vmalloc(SEQ_MAX_QUEUE * IEV_SZ); if (iqueue == NULL) { printk(KERN_ERR "sequencer: Can't allocate memory for sequencer input queue\n"); diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 46c0d03dbecc..fcb14a099822 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -87,7 +87,7 @@ int *load_mixer_volumes(char *name, int *levels, int present) int i, n; for (i = 0; i < num_mixer_volumes; i++) { - if (strcmp(name, mixer_vols[i].name) == 0) { + if (strncmp(name, mixer_vols[i].name, 32) == 0) { if (present) mixer_vols[i].num = i; return mixer_vols[i].levels; @@ -99,7 +99,7 @@ int *load_mixer_volumes(char *name, int *levels, int present) } n = num_mixer_volumes++; - strcpy(mixer_vols[n].name, name); + strncpy(mixer_vols[n].name, name, 32); if (present) mixer_vols[n].num = n; diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c index 62895a719fcb..22dbd91811a4 100644 --- a/sound/pci/asihpi/hpioctl.c +++ b/sound/pci/asihpi/hpioctl.c @@ -435,7 +435,7 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev) struct hpi_message hm; struct hpi_response hr; struct hpi_adapter *pa; - pa = (struct hpi_adapter *)pci_get_drvdata(pci_dev); + pa = pci_get_drvdata(pci_dev); hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_DELETE_ADAPTER); diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 4679ed83a43b..2f3cacbd5528 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -1129,10 +1129,11 @@ snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip, count_areas = size/2; addr_area2 = addr+count_areas; - count_areas--; /* max. index */ snd_azf3328_dbgcodec("setdma: buffers %08lx[%u] / %08lx[%u]\n", addr, count_areas, addr_area2, count_areas); + count_areas--; /* max. index */ + /* build combined I/O buffer length word */ lengths = (count_areas << 16) | (count_areas); spin_lock_irqsave(&chip->reg_lock, flags); @@ -1740,11 +1741,15 @@ static const struct snd_pcm_hardware snd_azf3328_hardware = .rate_max = AZF_FREQ_66200, .channels_min = 1, .channels_max = 2, - .buffer_bytes_max = 65536, - .period_bytes_min = 64, - .period_bytes_max = 65536, - .periods_min = 1, - .periods_max = 1024, + .buffer_bytes_max = (64*1024), + .period_bytes_min = 1024, + .period_bytes_max = (32*1024), + /* We simply have two DMA areas (instead of a list of descriptors + such as other cards); I believe that this is a fixed hardware + attribute and there isn't much driver magic to be done to expand it. + Thus indicate that we have at least and at most 2 periods. */ + .periods_min = 2, + .periods_max = 2, /* FIXME: maybe that card actually has a FIFO? * Hmm, it seems newer revisions do have one, but we still don't know * its size... */ @@ -1980,8 +1985,13 @@ snd_azf3328_timer_stop(struct snd_timer *timer) chip = snd_timer_chip(timer); spin_lock_irqsave(&chip->reg_lock, flags); /* disable timer countdown and interrupt */ - /* FIXME: should we write TIMER_IRQ_ACK here? */ - snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0); + /* Hmm, should we write TIMER_IRQ_ACK here? + YES indeed, otherwise a rogue timer operation - which prompts + ALSA(?) to call repeated stop() in vain, but NOT start() - + will never end (value 0x03 is kept shown in control byte). + Simply manually poking 0x04 _once_ immediately successfully stops + the hardware/ALSA interrupt activity. */ + snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x04); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_azf3328_dbgcallleave(); return 0; diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index 85ab43e89212..457d21189b0d 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c @@ -129,8 +129,6 @@ static int ct_pcm_playback_open(struct snd_pcm_substream *substream) apcm->substream = substream; apcm->interrupt = ct_atc_pcm_interrupt; - runtime->private_data = apcm; - runtime->private_free = ct_atc_pcm_free_substream; if (IEC958 == substream->pcm->device) { runtime->hw = ct_spdif_passthru_playback_hw; atc->spdif_out_passthru(atc, 1); @@ -155,8 +153,12 @@ static int ct_pcm_playback_open(struct snd_pcm_substream *substream) } apcm->timer = ct_timer_instance_new(atc->timer, apcm); - if (!apcm->timer) + if (!apcm->timer) { + kfree(apcm); return -ENOMEM; + } + runtime->private_data = apcm; + runtime->private_free = ct_atc_pcm_free_substream; return 0; } @@ -278,8 +280,6 @@ static int ct_pcm_capture_open(struct snd_pcm_substream *substream) apcm->started = 0; apcm->substream = substream; apcm->interrupt = ct_atc_pcm_interrupt; - runtime->private_data = apcm; - runtime->private_free = ct_atc_pcm_free_substream; runtime->hw = ct_pcm_capture_hw; runtime->hw.rate_max = atc->rsr * atc->msr; @@ -298,8 +298,12 @@ static int ct_pcm_capture_open(struct snd_pcm_substream *substream) } apcm->timer = ct_timer_instance_new(atc->timer, apcm); - if (!apcm->timer) + if (!apcm->timer) { + kfree(apcm); return -ENOMEM; + } + runtime->private_data = apcm; + runtime->private_free = ct_atc_pcm_free_substream; return 0; } diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 644e3f14f8ca..98b6d02a36c9 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1919,6 +1919,16 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec, } EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl); +static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name) +{ + int idx; + for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */ + if (!_snd_hda_find_mixer_ctl(codec, name, idx)) + return idx; + } + return -EBUSY; +} + /** * snd_hda_ctl_add - Add a control element and assign to the codec * @codec: HD-audio codec @@ -2654,8 +2664,6 @@ static struct snd_kcontrol_new dig_mixes[] = { { } /* end */ }; -#define SPDIF_MAX_IDX 4 /* 4 instances should be enough to probe */ - /** * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls * @codec: the HDA codec @@ -2673,12 +2681,8 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid) struct snd_kcontrol_new *dig_mix; int idx; - for (idx = 0; idx < SPDIF_MAX_IDX; idx++) { - if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch", - idx)) - break; - } - if (idx >= SPDIF_MAX_IDX) { + idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch"); + if (idx < 0) { printk(KERN_ERR "hda_codec: too many IEC958 outputs\n"); return -EBUSY; } @@ -2829,12 +2833,8 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid) struct snd_kcontrol_new *dig_mix; int idx; - for (idx = 0; idx < SPDIF_MAX_IDX; idx++) { - if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch", - idx)) - break; - } - if (idx >= SPDIF_MAX_IDX) { + idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch"); + if (idx < 0) { printk(KERN_ERR "hda_codec: too many IEC958 inputs\n"); return -EBUSY; } @@ -3808,21 +3808,32 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew) for (; knew->name; knew++) { struct snd_kcontrol *kctl; + int addr = 0, idx = 0; if (knew->iface == -1) /* skip this codec private value */ continue; - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) { - if (!codec->addr) - return err; + for (;;) { kctl = snd_ctl_new1(knew, codec); if (!kctl) return -ENOMEM; - kctl->id.device = codec->addr; + if (addr > 0) + kctl->id.device = addr; + if (idx > 0) + kctl->id.index = idx; err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) + if (!err) + break; + /* try first with another device index corresponding to + * the codec addr; if it still fails (or it's the + * primary codec), then try another control index + */ + if (!addr && codec->addr) + addr = codec->addr; + else if (!idx && !knew->index) { + idx = find_empty_mixer_ctl_idx(codec, + knew->name); + if (idx <= 0) + return err; + } else return err; } } diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index cb0c23a6b473..4a663471dadc 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -189,6 +189,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, a->channels = GRAB_BITS(buf, 0, 0, 3); a->channels++; + a->sample_bits = 0; + a->max_bitrate = 0; + a->format = GRAB_BITS(buf, 0, 3, 4); switch (a->format) { case AUDIO_CODING_TYPE_REF_STREAM_HEADER: @@ -198,7 +201,6 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a, case AUDIO_CODING_TYPE_LPCM: val = GRAB_BITS(buf, 2, 0, 3); - a->sample_bits = 0; for (i = 0; i < 3; i++) if (val & (1 << i)) a->sample_bits |= cea_sample_sizes[i + 1]; @@ -598,24 +600,19 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm, { int i; - pcm->rates = 0; - pcm->formats = 0; - pcm->maxbps = 0; - pcm->channels_min = -1; - pcm->channels_max = 0; + /* assume basic audio support (the basic audio flag is not in ELD; + * however, all audio capable sinks are required to support basic + * audio) */ + pcm->rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; + pcm->formats = SNDRV_PCM_FMTBIT_S16_LE; + pcm->maxbps = 16; + pcm->channels_max = 2; for (i = 0; i < eld->sad_count; i++) { struct cea_sad *a = &eld->sad[i]; pcm->rates |= a->rates; - if (a->channels < pcm->channels_min) - pcm->channels_min = a->channels; if (a->channels > pcm->channels_max) pcm->channels_max = a->channels; if (a->format == AUDIO_CODING_TYPE_LPCM) { - if (a->sample_bits & AC_SUPPCM_BITS_16) { - pcm->formats |= SNDRV_PCM_FMTBIT_S16_LE; - if (pcm->maxbps < 16) - pcm->maxbps = 16; - } if (a->sample_bits & AC_SUPPCM_BITS_20) { pcm->formats |= SNDRV_PCM_FMTBIT_S32_LE; if (pcm->maxbps < 20) @@ -635,7 +632,6 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm, /* restrict the parameters by the values the codec provides */ pcm->rates &= codec_pars->rates; pcm->formats &= codec_pars->formats; - pcm->channels_min = max(pcm->channels_min, codec_pars->channels_min); pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max); pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps); } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 21aa9b0e28f6..a1c4008af891 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2296,9 +2296,11 @@ static int azx_dev_free(struct snd_device *device) */ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1025, 0x009f, "Acer Aspire 5110", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1025, 0x026f, "Acer Aspire 5538", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1028, 0x0470, "Dell Inspiron 1120", POS_FIX_LPIB), SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 6361f752b5f3..76bd58a0e2b6 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -2116,8 +2116,8 @@ static void cxt5066_update_speaker(struct hda_codec *codec) struct conexant_spec *spec = codec->spec; unsigned int pinctl; - snd_printdd("CXT5066: update speaker, hp_present=%d\n", - spec->hp_present); + snd_printdd("CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n", + spec->hp_present, spec->cur_eapd); /* Port A (HP) */ pinctl = ((spec->hp_present & 1) && spec->cur_eapd) ? PIN_HP : 0; @@ -2125,11 +2125,20 @@ static void cxt5066_update_speaker(struct hda_codec *codec) pinctl); /* Port D (HP/LO) */ - pinctl = ((spec->hp_present & 2) && spec->cur_eapd) - ? spec->port_d_mode : 0; - /* Mute if Port A is connected on Thinkpad */ - if (spec->thinkpad && (spec->hp_present & 1)) - pinctl = 0; + if (spec->dell_automute) { + /* DELL AIO Port Rule: PortA> PortD> IntSpk */ + pinctl = (!(spec->hp_present & 1) && spec->cur_eapd) + ? PIN_OUT : 0; + } else if (spec->thinkpad) { + if (spec->cur_eapd) + pinctl = spec->port_d_mode; + /* Mute dock line-out if Port A (laptop HP) is present */ + if (spec->hp_present& 1) + pinctl = 0; + } else { + pinctl = ((spec->hp_present & 2) && spec->cur_eapd) + ? spec->port_d_mode : 0; + } snd_hda_codec_write(codec, 0x1c, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); @@ -2137,14 +2146,6 @@ static void cxt5066_update_speaker(struct hda_codec *codec) pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); - - if (spec->dell_automute) { - /* DELL AIO Port Rule: PortA > PortD > IntSpk */ - pinctl = (!(spec->hp_present & 1) && spec->cur_eapd) - ? PIN_OUT : 0; - snd_hda_codec_write(codec, 0x1c, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl); - } } /* turn on/off EAPD (+ mute HP) as a master switch */ @@ -3095,11 +3096,11 @@ static const char *cxt5066_models[CXT5066_MODELS] = { static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), - SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", - CXT5066_DELL_LAPTOP), + SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), + SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_HP_LAPTOP), SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), @@ -3108,8 +3109,10 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), + SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD), + SND_PCI_QUIRK(0x17aa, 0x21c8, "Thinkpad Edge 11", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G series", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x390a, "Lenovo S10-3t", CXT5066_IDEAPAD), diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index d3e49aa5b9ec..31df7747990d 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -834,7 +834,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, return -ENODEV; } else { /* fallback to the codec default */ - hinfo->channels_min = codec_pars->channels_min; hinfo->channels_max = codec_pars->channels_max; hinfo->rates = codec_pars->rates; hinfo->formats = codec_pars->formats; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5f00589cb791..552a09e9211f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -1614,6 +1614,7 @@ do_sku: spec->init_amp = ALC_INIT_GPIO3; break; case 5: + default: spec->init_amp = ALC_INIT_DEFAULT; break; } @@ -2014,6 +2015,36 @@ static struct hda_verb alc888_acer_aspire_6530g_verbs[] = { }; /* + *ALC888 Acer Aspire 7730G model + */ + +static struct hda_verb alc888_acer_aspire_7730G_verbs[] = { +/* 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) */ + {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, +/* Unselect Front Mic by default in input mixer 3 */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)}, +/* Enable unsolicited event for HP jack */ + {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, +/* 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}, +/*Enable internal subwoofer */ + {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x17, AC_VERB_SET_CONNECT_SEL, 0x02}, + {0x17, AC_VERB_SET_EAPD_BTLENABLE, 2}, + { } +}; + +/* * ALC889 Acer Aspire 8930G model */ @@ -2200,6 +2231,16 @@ static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec) spec->autocfg.speaker_pins[2] = 0x17; } +static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + spec->autocfg.hp_pins[0] = 0x15; + spec->autocfg.speaker_pins[0] = 0x14; + spec->autocfg.speaker_pins[1] = 0x16; + spec->autocfg.speaker_pins[2] = 0x17; +} + static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -4554,6 +4595,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW), SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), + SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG), SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG), SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW), SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700), @@ -9524,13 +9566,6 @@ static struct hda_verb alc883_acer_eapd_verbs[] = { { } }; -static struct hda_verb alc888_acer_aspire_7730G_verbs[] = { - {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x17, AC_VERB_SET_CONNECT_SEL, 0x02}, - {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, - { } /* end */ -}; - static void alc888_6st_dell_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -9831,7 +9866,6 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763), SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763), SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY), - SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG), SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66), @@ -10328,7 +10362,7 @@ static struct alc_config_preset alc882_presets[] = { .const_channel_count = 6, .input_mux = &alc883_capture_source, .unsol_event = alc_automute_amp_unsol_event, - .setup = alc888_acer_aspire_6530g_setup, + .setup = alc888_acer_aspire_7730g_setup, .init_hook = alc_automute_amp, }, [ALC883_MEDION] = { @@ -10796,7 +10830,8 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - int i, err; + int i, err, type; + int type_idx = 0; hda_nid_t nid; for (i = 0; i < cfg->num_inputs; i++) { @@ -10805,9 +10840,15 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec) nid = cfg->inputs[i].pin; if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { char label[32]; + type = cfg->inputs[i].type; + if (i > 0 && type == cfg->inputs[i - 1].type) + type_idx++; + else + type_idx = 0; snprintf(label, sizeof(label), "%s Boost", hda_get_autocfg_input_label(codec, cfg, i)); - err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0, + err = add_control(spec, ALC_CTL_WIDGET_VOL, label, + type_idx, HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); if (err < 0) return err; @@ -14623,7 +14664,10 @@ static int alc275_setup_dual_adc(struct hda_codec *codec) /* different alc269-variants */ enum { ALC269_TYPE_NORMAL, + ALC269_TYPE_ALC258, ALC269_TYPE_ALC259, + ALC269_TYPE_ALC269VB, + ALC269_TYPE_ALC270, ALC269_TYPE_ALC271X, }; @@ -14762,7 +14806,10 @@ static int alc269_resume(struct hda_codec *codec) enum { ALC269_FIXUP_SONY_VAIO, + ALC275_FIX_SONY_VAIO_GPIO2, ALC269_FIXUP_DELL_M101Z, + ALC269_FIXUP_SKU_IGNORE, + ALC269_FIXUP_ASUS_G73JW, }; static const struct alc_fixup alc269_fixups[] = { @@ -14772,6 +14819,14 @@ static const struct alc_fixup alc269_fixups[] = { {} } }, + [ALC275_FIX_SONY_VAIO_GPIO2] = { + .verbs = (const struct hda_verb[]) { + {0x01, AC_VERB_SET_GPIO_MASK, 0x04}, + {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04}, + {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, + { } + } + }, [ALC269_FIXUP_DELL_M101Z] = { .verbs = (const struct hda_verb[]) { /* Enables internal speaker */ @@ -14780,11 +14835,26 @@ static const struct alc_fixup alc269_fixups[] = { {} } }, + [ALC269_FIXUP_SKU_IGNORE] = { + .sku = ALC_FIXUP_SKU_IGNORE, + }, + [ALC269_FIXUP_ASUS_G73JW] = { + .pins = (const struct alc_pincfg[]) { + { 0x17, 0x99130111 }, /* subwoofer */ + { } + } + }, }; static struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2), + SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2), + SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2), SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), + SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), {} }; @@ -15023,7 +15093,7 @@ static int alc269_fill_coef(struct hda_codec *codec) static int patch_alc269(struct hda_codec *codec) { struct alc_spec *spec; - int board_config; + int board_config, coef; int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); @@ -15034,19 +15104,29 @@ static int patch_alc269(struct hda_codec *codec) alc_auto_parse_customize_define(codec); - if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ - if (codec->bus->pci->subsystem_vendor == 0x1025 && - spec->cdefine.platform_type == 1) { - alc_codec_rename(codec, "ALC271X"); - spec->codec_variant = ALC269_TYPE_ALC271X; - } else { - alc_codec_rename(codec, "ALC259"); - spec->codec_variant = ALC269_TYPE_ALC259; - } - } else - alc_fix_pll_init(codec, 0x20, 0x04, 15); - - alc269_fill_coef(codec); + if (codec->vendor_id == 0x10ec0269) { + coef = alc_read_coef_idx(codec, 0); + if ((coef & 0x00f0) == 0x0010) { + if (codec->bus->pci->subsystem_vendor == 0x1025 && + spec->cdefine.platform_type == 1) { + alc_codec_rename(codec, "ALC271X"); + spec->codec_variant = ALC269_TYPE_ALC271X; + } else if ((coef & 0xf000) == 0x1000) { + spec->codec_variant = ALC269_TYPE_ALC270; + } else if ((coef & 0xf000) == 0x2000) { + alc_codec_rename(codec, "ALC259"); + spec->codec_variant = ALC269_TYPE_ALC259; + } else if ((coef & 0xf000) == 0x3000) { + alc_codec_rename(codec, "ALC258"); + spec->codec_variant = ALC269_TYPE_ALC258; + } else { + alc_codec_rename(codec, "ALC269VB"); + spec->codec_variant = ALC269_TYPE_ALC269VB; + } + } else + alc_fix_pll_init(codec, 0x20, 0x04, 15); + alc269_fill_coef(codec); + } board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, alc269_models, @@ -15104,7 +15184,7 @@ static int patch_alc269(struct hda_codec *codec) spec->stream_digital_capture = &alc269_pcm_digital_capture; if (!spec->adc_nids) { /* wasn't filled automatically? use default */ - if (spec->codec_variant != ALC269_TYPE_NORMAL) { + if (spec->codec_variant == ALC269_TYPE_NORMAL) { spec->adc_nids = alc269_adc_nids; spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); spec->capsrc_nids = alc269_capsrc_nids; @@ -16898,7 +16978,7 @@ static struct alc_config_preset alc861vd_presets[] = { static int alc861vd_auto_create_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { - return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0); + return alc_auto_create_input_ctls(codec, cfg, 0x0b, 0x22, 0); } @@ -18952,6 +19032,8 @@ static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid) return 0x02; else if (nid >= 0x0c && nid <= 0x0e) return nid - 0x0c + 0x02; + else if (nid == 0x26) /* ALC887-VD has this DAC too */ + return 0x25; else return 0; } @@ -18960,7 +19042,7 @@ static inline hda_nid_t alc662_mix_to_dac(hda_nid_t nid) static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac) { - hda_nid_t mix[4]; + hda_nid_t mix[5]; int i, num; num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix)); @@ -19298,6 +19380,7 @@ static const struct alc_fixup alc662_fixups[] = { static struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), + SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), {} @@ -19419,7 +19502,10 @@ static int patch_alc888(struct hda_codec *codec) { if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){ kfree(codec->chip_name); - codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL); + if (codec->vendor_id == 0x10ec0887) + codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL); + else + codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL); if (!codec->chip_name) { alc_free(codec); return -ENOMEM; @@ -19909,7 +19995,7 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A", .patch = patch_alc882 }, { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, - { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 }, + { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 }, { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200", .patch = patch_alc882 }, { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 }, diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 93fa59cc60ef..f03b2ff90496 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -389,6 +389,11 @@ static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { 0x11, 0x20, 0 }; +#define STAC92HD87B_NUM_DMICS 1 +static hda_nid_t stac92hd87b_dmic_nids[STAC92HD87B_NUM_DMICS + 1] = { + 0x11, 0 +}; + #define STAC92HD83XXX_NUM_CAPS 2 static unsigned long stac92hd83xxx_capvols[] = { HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), @@ -1622,6 +1627,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { static struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a1, "Alienware M17x", STAC_ALIENWARE_M17X), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a, + "Alienware M17x", STAC_ALIENWARE_M17X), {} /* terminator */ }; @@ -3474,6 +3481,8 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, label = hda_get_input_pin_label(codec, nid, 1); snd_hda_add_imux_item(dimux, label, index, &type_idx); + if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) + snd_hda_add_imux_item(imux, label, index, &type_idx); err = create_elem_capture_vol(codec, nid, label, type_idx, HDA_INPUT); @@ -3485,11 +3494,6 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, if (err < 0) return err; } - - if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) { - snd_hda_add_imux_item(imux, label, index, NULL); - spec->num_analog_muxes++; - } } return 0; @@ -5452,12 +5456,17 @@ again: stac92hd83xxx_brd_tbl[spec->board_config]); switch (codec->vendor_id) { + case 0x111d76d1: + case 0x111d76d9: + spec->dmic_nids = stac92hd87b_dmic_nids; + spec->num_dmics = stac92xx_connected_ports(codec, + stac92hd87b_dmic_nids, + STAC92HD87B_NUM_DMICS); + /* Fall through */ case 0x111d7666: case 0x111d7667: case 0x111d7668: case 0x111d7669: - case 0x111d76d1: - case 0x111d76d9: spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); spec->pin_nids = stac92hd88xxx_pin_nids; spec->mono_nid = 0; diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 400f9ebd243e..629a5494347a 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1866,6 +1866,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x1028, + .subdevice = 0x0182, + .name = "Dell Latitude D610", /* STAC9750/51 */ + .type = AC97_TUNE_HP_ONLY + }, + { + .subvendor = 0x1028, .subdevice = 0x0186, .name = "Dell Latitude D810", /* cf. Malone #41015 */ .type = AC97_TUNE_HP_MUTE_LED diff --git a/sound/pci/mixart/mixart_hwdep.h b/sound/pci/mixart/mixart_hwdep.h index a46f5083db99..812e288ef2e7 100644 --- a/sound/pci/mixart/mixart_hwdep.h +++ b/sound/pci/mixart/mixart_hwdep.h @@ -25,11 +25,21 @@ #include <sound/hwdep.h> +#ifndef readl_be #define readl_be(x) be32_to_cpu(__raw_readl(x)) +#endif + +#ifndef writel_be #define writel_be(data,addr) __raw_writel(cpu_to_be32(data),addr) +#endif +#ifndef readl_le #define readl_le(x) le32_to_cpu(__raw_readl(x)) +#endif + +#ifndef writel_le #define writel_le(data,addr) __raw_writel(cpu_to_le32(data),addr) +#endif #define MIXART_MEM(mgr,x) ((mgr)->mem[0].virt + (x)) #define MIXART_REG(mgr,x) ((mgr)->mem[1].virt + (x)) diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 85081172403f..b47cfd45b3b9 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -1228,10 +1228,8 @@ int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) chip->rsrc[i].start + 1, rnames[i]) == NULL) { printk(KERN_ERR "snd: can't request rsrc " - " %d (%s: 0x%016llx:%016llx)\n", - i, rnames[i], - (unsigned long long)chip->rsrc[i].start, - (unsigned long long)chip->rsrc[i].end); + " %d (%s: %pR)\n", + i, rnames[i], &chip->rsrc[i]); err = -ENODEV; goto __error; } @@ -1256,10 +1254,8 @@ int __devinit snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) chip->rsrc[i].start + 1, rnames[i]) == NULL) { printk(KERN_ERR "snd: can't request rsrc " - " %d (%s: 0x%016llx:%016llx)\n", - i, rnames[i], - (unsigned long long)chip->rsrc[i].start, - (unsigned long long)chip->rsrc[i].end); + " %d (%s: %pR)\n", + i, rnames[i], &chip->rsrc[i]); err = -ENODEV; goto __error; } diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index e720d5e6f04c..bee3c94f58b0 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -16,7 +16,8 @@ config SND_ATMEL_SOC_SSC config SND_AT91_SOC_SAM9G20_WM8731 tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" - depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC + depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC && \ + AT91_PROGRAMMABLE_CLOCKS select SND_ATMEL_SOC_SSC select SND_SOC_WM8731 help @@ -25,7 +26,7 @@ config SND_AT91_SOC_SAM9G20_WM8731 config SND_AT32_SOC_PLAYPAQ tristate "SoC Audio support for PlayPaq with WM8510" - depends on SND_ATMEL_SOC && BOARD_PLAYPAQ + depends on SND_ATMEL_SOC && BOARD_PLAYPAQ && AT91_PROGRAMMABLE_CLOCKS select SND_ATMEL_SOC_SSC select SND_SOC_WM8510 help diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c index 293569dfd0ed..e521ada80542 100644 --- a/sound/soc/atmel/sam9g20_wm8731.c +++ b/sound/soc/atmel/sam9g20_wm8731.c @@ -222,9 +222,9 @@ static int __init at91sam9g20ek_init(void) } pllb = clk_get(NULL, "pllb"); - if (IS_ERR(mclk)) { + if (IS_ERR(pllb)) { printk(KERN_ERR "ASoC: Failed to get PLLB\n"); - ret = PTR_ERR(mclk); + ret = PTR_ERR(pllb); goto err_mclk; } ret = clk_set_parent(mclk, pllb); @@ -240,6 +240,7 @@ static int __init at91sam9g20ek_init(void) if (!at91sam9g20ek_snd_device) { printk(KERN_ERR "ASoC: Platform device allocation failed\n"); ret = -ENOMEM; + goto err_mclk; } platform_set_drvdata(at91sam9g20ek_snd_device, @@ -248,11 +249,13 @@ static int __init at91sam9g20ek_init(void) ret = platform_device_add(at91sam9g20ek_snd_device); if (ret) { printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - platform_device_put(at91sam9g20ek_snd_device); + goto err_device_add; } return ret; +err_device_add: + platform_device_put(at91sam9g20ek_snd_device); err_mclk: clk_put(mclk); mclk = NULL; diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c index e3d283561c19..86e0f8586dc3 100644 --- a/sound/soc/atmel/snd-soc-afeb9260.c +++ b/sound/soc/atmel/snd-soc-afeb9260.c @@ -167,7 +167,6 @@ static int __init afeb9260_soc_init(void) return 0; err1: - platform_device_del(afeb9260_snd_device); platform_device_put(afeb9260_snd_device); return err; } diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index bc22ee93a75d..6447dbb2f123 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -28,6 +28,11 @@ #include <sound/max98088.h> #include "max98088.h" +enum max98088_type { + MAX98088, + MAX98089, +}; + struct max98088_cdata { unsigned int rate; unsigned int fmt; @@ -35,7 +40,7 @@ struct max98088_cdata { }; struct max98088_priv { - u8 reg_cache[M98088_REG_CNT]; + enum max98088_type devtype; void *control_data; struct max98088_pdata *pdata; unsigned int sysclk; @@ -1582,7 +1587,7 @@ static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai, static void max98088_sync_cache(struct snd_soc_codec *codec) { - struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int i; if (!codec->cache_sync) @@ -1593,14 +1598,14 @@ static void max98088_sync_cache(struct snd_soc_codec *codec) /* write back cached values if they're writeable and * different from the hardware default. */ - for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) { + for (i = 1; i < codec->driver->reg_cache_size; i++) { if (!max98088_access[i].writable) continue; - if (max98088->reg_cache[i] == max98088_reg[i]) + if (reg_cache[i] == max98088_reg[i]) continue; - snd_soc_write(codec, i, max98088->reg_cache[i]); + snd_soc_write(codec, i, reg_cache[i]); } codec->cache_sync = 0; @@ -1945,7 +1950,6 @@ static int max98088_probe(struct snd_soc_codec *codec) int ret = 0; codec->cache_sync = 1; - memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg)); ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); if (ret != 0) { @@ -2013,7 +2017,10 @@ err_access: static int max98088_remove(struct snd_soc_codec *codec) { + struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec); + max98088_set_bias_level(codec, SND_SOC_BIAS_OFF); + kfree(max98088->eq_texts); return 0; } @@ -2040,6 +2047,8 @@ static int max98088_i2c_probe(struct i2c_client *i2c, if (max98088 == NULL) return -ENOMEM; + max98088->devtype = id->driver_data; + i2c_set_clientdata(i2c, max98088); max98088->control_data = i2c; max98088->pdata = i2c->dev.platform_data; @@ -2059,7 +2068,8 @@ static int __devexit max98088_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id max98088_i2c_id[] = { - { "max98088", 0 }, + { "max98088", MAX98088 }, + { "max98089", MAX98089 }, { } }; MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 00d67cc8e206..061f9e5a497b 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -383,6 +383,7 @@ static struct snd_soc_codec_driver soc_codec_dev_stac9766 = { .reg_cache_size = sizeof(stac9766_reg), .reg_word_size = sizeof(u16), .reg_cache_step = 2, + .reg_cache_default = stac9766_reg, }; static __devinit int stac9766_probe(struct platform_device *pdev) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index fc687790188b..77b8f9ae29be 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1176,7 +1176,7 @@ EXPORT_SYMBOL_GPL(aic3x_set_gpio); int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio) { u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG; - u8 val, bit = gpio ? 2: 1; + u8 val = 0, bit = gpio ? 2 : 1; aic3x_read(codec, reg, &val); return (val >> bit) & 1; @@ -1204,7 +1204,7 @@ EXPORT_SYMBOL_GPL(aic3x_set_headset_detection); int aic3x_headset_detected(struct snd_soc_codec *codec) { - u8 val; + u8 val = 0; aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val); return (val >> 4) & 1; } @@ -1212,7 +1212,7 @@ EXPORT_SYMBOL_GPL(aic3x_headset_detected); int aic3x_button_pressed(struct snd_soc_codec *codec) { - u8 val; + u8 val = 0; aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val); return (val >> 5) & 1; } diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index ee4fb201de60..d2c243095673 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -78,8 +78,10 @@ static int tpa6130a2_i2c_write(int reg, u8 value) if (data->power_state) { val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value); - if (val < 0) + if (val < 0) { dev_err(&tpa6130a2_client->dev, "Write failed\n"); + return val; + } } /* Either powered on or off, we save the context */ diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index 7540a509a6f5..464f0cfa4c7a 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -597,6 +597,7 @@ static struct snd_soc_codec_driver soc_codec_dev_uda134x = { .resume = uda134x_soc_resume, .reg_cache_size = sizeof(uda134x_reg), .reg_word_size = sizeof(u8), + .reg_cache_default = uda134x_reg, .reg_cache_step = 1, .read = uda134x_read_reg_cache, .write = uda134x_write, diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index f4f1fba38eb9..7611add7f8c3 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -831,7 +831,7 @@ static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, } /* MCLK direction */ - if (dir == WM8350_MCLK_DIR_OUT) + if (dir == SND_SOC_CLOCK_OUT) wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_2, WM8350_MCLK_DIR); else @@ -1586,6 +1586,13 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, WM8350_OUT2_VU | WM8350_OUT2R_MUTE); + /* Make sure AIF tristating is disabled by default */ + wm8350_clear_bits(wm8350, WM8350_AI_FORMATING, WM8350_AIF_TRI); + + /* Make sure we've got a sane companding setup too */ + wm8350_clear_bits(wm8350, WM8350_ADC_DAC_COMP, + WM8350_DAC_COMP | WM8350_LOOPBACK); + /* Make sure jack detect is disabled to start off with */ wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, WM8350_JDL_ENA | WM8350_JDR_ENA); diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 712ef7c76f90..deca79ea2b4b 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -41,7 +41,6 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { /* codec private data */ struct wm8523_priv { enum snd_soc_control_type control_type; - u16 reg_cache[WM8523_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; unsigned int sysclk; unsigned int rate_constraint_list[WM8523_NUM_RATES]; @@ -146,7 +145,6 @@ static int wm8523_startup(struct snd_pcm_substream *substream, return -EINVAL; } - return 0; snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &wm8523->rate_constraint); @@ -315,6 +313,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int ret, i; switch (level) { @@ -345,7 +344,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, /* Sync back default/cached values */ for (i = WM8523_AIF_CTRL1; i < WM8523_MAX_REGISTER; i++) - snd_soc_write(codec, i, wm8523->reg_cache[i]); + snd_soc_write(codec, i, reg_cache[i]); msleep(100); @@ -415,6 +414,7 @@ static int wm8523_resume(struct snd_soc_codec *codec) static int wm8523_probe(struct snd_soc_codec *codec) { struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int ret, i; codec->hw_write = (hw_write_t)i2c_master_send; @@ -471,8 +471,8 @@ static int wm8523_probe(struct snd_soc_codec *codec) } /* Change some default settings - latch VU and enable ZC */ - wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; - wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; + reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; + reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index a2e0ed59b376..8725d4e75431 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -161,7 +161,7 @@ static const u16 wm8580_reg[] = { 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ - 0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/ + 0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/ 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ @@ -491,16 +491,16 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, paifa |= 0x8; break; case SNDRV_PCM_FORMAT_S20_3LE: - paifa |= 0x10; + paifa |= 0x0; paifb |= WM8580_AIF_LENGTH_20; break; case SNDRV_PCM_FORMAT_S24_LE: - paifa |= 0x10; + paifa |= 0x0; paifb |= WM8580_AIF_LENGTH_24; break; case SNDRV_PCM_FORMAT_S32_LE: - paifa |= 0x10; - paifb |= WM8580_AIF_LENGTH_24; + paifa |= 0x0; + paifb |= WM8580_AIF_LENGTH_32; break; default: return -EINVAL; diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 631385802eb4..e725c09a3e79 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -526,7 +526,7 @@ static int wm8731_probe(struct snd_soc_codec *codec) snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0); /* Disable bypass path by default */ - snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); + snd_soc_update_bits(codec, WM8731_APANA, 0x8, 0); snd_soc_add_controls(codec, wm8731_snd_controls, ARRAY_SIZE(wm8731_snd_controls)); diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 90e31e9aa6f7..aea60ef8aba7 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -41,7 +41,6 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { /* codec private data */ struct wm8741_priv { enum snd_soc_control_type control_type; - u16 reg_cache[WM8741_REGISTER_COUNT]; struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; unsigned int sysclk; struct snd_pcm_hw_constraint_list *sysclk_constraints; @@ -422,6 +421,7 @@ static int wm8741_resume(struct snd_soc_codec *codec) static int wm8741_probe(struct snd_soc_codec *codec) { struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int ret = 0; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); @@ -437,10 +437,10 @@ static int wm8741_probe(struct snd_soc_codec *codec) } /* Change some default settings - latch VU */ - wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; - wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; - wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; - wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; + reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; + reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; + reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; + reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; snd_soc_add_controls(codec, wm8741_snd_controls, ARRAY_SIZE(wm8741_snd_controls)); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 8f679a13f2bc..87caae59e939 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -65,22 +65,22 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec, * are using 2 wire for device control, so we cache them instead. */ static const u16 wm8753_reg[] = { - 0x0008, 0x0000, 0x000a, 0x000a, - 0x0033, 0x0000, 0x0007, 0x00ff, - 0x00ff, 0x000f, 0x000f, 0x007b, - 0x0000, 0x0032, 0x0000, 0x00c3, - 0x00c3, 0x00c0, 0x0000, 0x0000, + 0x0000, 0x0008, 0x0000, 0x000a, + 0x000a, 0x0033, 0x0000, 0x0007, + 0x00ff, 0x00ff, 0x000f, 0x000f, + 0x007b, 0x0000, 0x0032, 0x0000, + 0x00c3, 0x00c3, 0x00c0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0055, - 0x0005, 0x0050, 0x0055, 0x0050, - 0x0055, 0x0050, 0x0055, 0x0079, - 0x0079, 0x0079, 0x0079, 0x0079, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0097, 0x0097, 0x0000, 0x0004, - 0x0000, 0x0083, 0x0024, 0x01ba, - 0x0000, 0x0083, 0x0024, 0x01ba, - 0x0000, 0x0000, 0x0000 + 0x0055, 0x0005, 0x0050, 0x0055, + 0x0050, 0x0055, 0x0050, 0x0055, + 0x0079, 0x0079, 0x0079, 0x0079, + 0x0079, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0097, 0x0097, 0x0000, + 0x0004, 0x0000, 0x0083, 0x0024, + 0x01ba, 0x0000, 0x0083, 0x0024, + 0x01ba, 0x0000, 0x0000, 0x0000 }; /* codec private data */ @@ -88,57 +88,10 @@ struct wm8753_priv { enum snd_soc_control_type control_type; unsigned int sysclk; unsigned int pcmclk; - u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; int dai_func; }; -/* - * read wm8753 register cache - */ -static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) - return -1; - return cache[reg - 1]; -} - -/* - * write wm8753 register cache - */ -static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec, - unsigned int reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1)) - return; - cache[reg - 1] = value; -} - -/* - * write to the WM8753 register space - */ -static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D9 WM8753 register offset - * D8...D0 register data - */ - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - wm8753_write_reg_cache(codec, reg, value); - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - else - return -EIO; -} - -#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0) +#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0) /* * WM8753 Controls @@ -218,7 +171,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); + int mode = snd_soc_read(codec, WM8753_IOCTL); ucontrol->value.integer.value[0] = (mode & 0xc) >> 2; return 0; @@ -228,7 +181,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); + int mode = snd_soc_read(codec, WM8753_IOCTL); struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) @@ -738,17 +691,17 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (pll_id == WM8753_PLL1) { offset = 0; enable = 0x10; - reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef; + reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef; } else { offset = 4; enable = 0x8; - reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7; + reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7; } if (!freq_in || !freq_out) { /* disable PLL */ - wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); - wm8753_write(codec, WM8753_CLOCK, reg); + snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026); + snd_soc_write(codec, WM8753_CLOCK, reg); return 0; } else { u16 value = 0; @@ -759,20 +712,20 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, /* set up N and K PLL divisor ratios */ /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */ value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18); - wm8753_write(codec, WM8753_PLL1CTL2 + offset, value); + snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value); /* bits 8:0 = PLL_K[17:9] */ value = (pll_div.k & 0x03fe00) >> 9; - wm8753_write(codec, WM8753_PLL1CTL3 + offset, value); + snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value); /* bits 8:0 = PLL_K[8:0] */ value = pll_div.k & 0x0001ff; - wm8753_write(codec, WM8753_PLL1CTL4 + offset, value); + snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value); /* set PLL as input and enable */ - wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | + snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 | (pll_div.div2 << 3)); - wm8753_write(codec, WM8753_CLOCK, reg | enable); + snd_soc_write(codec, WM8753_CLOCK, reg | enable); } return 0; } @@ -879,7 +832,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec; + u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec; /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -901,7 +854,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - wm8753_write(codec, WM8753_PCM, voice); + snd_soc_write(codec, WM8753_PCM, voice); return 0; } @@ -922,8 +875,8 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; - u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; + u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3; + u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f; /* bit size */ switch (params_format(params)) { @@ -943,9 +896,9 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, /* sample rate */ if (params_rate(params) * 384 == wm8753->pcmclk) srate |= 0x80; - wm8753_write(codec, WM8753_SRATE1, srate); + snd_soc_write(codec, WM8753_SRATE1, srate); - wm8753_write(codec, WM8753_PCM, voice); + snd_soc_write(codec, WM8753_PCM, voice); return 0; } @@ -958,8 +911,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; u16 voice, ioctl; - voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f; - ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d; + voice = snd_soc_read(codec, WM8753_PCM) & 0x011f; + ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x015d; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1013,8 +966,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - wm8753_write(codec, WM8753_PCM, voice); - wm8753_write(codec, WM8753_IOCTL, ioctl); + snd_soc_write(codec, WM8753_PCM, voice); + snd_soc_write(codec, WM8753_IOCTL, ioctl); return 0; } @@ -1026,16 +979,16 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8753_PCMDIV: - reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f; - wm8753_write(codec, WM8753_CLOCK, reg | div); + reg = snd_soc_read(codec, WM8753_CLOCK) & 0x003f; + snd_soc_write(codec, WM8753_CLOCK, reg | div); break; case WM8753_BCLKDIV: - reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7; - wm8753_write(codec, WM8753_SRATE2, reg | div); + reg = snd_soc_read(codec, WM8753_SRATE2) & 0x01c7; + snd_soc_write(codec, WM8753_SRATE2, reg | div); break; case WM8753_VXCLKDIV: - reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f; - wm8753_write(codec, WM8753_SRATE2, reg | div); + reg = snd_soc_read(codec, WM8753_SRATE2) & 0x003f; + snd_soc_write(codec, WM8753_SRATE2, reg | div); break; default: return -EINVAL; @@ -1050,7 +1003,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0; + u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0; /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -1072,7 +1025,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - wm8753_write(codec, WM8753_HIFI, hifi); + snd_soc_write(codec, WM8753_HIFI, hifi); return 0; } @@ -1085,8 +1038,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; u16 ioctl, hifi; - hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f; - ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae; + hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f; + ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1140,8 +1093,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - wm8753_write(codec, WM8753_HIFI, hifi); - wm8753_write(codec, WM8753_IOCTL, ioctl); + snd_soc_write(codec, WM8753_HIFI, hifi); + snd_soc_write(codec, WM8753_IOCTL, ioctl); return 0; } @@ -1162,8 +1115,8 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; - u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; + u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0; + u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3; int coeff; /* is digital filter coefficient valid ? */ @@ -1172,7 +1125,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, printk(KERN_ERR "wm8753 invalid MCLK or rate\n"); return coeff; } - wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | + snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); /* bit size */ @@ -1190,7 +1143,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, break; } - wm8753_write(codec, WM8753_HIFI, hifi); + snd_soc_write(codec, WM8753_HIFI, hifi); return 0; } @@ -1201,8 +1154,8 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai, u16 clock; /* set clk source as pcmclk */ - clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; - wm8753_write(codec, WM8753_CLOCK, clock); + clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; + snd_soc_write(codec, WM8753_CLOCK, clock); if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) return -EINVAL; @@ -1224,8 +1177,8 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai, u16 clock; /* set clk source as pcmclk */ - clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; - wm8753_write(codec, WM8753_CLOCK, clock); + clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; + snd_soc_write(codec, WM8753_CLOCK, clock); if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) return -EINVAL; @@ -1239,8 +1192,8 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai, u16 clock; /* set clk source as mclk */ - clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb; - wm8753_write(codec, WM8753_CLOCK, clock | 0x4); + clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; + snd_soc_write(codec, WM8753_CLOCK, clock | 0x4); if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) return -EINVAL; @@ -1252,19 +1205,19 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai, static int wm8753_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; + u16 mute_reg = snd_soc_read(codec, WM8753_DAC) & 0xfff7; struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); /* the digital mute covers the HiFi and Voice DAC's on the WM8753. * make sure we check if they are not both active when we mute */ if (mute && wm8753->dai_func == 1) { if (!codec->active) - wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); + snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); } else { if (mute) - wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); + snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8); else - wm8753_write(codec, WM8753_DAC, mute_reg); + snd_soc_write(codec, WM8753_DAC, mute_reg); } return 0; @@ -1273,23 +1226,23 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) static int wm8753_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e; + u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: /* set vmid to 50k and unmute dac */ - wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); + snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); break; case SND_SOC_BIAS_PREPARE: /* set vmid to 5k for quick power up */ - wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); + snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); break; case SND_SOC_BIAS_STANDBY: /* mute dac and set vmid to 500k, enable VREF */ - wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141); + snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141); break; case SND_SOC_BIAS_OFF: - wm8753_write(codec, WM8753_PWR1, 0x0001); + snd_soc_write(codec, WM8753_PWR1, 0x0001); break; } codec->bias_level = level; @@ -1477,7 +1430,7 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec, else dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1]; } - wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func); + snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func); } static void wm8753_work(struct work_struct *work) @@ -1495,22 +1448,19 @@ static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8753_resume(struct snd_soc_codec *codec) { + u16 *reg_cache = codec->reg_cache; int i; - u8 data[2]; - u16 *cache = codec->reg_cache; /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) { - if (i + 1 == WM8753_RESET) + for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) { + if (i == WM8753_RESET) continue; /* No point in writing hardware default values back */ - if (cache[i] == wm8753_reg[i]) + if (reg_cache[i] == wm8753_reg[i]) continue; - data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); + snd_soc_write(codec, i, reg_cache[i]); } wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1548,7 +1498,7 @@ static int run_delayed_work(struct delayed_work *dwork) static int wm8753_probe(struct snd_soc_codec *codec) { struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); - int ret = 0, reg; + int ret; INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work); @@ -1573,26 +1523,16 @@ static int wm8753_probe(struct snd_soc_codec *codec) msecs_to_jiffies(caps_charge)); /* set the update bits */ - reg = wm8753_read_reg_cache(codec, WM8753_LDAC); - wm8753_write(codec, WM8753_LDAC, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_RDAC); - wm8753_write(codec, WM8753_RDAC, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_LADC); - wm8753_write(codec, WM8753_LADC, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_RADC); - wm8753_write(codec, WM8753_RADC, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V); - wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V); - wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V); - wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V); - wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_LINVOL); - wm8753_write(codec, WM8753_LINVOL, reg | 0x0100); - reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); - wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); + snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100); + snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100); snd_soc_add_controls(codec, wm8753_snd_controls, ARRAY_SIZE(wm8753_snd_controls)); diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 04182c464e35..0132a27140ae 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -34,7 +34,6 @@ /* codec private data */ struct wm8776_priv { enum snd_soc_control_type control_type; - u16 reg_cache[WM8776_CACHEREGNUM]; int sysclk[2]; }; diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 33be84e506ea..1ec12eff0620 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -50,8 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = { /* codec private data */ struct wm8904_priv { - u16 reg_cache[WM8904_MAX_REGISTER + 1]; - enum wm8904_type devtype; void *control_data; @@ -818,7 +816,8 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); - return wm8904->deemph; + ucontrol->value.enumerated.item[0] = wm8904->deemph; + return 0; } static int wm8904_put_deemph(struct snd_kcontrol *kcontrol, @@ -2093,7 +2092,7 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute) static void wm8904_sync_cache(struct snd_soc_codec *codec) { - struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int i; if (!codec->cache_sync) @@ -2104,14 +2103,14 @@ static void wm8904_sync_cache(struct snd_soc_codec *codec) /* Sync back cached values if they're different from the * hardware default. */ - for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) { + for (i = 1; i < codec->driver->reg_cache_size; i++) { if (!wm8904_access[i].writable) continue; - if (wm8904->reg_cache[i] == wm8904_reg[i]) + if (reg_cache[i] == wm8904_reg[i]) continue; - snd_soc_write(codec, i, wm8904->reg_cache[i]); + snd_soc_write(codec, i, reg_cache[i]); } codec->cache_sync = 0; @@ -2370,6 +2369,7 @@ static int wm8904_probe(struct snd_soc_codec *codec) { struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); struct wm8904_pdata *pdata = wm8904->pdata; + u16 *reg_cache = codec->reg_cache; int ret, i; codec->cache_sync = 1; @@ -2436,19 +2436,19 @@ static int wm8904_probe(struct snd_soc_codec *codec) } /* Change some default settings - latch VU and enable ZC */ - wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; - wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; - wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; - wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; - wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | + reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; + reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; + reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; + reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; + reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | WM8904_HPOUTLZC; - wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | + reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | WM8904_HPOUTRZC; - wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | + reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | WM8904_LINEOUTLZC; - wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | + reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | WM8904_LINEOUTRZC; - wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; + reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; /* Apply configuration from the platform data. */ if (wm8904->pdata) { @@ -2456,23 +2456,23 @@ static int wm8904_probe(struct snd_soc_codec *codec) if (!pdata->gpio_cfg[i]) continue; - wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i] + reg_cache[WM8904_GPIO_CONTROL_1 + i] = pdata->gpio_cfg[i] & 0xffff; } /* Zero is the default value for these anyway */ for (i = 0; i < WM8904_MIC_REGS; i++) - wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] + reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] = pdata->mic_cfg[i]; } /* Set Class W by default - this will be managed by the Class * G widget at runtime where bypass paths are available. */ - wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; + reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; /* Use normal bias source */ - wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; + reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -2498,6 +2498,8 @@ static int wm8904_remove(struct snd_soc_codec *codec) wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); + kfree(wm8904->retune_mobile_texts); + kfree(wm8904->drc_texts); return 0; } diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 2cb16f895c46..23086e2c976a 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -768,6 +768,7 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, wm8940); wm8940->control_data = i2c; + wm8940->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8940, &wm8940_dai, 1); diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index f89ad6c9a80b..2ac35b0be86a 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -42,8 +42,6 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { struct wm8955_priv { enum snd_soc_control_type control_type; - u16 reg_cache[WM8955_MAX_REGISTER + 1]; - unsigned int mclk_rate; int deemph; @@ -380,7 +378,8 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); - return wm8955->deemph; + ucontrol->value.enumerated.item[0] = wm8955->deemph; + return 0; } static int wm8955_put_deemph(struct snd_kcontrol *kcontrol, @@ -767,6 +766,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int ret, i; switch (level) { @@ -799,14 +799,14 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec, /* Sync back cached values if they're * different from the hardware default. */ - for (i = 0; i < ARRAY_SIZE(wm8955->reg_cache); i++) { + for (i = 0; i < codec->driver->reg_cache_size; i++) { if (i == WM8955_RESET) continue; - if (wm8955->reg_cache[i] == wm8955_reg[i]) + if (reg_cache[i] == wm8955_reg[i]) continue; - snd_soc_write(codec, i, wm8955->reg_cache[i]); + snd_soc_write(codec, i, reg_cache[i]); } /* Enable VREF and VMID */ @@ -901,6 +901,7 @@ static int wm8955_probe(struct snd_soc_codec *codec) { struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); + u16 *reg_cache = codec->reg_cache; int ret, i; ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); @@ -933,25 +934,25 @@ static int wm8955_probe(struct snd_soc_codec *codec) } /* Change some default settings - latch VU and enable ZC */ - wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; - wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; - wm8955->reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; - wm8955->reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; - wm8955->reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; - wm8955->reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; - wm8955->reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC; + reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; + reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; + reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; + reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; + reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; + reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; + reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC; /* Also enable adaptive bass boost by default */ - wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; + reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; /* Set platform data values */ if (pdata) { if (pdata->out2_speaker) - wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] + reg_cache[WM8955_ADDITIONAL_CONTROL_2] |= WM8955_ROUT2INV; if (pdata->monoin_diff) - wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] + reg_cache[WM8955_MONO_OUT_MIX_1] |= WM8955_DMEN; } @@ -1002,6 +1003,7 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8955); + wm8955->control_type = SND_SOC_I2C; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8955, &wm8955_dai, 1); diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 8d5efb333c33..ff6ff2f529d2 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -138,7 +138,8 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - return wm8960->deemph; + ucontrol->value.enumerated.item[0] = wm8960->deemph; + return 0; } static int wm8960_put_deemph(struct snd_kcontrol *kcontrol, @@ -1012,6 +1013,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm8960); + wm8960->control_type = SND_SOC_I2C; wm8960->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 4f326f604104..8340485c9851 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -711,7 +711,7 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream, if (fs <= 24000) reg |= WM8961_DACSLOPE; else - reg &= WM8961_DACSLOPE; + reg &= ~WM8961_DACSLOPE; snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); return 0; @@ -736,7 +736,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id, freq /= 2; } else { dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq); - reg &= WM8961_MCLKDIV; + reg &= ~WM8961_MCLKDIV; } snd_soc_write(codec, WM8961_CLOCKING1, reg); diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 894d0cd3aa9b..7c421cc837bd 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -52,8 +52,6 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = { struct wm8962_priv { struct snd_soc_codec *codec; - u16 reg_cache[WM8962_MAX_REGISTER + 1]; - int sysclk; int sysclk_rate; @@ -1991,8 +1989,7 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = wm8962->reg_cache; + u16 *reg_cache = codec->reg_cache; int ret; /* Apply the update (if any) */ @@ -2020,8 +2017,7 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = wm8962->reg_cache; + u16 *reg_cache = codec->reg_cache; int ret; /* Apply the update (if any) */ @@ -2329,8 +2325,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - u16 *reg_cache = wm8962->reg_cache; + u16 *reg_cache = codec->reg_cache; int reg; switch (w->shift) { @@ -2719,7 +2714,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec) static void wm8962_sync_cache(struct snd_soc_codec *codec) { - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int i; if (!codec->cache_sync) @@ -2732,13 +2727,13 @@ static void wm8962_sync_cache(struct snd_soc_codec *codec) /* Sync back cached values if they're different from the * hardware default. */ - for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { + for (i = 1; i < codec->driver->reg_cache_size; i++) { if (i == WM8962_SOFTWARE_RESET) continue; - if (wm8962->reg_cache[i] == wm8962_reg[i]) + if (reg_cache[i] == wm8962_reg[i]) continue; - snd_soc_write(codec, i, wm8962->reg_cache[i]); + snd_soc_write(codec, i, reg_cache[i]); } codec->cache_sync = 0; @@ -3339,7 +3334,7 @@ static irqreturn_t wm8962_irq(int irq, void *data) int mask; int active; - mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); + mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK); active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); active &= ~mask; @@ -3406,12 +3401,11 @@ EXPORT_SYMBOL_GPL(wm8962_mic_detect); #ifdef CONFIG_PM static int wm8962_resume(struct snd_soc_codec *codec) { - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); u16 *reg_cache = codec->reg_cache; int i; /* Restore the registers */ - for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) { + for (i = 1; i < codec->driver->reg_cache_size; i++) { switch (i) { case WM8962_SOFTWARE_RESET: continue; @@ -3500,8 +3494,11 @@ static ssize_t wm8962_beep_set(struct device *dev, { struct wm8962_priv *wm8962 = dev_get_drvdata(dev); long int time; + int ret; - strict_strtol(buf, 10, &time); + ret = strict_strtol(buf, 10, &time); + if (ret != 0) + return ret; input_event(wm8962->beep, EV_SND, SND_TONE, time); @@ -3702,6 +3699,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); struct i2c_client *i2c = container_of(codec->dev, struct i2c_client, dev); + u16 *reg_cache = codec->reg_cache; int i, trigger, irq_pol; wm8962->codec = codec; @@ -3801,7 +3799,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) /* Put the speakers into mono mode? */ if (pdata->spk_mono) - wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2] + reg_cache[WM8962_CLASS_D_CONTROL_2] |= WM8962_SPK_MONO; /* Micbias setup, detection enable and detection @@ -3816,16 +3814,16 @@ static int wm8962_probe(struct snd_soc_codec *codec) } /* Latch volume update bits */ - wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; - wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; - wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; - wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; - wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; - wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; - wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; - wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; - wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; - wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; + reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; + reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; + reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; + reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; + reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; + reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; + reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; + reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; + reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; + reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; wm8962_add_widgets(codec); diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 63f6dbf5d070..9f18db6e167c 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -718,6 +718,7 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, if (wm8971 == NULL) return -ENOMEM; + wm8971->control_type = SND_SOC_I2C; i2c_set_clientdata(i2c, wm8971); ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 0db59c3aa5d4..4d3e6f1ac584 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -3903,6 +3903,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) return -ENOMEM; snd_soc_codec_set_drvdata(codec, wm8994); + codec->reg_cache = &wm8994->reg_cache; + wm8994->pdata = dev_get_platdata(codec->dev->parent); wm8994->codec = codec; @@ -4059,6 +4061,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); + kfree(wm8994->retune_mobile_texts); + kfree(wm8994->drc_texts); kfree(wm8994); return 0; @@ -4071,6 +4075,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { .resume = wm8994_resume, .read = wm8994_read, .write = wm8994_write, + .readable_register = wm8994_readable, + .volatile_register = wm8994_volatile, .set_bias_level = wm8994_set_bias_level, }; diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index ecc7c37180c7..a486670966bd 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1335,6 +1335,7 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, return -ENOMEM; i2c_set_clientdata(i2c, wm9081); + wm9081->control_type = SND_SOC_I2C; wm9081->control_data = i2c; ret = snd_soc_register_codec(&i2c->dev, diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 99c046ba46bb..6e5f64f627cb 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -141,7 +141,6 @@ static const u16 wm9090_reg_defaults[] = { /* This struct is used to save the context */ struct wm9090_priv { struct mutex mutex; - u16 reg_cache[WM9090_MAX_REGISTER + 1]; struct wm9090_platform_data pdata; void *control_data; }; @@ -552,6 +551,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, static int wm9090_probe(struct snd_soc_codec *codec) { struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); + u16 *reg_cache = codec->reg_cache; int ret; codec->control_data = wm9090->control_data; @@ -576,22 +576,22 @@ static int wm9090_probe(struct snd_soc_codec *codec) /* Configure some defaults; they will be written out when we * bring the bias up. */ - wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU + reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU | WM9090_IN1A_ZC; - wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU + reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU | WM9090_IN1B_ZC; - wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU + reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU | WM9090_IN2A_ZC; - wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU + reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU | WM9090_IN2B_ZC; - wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= + reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; - wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= + reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; - wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= + reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; - wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; + reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 19ca782ac970..0e24092722c3 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -293,7 +293,7 @@ SOC_DOUBLE_R("Speaker Switch", SOC_DOUBLE_R("Speaker ZC Switch", WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, 7, 1, 0), -SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0, +SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0, spkboost_tlv), SOC_ENUM("Speaker Reference", speaker_ref), SOC_ENUM("Speaker Mode", speaker_mode), diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 2b07b17a6b2d..bc9e6b0b3f6f 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -157,12 +157,23 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd) } /* davinci-evm digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link evm_dai = { +static struct snd_soc_dai_link dm6446_evm_dai = { .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai_name = "davinci-mcasp.0", + .cpu_dai_name = "davinci-mcbsp", .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.0-001a", + .codec_name = "tlv320aic3x-codec.1-001b", + .platform_name = "davinci-pcm-audio", + .init = evm_aic3x_init, + .ops = &evm_ops, +}; + +static struct snd_soc_dai_link dm355_evm_dai = { + .name = "TLV320AIC3X", + .stream_name = "AIC3X", + .cpu_dai_name = "davinci-mcbsp.1", + .codec_dai_name = "tlv320aic3x-hifi", + .codec_name = "tlv320aic3x-codec.1-001b", .platform_name = "davinci-pcm-audio", .init = evm_aic3x_init, .ops = &evm_ops, @@ -172,10 +183,10 @@ static struct snd_soc_dai_link dm365_evm_dai = { #ifdef CONFIG_SND_DM365_AIC3X_CODEC .name = "TLV320AIC3X", .stream_name = "AIC3X", - .cpu_dai_name = "davinci-i2s", + .cpu_dai_name = "davinci-mcbsp", .codec_dai_name = "tlv320aic3x-hifi", .init = evm_aic3x_init, - .codec_name = "tlv320aic3x-codec.0-001a", + .codec_name = "tlv320aic3x-codec.1-0018", .ops = &evm_ops, #elif defined(CONFIG_SND_DM365_VOICE_CODEC) .name = "Voice Codec - CQ93VC", @@ -219,10 +230,17 @@ static struct snd_soc_dai_link da8xx_evm_dai = { .ops = &evm_ops, }; -/* davinci dm6446, dm355 evm audio machine driver */ -static struct snd_soc_card snd_soc_card_evm = { - .name = "DaVinci EVM", - .dai_link = &evm_dai, +/* davinci dm6446 evm audio machine driver */ +static struct snd_soc_card dm6446_snd_soc_card_evm = { + .name = "DaVinci DM6446 EVM", + .dai_link = &dm6446_evm_dai, + .num_links = 1, +}; + +/* davinci dm355 evm audio machine driver */ +static struct snd_soc_card dm355_snd_soc_card_evm = { + .name = "DaVinci DM355 EVM", + .dai_link = &dm355_evm_dai, .num_links = 1, }; @@ -261,10 +279,10 @@ static int __init evm_init(void) int ret; if (machine_is_davinci_evm()) { - evm_snd_dev_data = &snd_soc_card_evm; + evm_snd_dev_data = &dm6446_snd_soc_card_evm; index = 0; } else if (machine_is_davinci_dm355_evm()) { - evm_snd_dev_data = &snd_soc_card_evm; + evm_snd_dev_data = &dm355_snd_soc_card_evm; index = 1; } else if (machine_is_davinci_dm365_evm()) { evm_snd_dev_data = &dm365_snd_soc_card_evm; diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index d46b545d41f4..9e0e565e6ed9 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -426,9 +426,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, snd_pcm_format_t fmt; unsigned element_cnt = 1; - dai->capture_dma_data = dev->dma_params; - dai->playback_dma_data = dev->dma_params; - /* general line settings */ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { @@ -601,6 +598,15 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, return ret; } +static int davinci_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); + + snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); + return 0; +} + static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { @@ -612,6 +618,7 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 static struct snd_soc_dai_ops davinci_i2s_dai_ops = { + .startup = davinci_i2s_startup, .shutdown = davinci_i2s_shutdown, .prepare = davinci_i2s_prepare, .trigger = davinci_i2s_trigger, @@ -749,7 +756,7 @@ static struct platform_driver davinci_mcbsp_driver = { .probe = davinci_i2s_probe, .remove = davinci_i2s_remove, .driver = { - .name = "davinci-i2s", + .name = "davinci-mcbsp", .owner = THIS_MODULE, }, }; diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 86918ee12419..fb55d2c5d704 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -715,9 +715,6 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, int word_length; u8 fifo_level; - cpu_dai->capture_dma_data = dev->dma_params; - cpu_dai->playback_dma_data = dev->dma_params; - davinci_hw_common_param(dev, substream->stream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) fifo_level = dev->txnumevt; @@ -799,7 +796,17 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, return ret; } +static int davinci_mcasp_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai); + + snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); + return 0; +} + static struct snd_soc_dai_ops davinci_mcasp_dai_ops = { + .startup = davinci_mcasp_startup, .trigger = davinci_mcasp_trigger, .hw_params = davinci_mcasp_hw_params, .set_fmt = davinci_mcasp_set_dai_fmt, diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index 009b6521a1bf..6c6666a1f942 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c @@ -84,7 +84,7 @@ static struct snd_soc_ops sffsdr_ops = { static struct snd_soc_dai_link sffsdr_dai = { .name = "PCM3008", /* Codec name */ .stream_name = "PCM3008 HiFi", - .cpu_dai_name = "davinci-asp.0", + .cpu_dai_name = "davinci-mcbsp", .codec_dai_name = "pcm3008-hifi", .codec_name = "pcm3008-codec", .platform_name = "davinci-pcm-audio", diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index ea232f6a2c21..9d2afccc3a2d 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c @@ -97,9 +97,6 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream, &davinci_vcif_dev->dma_params[substream->stream]; u32 w; - dai->capture_dma_data = davinci_vcif_dev->dma_params; - dai->playback_dma_data = davinci_vcif_dev->dma_params; - /* Restart the codec before setup */ davinci_vcif_stop(substream); davinci_vcif_start(substream); @@ -174,9 +171,19 @@ static int davinci_vcif_trigger(struct snd_pcm_substream *substream, int cmd, return ret; } +static int davinci_vcif_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct davinci_vcif_dev *dev = snd_soc_dai_get_drvdata(dai); + + snd_soc_dai_set_dma_data(dai, substream, dev->dma_params); + return 0; +} + #define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000 static struct snd_soc_dai_ops davinci_vcif_dai_ops = { + .startup = davinci_vcif_startup, .trigger = davinci_vcif_trigger, .hw_params = davinci_vcif_hw_params, }; @@ -240,7 +247,10 @@ fail: static int davinci_vcif_remove(struct platform_device *pdev) { + struct davinci_vcif_dev *davinci_vcif_dev = dev_get_drvdata(&pdev->dev); + snd_soc_unregister_dai(&pdev->dev); + kfree(davinci_vcif_dev); return 0; } diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/ep93xx/simone.c index 4b0d19913728..286817946c56 100644 --- a/sound/soc/ep93xx/simone.c +++ b/sound/soc/ep93xx/simone.c @@ -54,24 +54,26 @@ static int __init simone_init(void) ret = platform_device_add(simone_snd_ac97_device); if (ret) - goto fail; + goto fail1; simone_snd_device = platform_device_alloc("soc-audio", -1); if (!simone_snd_device) { ret = -ENOMEM; - goto fail; + goto fail2; } platform_set_drvdata(simone_snd_device, &snd_soc_simone); ret = platform_device_add(simone_snd_device); - if (ret) { - platform_device_put(simone_snd_device); - goto fail; - } + if (ret) + goto fail3; - return ret; + return 0; -fail: +fail3: + platform_device_put(simone_snd_device); +fail2: + platform_device_del(simone_snd_ac97_device); +fail1: platform_device_put(simone_snd_ac97_device); return ret; } diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c index 53251e6b5bd5..108b5d8bd0e9 100644 --- a/sound/soc/fsl/efika-audio-fabric.c +++ b/sound/soc/fsl/efika-audio-fabric.c @@ -76,6 +76,7 @@ static __init int efika_fabric_init(void) rc = platform_device_add(pdev); if (rc) { pr_err("efika_fabric_init: platform_device_add() failed\n"); + platform_device_put(pdev); return -ENODEV; } return 0; diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index dce6b551cd78..f92dca07cd35 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -9,7 +9,6 @@ #include <linux/module.h> #include <linux/of_device.h> #include <linux/slab.h> -#include <linux/of_device.h> #include <linux/of_platform.h> #include <sound/soc.h> diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 74ffed41340f..9018fa5bf0db 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -160,7 +160,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op, rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); if (rc != 0) { pr_err("Failed to register DAI\n"); - return 0; + return rc; } psc_dma = dev_get_drvdata(&op->dev); diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 0d7dcf1e4863..7d7847a1e66b 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -498,6 +498,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) dev_err(&pdev->dev, "platform device add failed\n"); goto error; } + dev_set_drvdata(&pdev->dev, sound_device); of_node_put(codec_np); diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 63b9eaa1ebc2..026b756961e0 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -498,6 +498,7 @@ static int p1022_ds_probe(struct platform_device *pdev) dev_err(&pdev->dev, "platform device add failed\n"); goto error; } + dev_set_drvdata(&pdev->dev, sound_device); of_node_put(codec_np); diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index 25f27ec1dd6e..ba4d85e317ed 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c @@ -76,6 +76,7 @@ static __init int pcm030_fabric_init(void) rc = platform_device_add(pdev); if (rc) { pr_err("pcm030_fabric_init: platform_device_add() failed\n"); + platform_device_put(pdev); return -ENODEV; } return 0; diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c index b59675257ce5..dd4fffdbd177 100644 --- a/sound/soc/imx/eukrea-tlv320.c +++ b/sound/soc/imx/eukrea-tlv320.c @@ -34,8 +34,8 @@ static int eukrea_tlv320_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int ret; ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | @@ -79,10 +79,10 @@ static struct snd_soc_ops eukrea_tlv320_snd_ops = { static struct snd_soc_dai_link eukrea_tlv320_dai = { .name = "tlv320aic23", .stream_name = "TLV320AIC23", - .codec_dai = "tlv320aic23-hifi", + .codec_dai_name = "tlv320aic23-hifi", .platform_name = "imx-pcm-audio.0", .codec_name = "tlv320aic23-codec.0-001a", - .cpu_dai = "imx-ssi.0", + .cpu_dai_name = "imx-ssi.0", .ops = &eukrea_tlv320_snd_ops, }; diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index fd493ee1428e..671ef8dd524c 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/dmaengine.h> #include <sound/core.h> #include <sound/initval.h> @@ -27,165 +28,146 @@ #include <sound/pcm_params.h> #include <sound/soc.h> -#include <mach/dma-mx1-mx2.h> +#include <mach/dma.h> #include "imx-ssi.h" struct imx_pcm_runtime_data { - int sg_count; - struct scatterlist *sg_list; - int period; + int period_bytes; int periods; - unsigned long dma_addr; int dma; - struct snd_pcm_substream *substream; unsigned long offset; unsigned long size; - unsigned long period_cnt; void *buf; int period_time; + struct dma_async_tx_descriptor *desc; + struct dma_chan *dma_chan; + struct imx_dma_data dma_data; }; -/* Called by the DMA framework when a period has elapsed */ -static void imx_ssi_dma_progression(int channel, void *data, - struct scatterlist *sg) +static void audio_dma_irq(void *data) { - struct snd_pcm_substream *substream = data; + struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; struct snd_pcm_runtime *runtime = substream->runtime; struct imx_pcm_runtime_data *iprtd = runtime->private_data; - if (!sg) - return; - - runtime = iprtd->substream->runtime; + iprtd->offset += iprtd->period_bytes; + iprtd->offset %= iprtd->period_bytes * iprtd->periods; - iprtd->offset = sg->dma_address - runtime->dma_addr; - - snd_pcm_period_elapsed(iprtd->substream); + snd_pcm_period_elapsed(substream); } -static void imx_ssi_dma_callback(int channel, void *data) +static bool filter(struct dma_chan *chan, void *param) { - pr_err("%s shouldn't be called\n", __func__); -} + struct imx_pcm_runtime_data *iprtd = param; -static void snd_imx_dma_err_callback(int channel, void *data, int err) -{ - struct snd_pcm_substream *substream = data; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct imx_pcm_dma_params *dma_params = - snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct imx_pcm_runtime_data *iprtd = runtime->private_data; - int ret; + if (!imx_dma_is_general_purpose(chan)) + return false; - pr_err("DMA timeout on channel %d -%s%s%s%s\n", - channel, - err & IMX_DMA_ERR_BURST ? " burst" : "", - err & IMX_DMA_ERR_REQUEST ? " request" : "", - err & IMX_DMA_ERR_TRANSFER ? " transfer" : "", - err & IMX_DMA_ERR_BUFFER ? " buffer" : ""); + chan->private = &iprtd->dma_data; - imx_dma_disable(iprtd->dma); - ret = imx_dma_setup_sg(iprtd->dma, iprtd->sg_list, iprtd->sg_count, - IMX_DMA_LENGTH_LOOP, dma_params->dma_addr, - substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - DMA_MODE_WRITE : DMA_MODE_READ); - if (!ret) - imx_dma_enable(iprtd->dma); + return true; } -static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream) +static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct imx_pcm_dma_params *dma_params; struct snd_pcm_runtime *runtime = substream->runtime; struct imx_pcm_runtime_data *iprtd = runtime->private_data; + struct dma_slave_config slave_config; + dma_cap_mask_t mask; + enum dma_slave_buswidth buswidth; int ret; dma_params = snd_soc_dai_get_dma_data(rtd->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"); - return -ENODEV; - } + iprtd->dma_data.peripheral_type = IMX_DMATYPE_SSI; + iprtd->dma_data.priority = DMA_PRIO_HIGH; + iprtd->dma_data.dma_request = dma_params->dma; - ret = imx_dma_setup_handlers(iprtd->dma, - imx_ssi_dma_callback, - snd_imx_dma_err_callback, substream); - if (ret) - goto out; + /* Try to grab a DMA channel */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + iprtd->dma_chan = dma_request_channel(mask, filter, iprtd); + if (!iprtd->dma_chan) + return -EINVAL; - ret = imx_dma_setup_progression_handler(iprtd->dma, - imx_ssi_dma_progression); - if (ret) { - pr_err("Failed to setup the DMA handler\n"); - goto out; + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + case SNDRV_PCM_FORMAT_S24_LE: + buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; + break; + default: + return 0; } - ret = imx_dma_config_channel(iprtd->dma, - IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO, - IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, - dma_params->dma, 1); - if (ret < 0) { - pr_err("Cannot configure DMA channel: %d\n", ret); - goto out; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + slave_config.direction = DMA_TO_DEVICE; + slave_config.dst_addr = dma_params->dma_addr; + slave_config.dst_addr_width = buswidth; + slave_config.dst_maxburst = dma_params->burstsize; + } else { + slave_config.direction = DMA_FROM_DEVICE; + slave_config.src_addr = dma_params->dma_addr; + slave_config.src_addr_width = buswidth; + slave_config.src_maxburst = dma_params->burstsize; } - imx_dma_config_burstlen(iprtd->dma, dma_params->burstsize * 2); + ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config); + if (ret) + return ret; return 0; -out: - imx_dma_free(iprtd->dma); - return ret; } static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { + struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; struct imx_pcm_runtime_data *iprtd = runtime->private_data; - int i; unsigned long dma_addr; + struct dma_chan *chan; + struct imx_pcm_dma_params *dma_params; + int ret; - imx_ssi_dma_alloc(substream); + dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + ret = imx_ssi_dma_alloc(substream, params); + if (ret) + return ret; + chan = iprtd->dma_chan; iprtd->size = params_buffer_bytes(params); iprtd->periods = params_periods(params); - iprtd->period = params_period_bytes(params); + iprtd->period_bytes = params_period_bytes(params); iprtd->offset = 0; iprtd->period_time = HZ / (params_rate(params) / params_period_size(params)); snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - if (iprtd->sg_count != iprtd->periods) { - kfree(iprtd->sg_list); - - iprtd->sg_list = kcalloc(iprtd->periods + 1, - sizeof(struct scatterlist), GFP_KERNEL); - if (!iprtd->sg_list) - return -ENOMEM; - iprtd->sg_count = iprtd->periods + 1; - } - - sg_init_table(iprtd->sg_list, iprtd->sg_count); dma_addr = runtime->dma_addr; - for (i = 0; i < iprtd->periods; i++) { - iprtd->sg_list[i].page_link = 0; - iprtd->sg_list[i].offset = 0; - iprtd->sg_list[i].dma_address = dma_addr; - iprtd->sg_list[i].length = iprtd->period; - dma_addr += iprtd->period; + iprtd->buf = (unsigned int *)substream->dma_buffer.area; + + iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr, + iprtd->period_bytes * iprtd->periods, + iprtd->period_bytes, + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + DMA_TO_DEVICE : DMA_FROM_DEVICE); + if (!iprtd->desc) { + dev_err(&chan->dev->device, "cannot prepare slave dma\n"); + return -EINVAL; } - /* close the loop */ - iprtd->sg_list[iprtd->sg_count - 1].offset = 0; - iprtd->sg_list[iprtd->sg_count - 1].length = 0; - iprtd->sg_list[iprtd->sg_count - 1].page_link = - ((unsigned long) iprtd->sg_list | 0x01) & ~0x02; + iprtd->desc->callback = audio_dma_irq; + iprtd->desc->callback_param = substream; + return 0; } @@ -194,41 +176,21 @@ static int snd_imx_pcm_hw_free(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct imx_pcm_runtime_data *iprtd = runtime->private_data; - if (iprtd->dma >= 0) { - imx_dma_free(iprtd->dma); - iprtd->dma = -EINVAL; + if (iprtd->dma_chan) { + dma_release_channel(iprtd->dma_chan); + iprtd->dma_chan = NULL; } - kfree(iprtd->sg_list); - iprtd->sg_list = NULL; - return 0; } 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; - struct imx_pcm_runtime_data *iprtd = runtime->private_data; - int err; dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - iprtd->substream = substream; - iprtd->buf = (unsigned int *)substream->dma_buffer.area; - iprtd->period_cnt = 0; - - pr_debug("%s: buf: %p period: %d periods: %d\n", - __func__, iprtd->buf, iprtd->period, iprtd->periods); - - err = imx_dma_setup_sg(iprtd->dma, iprtd->sg_list, iprtd->sg_count, - IMX_DMA_LENGTH_LOOP, dma_params->dma_addr, - substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - DMA_MODE_WRITE : DMA_MODE_READ); - if (err) - return err; - return 0; } @@ -241,14 +203,14 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - imx_dma_enable(iprtd->dma); + dmaengine_submit(iprtd->desc); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - imx_dma_disable(iprtd->dma); + dmaengine_terminate_all(iprtd->dma_chan); break; default: @@ -263,6 +225,9 @@ static snd_pcm_uframes_t snd_imx_pcm_pointer(struct snd_pcm_substream *substream struct snd_pcm_runtime *runtime = substream->runtime; struct imx_pcm_runtime_data *iprtd = runtime->private_data; + pr_debug("%s: %ld %ld\n", __func__, iprtd->offset, + bytes_to_frames(substream->runtime, iprtd->offset)); + return bytes_to_frames(substream->runtime, iprtd->offset); } @@ -279,7 +244,7 @@ static struct snd_pcm_hardware snd_imx_hardware = { .channels_max = 2, .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, .period_bytes_min = 128, - .period_bytes_max = 16 * 1024, + .period_bytes_max = 65535, /* Limited by SDMA engine */ .periods_min = 2, .periods_max = 255, .fifo_size = 0, @@ -304,11 +269,23 @@ static int snd_imx_open(struct snd_pcm_substream *substream) } snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); + + return 0; +} + +static int snd_imx_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct imx_pcm_runtime_data *iprtd = runtime->private_data; + + kfree(iprtd); + return 0; } static struct snd_pcm_ops imx_pcm_ops = { .open = snd_imx_open, + .close = snd_imx_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_imx_pcm_hw_params, .hw_free = snd_imx_pcm_hw_free, @@ -340,7 +317,6 @@ static struct platform_driver imx_pcm_driver = { .name = "imx-pcm-audio", .owner = THIS_MODULE, }, - .probe = imx_soc_platform_probe, .remove = __devexit_p(imx_soc_platform_remove), }; @@ -356,4 +332,3 @@ static void __exit snd_imx_pcm_exit(void) platform_driver_unregister(&imx_pcm_driver); } module_exit(snd_imx_pcm_exit); - diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index d4bd345b0a8d..390b6ffc2658 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -439,7 +439,22 @@ void imx_pcm_free(struct snd_pcm *pcm) } EXPORT_SYMBOL_GPL(imx_pcm_free); +static int imx_ssi_dai_probe(struct snd_soc_dai *dai) +{ + struct imx_ssi *ssi = dev_get_drvdata(dai->dev); + uint32_t val; + + snd_soc_dai_set_drvdata(dai, ssi); + + val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | + SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); + writel(val, ssi->base + SSI_SFCSR); + + return 0; +} + static struct snd_soc_dai_driver imx_ssi_dai = { + .probe = imx_ssi_dai_probe, .playback = { .channels_min = 2, .channels_max = 2, @@ -455,20 +470,6 @@ static struct snd_soc_dai_driver imx_ssi_dai = { .ops = &imx_ssi_pcm_dai_ops, }; -static int imx_ssi_dai_probe(struct snd_soc_dai *dai) -{ - struct imx_ssi *ssi = dev_get_drvdata(dai->dev); - uint32_t val; - - snd_soc_dai_set_drvdata(dai, ssi); - - val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | - SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize); - writel(val, ssi->base + SSI_SFCSR); - - return 0; -} - static struct snd_soc_dai_driver imx_ac97_dai = { .probe = imx_ssi_dai_probe, .ac97_control = 1, @@ -677,9 +678,25 @@ static int imx_ssi_probe(struct platform_device *pdev) goto failed_register; } - ssi->soc_platform_pdev = platform_device_alloc("imx-fiq-pcm-audio", pdev->id); - if (!ssi->soc_platform_pdev) + ssi->soc_platform_pdev_fiq = platform_device_alloc("imx-fiq-pcm-audio", pdev->id); + if (!ssi->soc_platform_pdev_fiq) { + ret = -ENOMEM; + goto failed_pdev_fiq_alloc; + } + + platform_set_drvdata(ssi->soc_platform_pdev_fiq, ssi); + ret = platform_device_add(ssi->soc_platform_pdev_fiq); + if (ret) { + dev_err(&pdev->dev, "failed to add platform device\n"); + goto failed_pdev_fiq_add; + } + + ssi->soc_platform_pdev = platform_device_alloc("imx-pcm-audio", pdev->id); + if (!ssi->soc_platform_pdev) { + ret = -ENOMEM; goto failed_pdev_alloc; + } + platform_set_drvdata(ssi->soc_platform_pdev, ssi); ret = platform_device_add(ssi->soc_platform_pdev); if (ret) { @@ -692,6 +709,10 @@ static int imx_ssi_probe(struct platform_device *pdev) failed_pdev_add: platform_device_put(ssi->soc_platform_pdev); failed_pdev_alloc: + platform_device_del(ssi->soc_platform_pdev_fiq); +failed_pdev_fiq_add: + platform_device_put(ssi->soc_platform_pdev_fiq); +failed_pdev_fiq_alloc: snd_soc_unregister_dai(&pdev->dev); failed_register: failed_ac97: @@ -712,8 +733,8 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev) struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct imx_ssi *ssi = platform_get_drvdata(pdev); - platform_device_del(ssi->soc_platform_pdev); - platform_device_put(ssi->soc_platform_pdev); + platform_device_unregister(ssi->soc_platform_pdev); + platform_device_unregister(ssi->soc_platform_pdev_fiq); snd_soc_unregister_dai(&pdev->dev); diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h index 53b780d9b2b0..a4406a134892 100644 --- a/sound/soc/imx/imx-ssi.h +++ b/sound/soc/imx/imx-ssi.h @@ -185,6 +185,9 @@ #define DRV_NAME "imx-ssi" +#include <linux/dmaengine.h> +#include <mach/dma.h> + struct imx_pcm_dma_params { int dma; unsigned long dma_addr; @@ -212,6 +215,7 @@ struct imx_ssi { int enabled; struct platform_device *soc_platform_pdev; + struct platform_device *soc_platform_pdev_fiq; }; struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c index 6a65dd705519..9eabc28667e6 100644 --- a/sound/soc/imx/phycore-ac97.c +++ b/sound/soc/imx/phycore-ac97.c @@ -20,9 +20,6 @@ #include <sound/soc-dapm.h> #include <asm/mach-types.h> -#include "../codecs/wm9712.h" -#include "imx-ssi.h" - static struct snd_soc_card imx_phycore; static struct snd_soc_ops imx_phycore_hifi_ops = { @@ -41,11 +38,12 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = { }; static struct snd_soc_card imx_phycore = { - .name = "PhyCORE-audio", + .name = "PhyCORE-ac97-audio", .dai_link = imx_phycore_dai_ac97, .num_links = ARRAY_SIZE(imx_phycore_dai_ac97), }; +static struct platform_device *imx_phycore_snd_ac97_device; static struct platform_device *imx_phycore_snd_device; static int __init imx_phycore_init(void) @@ -56,29 +54,42 @@ static int __init imx_phycore_init(void) /* return happy. We might run on a totally different machine */ return 0; - imx_phycore_snd_device = platform_device_alloc("soc-audio", -1); - if (!imx_phycore_snd_device) + imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1); + if (!imx_phycore_snd_ac97_device) return -ENOMEM; - platform_set_drvdata(imx_phycore_snd_device, &imx_phycore); - ret = platform_device_add(imx_phycore_snd_device); + platform_set_drvdata(imx_phycore_snd_ac97_device, &imx_phycore); + ret = platform_device_add(imx_phycore_snd_ac97_device); + if (ret) + goto fail1; imx_phycore_snd_device = platform_device_alloc("wm9712-codec", -1); - if (!imx_phycore_snd_device) - return -ENOMEM; + if (!imx_phycore_snd_device) { + ret = -ENOMEM; + goto fail2; + } ret = platform_device_add(imx_phycore_snd_device); if (ret) { printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - platform_device_put(imx_phycore_snd_device); + goto fail3; } + return 0; + +fail3: + platform_device_put(imx_phycore_snd_device); +fail2: + platform_device_del(imx_phycore_snd_ac97_device); +fail1: + platform_device_put(imx_phycore_snd_ac97_device); return ret; } static void __exit imx_phycore_exit(void) { platform_device_unregister(imx_phycore_snd_device); + platform_device_unregister(imx_phycore_snd_ac97_device); } late_initcall(imx_phycore_init); diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index 293dc748797c..dac6732da969 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c @@ -49,7 +49,7 @@ static unsigned short nuc900_ac97_read(struct snd_ac97 *ac97, mutex_lock(&ac97_mutex); val = nuc900_checkready(); - if (!!val) { + if (val) { dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); goto out; } @@ -102,7 +102,7 @@ static void nuc900_ac97_write(struct snd_ac97 *ac97, unsigned short reg, mutex_lock(&ac97_mutex); tmp = nuc900_checkready(); - if (!!tmp) + if (tmp) dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); /* clear the R_WB bit and write register index */ @@ -149,7 +149,7 @@ static void nuc900_ac97_warm_reset(struct snd_ac97 *ac97) udelay(100); val = nuc900_checkready(); - if (!!val) + if (val) dev_err(nuc900_audio->dev, "AC97 codec is not ready\n"); mutex_unlock(&ac97_mutex); @@ -263,8 +263,7 @@ static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, return ret; } -static int nuc900_ac97_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int nuc900_ac97_probe(struct snd_soc_dai *dai) { struct nuc900_audio *nuc900_audio = nuc900_ac97_data; unsigned long val; @@ -284,12 +283,12 @@ static int nuc900_ac97_probe(struct platform_device *pdev, return 0; } -static void nuc900_ac97_remove(struct platform_device *pdev, - struct snd_soc_dai *dai) +static int nuc900_ac97_remove(struct snd_soc_dai *dai) { struct nuc900_audio *nuc900_audio = nuc900_ac97_data; clk_disable(nuc900_audio->clk); + return 0; } static struct snd_soc_dai_ops nuc900_ac97_dai_ops = { @@ -313,7 +312,7 @@ static struct snd_soc_dai_driver nuc900_ac97_dai = { .channels_max = 2, }, .ops = &nuc900_ac97_dai_ops, -} +}; static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev) { @@ -384,7 +383,6 @@ out0: static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev) { - snd_soc_unregister_dai(&pdev->dev); clk_put(nuc900_ac97_data->clk); @@ -392,6 +390,7 @@ static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev) release_mem_region(nuc900_ac97_data->res->start, resource_size(nuc900_ac97_data->res)); + kfree(nuc900_ac97_data); nuc900_ac97_data = NULL; return 0; diff --git a/sound/soc/nuc900/nuc900-audio.h b/sound/soc/nuc900/nuc900-audio.h index aeed8ead2b2b..59f7e8ed1a68 100644 --- a/sound/soc/nuc900/nuc900-audio.h +++ b/sound/soc/nuc900/nuc900-audio.h @@ -110,4 +110,6 @@ struct nuc900_audio { }; +extern struct nuc900_audio *nuc900_ac97_data; + #endif /*end _NUC900_AUDIO_H */ diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c index 195d1ac94771..8263f56dc665 100644 --- a/sound/soc/nuc900/nuc900-pcm.c +++ b/sound/soc/nuc900/nuc900-pcm.c @@ -50,12 +50,12 @@ static int nuc900_dma_hw_params(struct snd_pcm_substream *substream, unsigned long flags; int ret = 0; - spin_lock_irqsave(&nuc900_audio->lock, flags); - ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); if (ret < 0) return ret; + spin_lock_irqsave(&nuc900_audio->lock, flags); + nuc900_audio->substream = substream; nuc900_audio->dma_addr[substream->stream] = runtime->dma_addr; nuc900_audio->buffersize[substream->stream] = @@ -169,6 +169,7 @@ static int nuc900_dma_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct nuc900_audio *nuc900_audio = runtime->private_data; unsigned long flags, val; + int ret = 0; spin_lock_irqsave(&nuc900_audio->lock, flags); @@ -197,10 +198,10 @@ static int nuc900_dma_prepare(struct snd_pcm_substream *substream) AUDIO_WRITE(nuc900_audio->mmio + ACTL_RESET, val); break; default: - return -EINVAL; + ret = -EINVAL; } spin_unlock_irqrestore(&nuc900_audio->lock, flags); - return 0; + return ret; } static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd) @@ -332,7 +333,7 @@ static struct snd_soc_platform_driver nuc900_soc_platform = { .ops = &nuc900_dma_ops, .pcm_new = nuc900_dma_new, .pcm_free = nuc900_dma_free_dma_buffers, -} +}; static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev) { diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index d542ea2ff6be..a088db6d5091 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -12,8 +12,8 @@ config SND_OMAP_SOC_MCPDM config SND_OMAP_SOC_N810 tristate "SoC Audio support for Nokia N810" depends on SND_OMAP_SOC && MACH_NOKIA_N810 && I2C + depends on OMAP_MUX select SND_OMAP_SOC_MCBSP - select OMAP_MUX select SND_SOC_TLV320AIC3X help Say Y if you want to add support for SoC audio on Nokia N810. diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index d211c9fa5a91..7e84f24b9a88 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -644,15 +644,23 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, case OMAP_MCBSP_CLKR_SRC_CLKR: + if (cpu_class_is_omap1()) + break; omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR); break; case OMAP_MCBSP_CLKR_SRC_CLKX: + if (cpu_class_is_omap1()) + break; omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX); break; case OMAP_MCBSP_FSR_SRC_FSR: + if (cpu_class_is_omap1()) + break; omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR); break; case OMAP_MCBSP_FSR_SRC_FSX: + if (cpu_class_is_omap1()) + break; omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX); break; default: diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index dbd9d96b5f92..4ee33ce2cb98 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c @@ -306,6 +306,7 @@ static int __init omap3pandora_soc_init(void) pr_err(PREFIX "Failed to get DAC regulator from %s: %ld\n", dev_name(&omap3pandora_snd_device->dev), PTR_ERR(omap3pandora_dac_reg)); + ret = PTR_ERR(omap3pandora_dac_reg); goto fail3; } diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index f0e662556428..65ae00e976ef 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c @@ -177,7 +177,8 @@ static int __init osk_soc_init(void) tlv320aic23_mclk = clk_get(dev, "mclk"); if (IS_ERR(tlv320aic23_mclk)) { printk(KERN_ERR "Could not get mclk clock\n"); - return -ENODEV; + err = PTR_ERR(tlv320aic23_mclk); + goto err2; } /* @@ -188,7 +189,7 @@ static int __init osk_soc_init(void) if (clk_set_rate(tlv320aic23_mclk, CODEC_CLOCK)) { printk(KERN_ERR "Cannot set MCLK for AIC23 CODEC\n"); err = -ECANCELED; - goto err1; + goto err3; } } @@ -196,9 +197,12 @@ static int __init osk_soc_init(void) (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK); return 0; -err1: + +err3: clk_put(tlv320aic23_mclk); +err2: platform_device_del(osk_snd_device); +err1: platform_device_put(osk_snd_device); return err; @@ -207,6 +211,7 @@ err1: static void __exit osk_soc_exit(void) { + clk_put(tlv320aic23_mclk); platform_device_unregister(osk_snd_device); } diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 37f191bbfdd9..580f48571303 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -1,6 +1,7 @@ config SND_PXA2XX_SOC tristate "SoC Audio for the Intel PXA2xx chip" depends on ARCH_PXA + select SND_ARM select SND_PXA2XX_LIB help Say Y or M if you want to add support for codecs attached to diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 97e9423615c9..f451acd4935b 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -100,8 +100,13 @@ static int corgi_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; + mutex_lock(&codec->mutex); + /* check the jack status at stream startup */ corgi_ext_control(codec); + + mutex_unlock(&codec->mutex); + return 0; } diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c index b8207ced4072..5ef0526924b9 100644 --- a/sound/soc/pxa/magician.c +++ b/sound/soc/pxa/magician.c @@ -72,9 +72,13 @@ static int magician_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; + mutex_lock(&codec->mutex); + /* check the jack status at stream startup */ magician_ext_control(codec); + mutex_unlock(&codec->mutex); + return 0; } diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index af84ee9c5e11..84edd0385a21 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -77,8 +77,13 @@ static int poodle_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; + mutex_lock(&codec->mutex); + /* check the jack status at stream startup */ poodle_ext_control(codec); + + mutex_unlock(&codec->mutex); + return 0; } diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index f470f360f4dd..0b30d7de24ec 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -108,8 +108,13 @@ static int spitz_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; + mutex_lock(&codec->mutex); + /* check the jack status at stream startup */ spitz_ext_control(codec); + + mutex_unlock(&codec->mutex); + return 0; } diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 73d0edd8ded9..7b983f935454 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c @@ -81,8 +81,13 @@ static int tosa_startup(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; + mutex_lock(&codec->mutex); + /* check the jack status at stream startup */ tosa_ext_control(codec); + + mutex_unlock(&codec->mutex); + return 0; } diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index 8a6b53ccd203..d85bf8a0abb2 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig @@ -2,6 +2,7 @@ config SND_S3C24XX_SOC tristate "SoC Audio for the Samsung S3CXXXX chips" depends on ARCH_S3C2410 || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 select S3C64XX_DMA if ARCH_S3C64XX + select S3C2410_DMA if ARCH_S3C2410 help Say Y or M if you want to add support for codecs attached to the S3C24XX AC97 or I2S interfaces. You will also need to diff --git a/sound/soc/s3c24xx/rx1950_uda1380.c b/sound/soc/s3c24xx/rx1950_uda1380.c index ffd5cf2fb0a9..468cc11fdf47 100644 --- a/sound/soc/s3c24xx/rx1950_uda1380.c +++ b/sound/soc/s3c24xx/rx1950_uda1380.c @@ -50,7 +50,6 @@ static unsigned int rates[] = { 16000, 44100, 48000, - 88200, }; static struct snd_pcm_hw_constraint_list hw_rates = { @@ -130,7 +129,6 @@ static const struct snd_soc_dapm_route audio_map[] = { }; static struct platform_device *s3c24xx_snd_device; -static struct clk *xtal; static int rx1950_startup(struct snd_pcm_substream *substream) { @@ -179,10 +177,8 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream, case 44100: case 88200: clk_source = S3C24XX_CLKSRC_MPLL; - fs_mode = S3C2410_IISMOD_256FS; - div = clk_get_rate(xtal) / (256 * rate); - if (clk_get_rate(xtal) % (256 * rate) > (128 * rate)) - div++; + fs_mode = S3C2410_IISMOD_384FS; + div = 1; break; default: printk(KERN_ERR "%s: rate %d is not supported\n", @@ -210,7 +206,7 @@ static int rx1950_hw_params(struct snd_pcm_substream *substream, /* set MCLK division for sample rate */ ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, - S3C2410_IISMOD_384FS); + fs_mode); if (ret < 0) return ret; @@ -295,17 +291,8 @@ static int __init rx1950_init(void) goto err_plat_add; } - xtal = clk_get(&s3c24xx_snd_device->dev, "xtal"); - - if (IS_ERR(xtal)) { - ret = PTR_ERR(xtal); - platform_device_unregister(s3c24xx_snd_device); - goto err_clk; - } - return 0; -err_clk: err_plat_add: err_plat_alloc: err_gpio_conf: @@ -320,7 +307,6 @@ static void __exit rx1950_exit(void) platform_device_unregister(s3c24xx_snd_device); snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios), hp_jack_gpios); - clk_put(xtal); gpio_free(S3C2410_GPA(1)); } diff --git a/sound/soc/s3c24xx/smdk_spdif.c b/sound/soc/s3c24xx/smdk_spdif.c index f31d22ad7c88..c8bd90488a87 100644 --- a/sound/soc/s3c24xx/smdk_spdif.c +++ b/sound/soc/s3c24xx/smdk_spdif.c @@ -38,7 +38,7 @@ static int set_audio_clock_heirachy(struct platform_device *pdev) } mout_epll = clk_get(NULL, "mout_epll"); - if (IS_ERR(fout_epll)) { + if (IS_ERR(mout_epll)) { printk(KERN_WARNING "%s: Cannot find mout_epll.\n", __func__); ret = -EINVAL; @@ -54,7 +54,7 @@ static int set_audio_clock_heirachy(struct platform_device *pdev) } sclk_spdif = clk_get(NULL, "sclk_spdif"); - if (IS_ERR(fout_epll)) { + if (IS_ERR(sclk_spdif)) { printk(KERN_WARNING "%s: Cannot find sclk_spdif.\n", __func__); ret = -EINVAL; diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c index 8778faa174a6..3052f64b2403 100644 --- a/sound/soc/s6000/s6000-i2s.c +++ b/sound/soc/s6000/s6000-i2s.c @@ -434,7 +434,7 @@ static struct snd_soc_dai_driver s6000_i2s_dai = { .rate_max = 1562500, }, .ops = &s6000_i2s_dai_ops, -} +}; static int __devinit s6000_i2s_probe(struct platform_device *pdev) { diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index 271fd222bf19..ab3ccaec72d2 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c @@ -473,7 +473,7 @@ static int s6000_pcm_new(struct snd_card *card, } res = request_irq(params->irq, s6000_pcm_irq, IRQF_SHARED, - s6000_soc_platform.name, pcm); + "s6000-audio", pcm); if (res) { printk(KERN_ERR "s6000-pcm couldn't get IRQ\n"); return res; diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c index 96c05e137538..c1244c5bc730 100644 --- a/sound/soc/s6000/s6105-ipcam.c +++ b/sound/soc/s6000/s6105-ipcam.c @@ -167,7 +167,7 @@ static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_sync(codec); - snd_ctl_add(codec->snd_card, snd_ctl_new1(&audio_out_mux, codec)); + snd_ctl_add(codec->card->snd_card, snd_ctl_new1(&audio_out_mux, codec)); return 0; } diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 507e709f2807..4c2404b1b862 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -132,6 +132,8 @@ struct fsi_priv { struct fsi_stream playback; struct fsi_stream capture; + long rate; + u32 mst_ctrl; }; @@ -854,10 +856,17 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, { struct fsi_priv *fsi = fsi_get_priv(substream); int is_play = fsi_is_play(substream); + struct fsi_master *master = fsi_get_master(fsi); + int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); fsi_irq_disable(fsi, is_play); fsi_clk_ctrl(fsi, 0); + set_rate = master->info->set_rate; + if (set_rate && fsi->rate) + set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); + fsi->rate = 0; + pm_runtime_put_sync(dai->dev); } @@ -891,20 +900,20 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, { struct fsi_priv *fsi = fsi_get_priv(substream); struct fsi_master *master = fsi_get_master(fsi); - int (*set_rate)(int is_porta, int rate) = master->info->set_rate; + int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); int fsi_ver = master->core->ver; - int is_play = fsi_is_play(substream); + long rate = params_rate(params); int ret; - /* if slave mode, set_rate is not needed */ - if (!fsi_is_master_mode(fsi, is_play)) + set_rate = master->info->set_rate; + if (!set_rate) return 0; - /* it is error if no set_rate */ - if (!set_rate) - return -EIO; + ret = set_rate(dai->dev, fsi_is_port_a(fsi), rate, 1); + if (ret < 0) /* error */ + return ret; - ret = set_rate(fsi_is_port_a(fsi), params_rate(params)); + fsi->rate = rate; if (ret > 0) { u32 data = 0; diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index 40bbdf1591dc..05192d97b377 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c @@ -387,7 +387,7 @@ static int __devinit sh4_soc_dai_probe(struct platform_device *pdev) static int __devexit sh4_soc_dai_remove(struct platform_device *pdev) { - snd_soc_unregister_dai(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai)); + snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai)); return 0; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 614a8b30d87b..85b7d548f167 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1619,12 +1619,14 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) #ifdef CONFIG_SND_SOC_AC97_BUS /* register any AC97 codecs */ for (i = 0; i < card->num_rtd; i++) { - ret = soc_register_ac97_dai_link(&card->rtd[i]); - if (ret < 0) { - printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name); - goto probe_dai_err; - } + ret = soc_register_ac97_dai_link(&card->rtd[i]); + if (ret < 0) { + printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name); + while (--i >= 0) + soc_unregister_ac97_dai_link(&card->rtd[i]); + goto probe_dai_err; } + } #endif card->instantiated = 1; @@ -3043,8 +3045,10 @@ int snd_soc_register_dais(struct device *dev, for (i = 0; i < count; i++) { dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL); - if (dai == NULL) - return -ENOMEM; + if (dai == NULL) { + ret = -ENOMEM; + goto err; + } /* create DAI component name */ dai->name = fmt_multiple_name(dev, &dai_drv[i]); @@ -3070,7 +3074,9 @@ int snd_soc_register_dais(struct device *dev, pr_debug("Registered DAI '%s'\n", dai->name); } + mutex_lock(&client_mutex); snd_soc_instantiate_cards(); + mutex_unlock(&client_mutex); return 0; err: @@ -3263,9 +3269,6 @@ int snd_soc_register_codec(struct device *dev, return 0; error: - for (i--; i >= 0; i--) - snd_soc_unregister_dai(dev); - if (codec->reg_cache) kfree(codec->reg_cache); kfree(codec->name); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7d85c6496afa..c721502833bc 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -683,12 +683,12 @@ static int dapm_seq_compare(struct snd_soc_dapm_widget *a, struct snd_soc_dapm_widget *b, int sort[]) { - if (a->codec != b->codec) - return (unsigned long)a - (unsigned long)b; if (sort[a->id] != sort[b->id]) return sort[a->id] - sort[b->id]; if (a->reg != b->reg) return a->reg - b->reg; + if (a->codec != b->codec) + return (unsigned long)a->codec - (unsigned long)b->codec; return 0; } @@ -944,6 +944,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) case SND_SOC_DAPM_STREAM_RESUME: sys_power = 1; break; + case SND_SOC_DAPM_STREAM_STOP: + sys_power = !!codec->active; + break; case SND_SOC_DAPM_STREAM_SUSPEND: sys_power = 0; break; diff --git a/sound/sound_core.c b/sound/sound_core.c index c03bbaefdbc3..5580aced8730 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -104,7 +104,6 @@ module_exit(cleanup_soundcore); #include <linux/init.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sound.h> diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c index 1bc56b2b94e2..337a00241a1f 100644 --- a/sound/spi/at73c213.c +++ b/sound/spi/at73c213.c @@ -155,7 +155,7 @@ static int snd_at73c213_set_bitrate(struct snd_at73c213 *chip) if (max_tries < 1) max_tries = 1; - /* ssc_div must be a power of 2. */ + /* ssc_div must be even. */ ssc_div = (ssc_div + 1) & ~1UL; if ((ssc_rate / (ssc_div * 2 * 16)) < BITRATE_MIN) { |