diff options
Diffstat (limited to 'sound')
65 files changed, 1049 insertions, 457 deletions
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 1497dce1b04a..656e474dca47 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -172,14 +172,15 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg) return v; } -static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun) +static inline void +aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask) { u32 val; int timeout = 5000; do { val = readl(aacirun->base + AACI_SR); - } while (val & (SR_TXB|SR_RXB) && timeout--); + } while (val & mask && timeout--); } @@ -208,8 +209,10 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) writel(0, aacirun->base + AACI_IE); return; } - ptr = aacirun->ptr; + spin_lock(&aacirun->lock); + + ptr = aacirun->ptr; do { unsigned int len = aacirun->fifosz; u32 val; @@ -217,9 +220,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) if (aacirun->bytes <= 0) { aacirun->bytes += aacirun->period; aacirun->ptr = ptr; - spin_unlock(&aaci->lock); + spin_unlock(&aacirun->lock); snd_pcm_period_elapsed(aacirun->substream); - spin_lock(&aaci->lock); + spin_lock(&aacirun->lock); } if (!(aacirun->cr & CR_EN)) break; @@ -245,7 +248,10 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) ptr = aacirun->start; } } while(1); + aacirun->ptr = ptr; + + spin_unlock(&aacirun->lock); } if (mask & ISR_URINTR) { @@ -263,6 +269,8 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) return; } + spin_lock(&aacirun->lock); + ptr = aacirun->ptr; do { unsigned int len = aacirun->fifosz; @@ -271,9 +279,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) if (aacirun->bytes <= 0) { aacirun->bytes += aacirun->period; aacirun->ptr = ptr; - spin_unlock(&aaci->lock); + spin_unlock(&aacirun->lock); snd_pcm_period_elapsed(aacirun->substream); - spin_lock(&aaci->lock); + spin_lock(&aacirun->lock); } if (!(aacirun->cr & CR_EN)) break; @@ -301,6 +309,8 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask) } while (1); aacirun->ptr = ptr; + + spin_unlock(&aacirun->lock); } } @@ -310,7 +320,6 @@ static irqreturn_t aaci_irq(int irq, void *devid) u32 mask; int i; - spin_lock(&aaci->lock); mask = readl(aaci->base + AACI_ALLINTS); if (mask) { u32 m = mask; @@ -320,7 +329,6 @@ static irqreturn_t aaci_irq(int irq, void *devid) } } } - spin_unlock(&aaci->lock); return mask ? IRQ_HANDLED : IRQ_NONE; } @@ -330,63 +338,6 @@ static irqreturn_t aaci_irq(int irq, void *devid) /* * ALSA support. */ - -struct aaci_stream { - unsigned char codec_idx; - unsigned char rate_idx; -}; - -static struct aaci_stream aaci_streams[] = { - [ACSTREAM_FRONT] = { - .codec_idx = 0, - .rate_idx = AC97_RATES_FRONT_DAC, - }, - [ACSTREAM_SURROUND] = { - .codec_idx = 0, - .rate_idx = AC97_RATES_SURR_DAC, - }, - [ACSTREAM_LFE] = { - .codec_idx = 0, - .rate_idx = AC97_RATES_LFE_DAC, - }, -}; - -static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid) -{ - struct aaci_stream *s = aaci_streams + streamid; - return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx]; -} - -static unsigned int rate_list[] = { - 5512, 8000, 11025, 16000, 22050, 32000, 44100, - 48000, 64000, 88200, 96000, 176400, 192000 -}; - -/* - * Double-rate rule: we can support double rate iff channels == 2 - * (unimplemented) - */ -static int -aaci_rule_rate_by_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule) -{ - struct aaci *aaci = rule->private; - unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512; - struct snd_interval *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS); - - switch (c->max) { - case 6: - rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE); - case 4: - rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND); - case 2: - rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT); - } - - return snd_interval_list(hw_param_interval(p, rule->var), - ARRAY_SIZE(rate_list), rate_list, - rate_mask); -} - static struct snd_pcm_hardware aaci_hw_info = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | @@ -400,10 +351,7 @@ static struct snd_pcm_hardware aaci_hw_info = { */ .formats = SNDRV_PCM_FMTBIT_S16_LE, - /* should this be continuous or knot? */ - .rates = SNDRV_PCM_RATE_CONTINUOUS, - .rate_max = 48000, - .rate_min = 4000, + /* rates are setup from the AC'97 codec */ .channels_min = 2, .channels_max = 6, .buffer_bytes_max = 64 * 1024, @@ -423,6 +371,12 @@ static int __aaci_pcm_open(struct aaci *aaci, aacirun->substream = substream; runtime->private_data = aacirun; runtime->hw = aaci_hw_info; + runtime->hw.rates = aacirun->pcm->rates; + snd_pcm_limit_hw_rates(runtime); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && + aacirun->pcm->r[1].slots) + snd_ac97_pcm_double_rate_rules(runtime); /* * FIXME: ALSA specifies fifo_size in bytes. If we're in normal @@ -433,17 +387,6 @@ static int __aaci_pcm_open(struct aaci *aaci, */ runtime->hw.fifo_size = aaci->fifosize * 2; - /* - * Add rule describing hardware rate dependency - * on the number of channels. - */ - ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - aaci_rule_rate_by_channels, aaci, - SNDRV_PCM_HW_PARAM_CHANNELS, - SNDRV_PCM_HW_PARAM_RATE, -1); - if (ret) - goto out; - ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED|IRQF_DISABLED, DRIVER_NAME, aaci); if (ret) @@ -498,6 +441,7 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { int err; + struct aaci *aaci = substream->private_data; aaci_pcm_hw_free(substream); if (aacirun->pcm_open) { @@ -507,18 +451,22 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream, err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); - if (err < 0) - goto out; + if (err >= 0) { + unsigned int rate = params_rate(params); + int dbl = rate > 48000; - err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params), - params_channels(params), - aacirun->pcm->r[0].slots); - if (err) - goto out; + err = snd_ac97_pcm_open(aacirun->pcm, rate, + params_channels(params), + aacirun->pcm->r[dbl].slots); - aacirun->pcm_open = 1; + aacirun->pcm_open = err == 0; + aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; + aacirun->fifosz = aaci->fifosize * 4; + + if (aacirun->cr & CR_COMPACT) + aacirun->fifosz >>= 1; + } - out: return err; } @@ -527,7 +475,7 @@ static int aaci_pcm_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct aaci_runtime *aacirun = runtime->private_data; - aacirun->start = (void *)runtime->dma_area; + aacirun->start = runtime->dma_area; aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream); aacirun->ptr = aacirun->start; aacirun->period = @@ -613,7 +561,6 @@ static int aaci_pcm_open(struct snd_pcm_substream *substream) static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct aaci *aaci = substream->private_data; struct aaci_runtime *aacirun = substream->runtime->private_data; unsigned int channels = params_channels(params); int ret; @@ -627,14 +574,9 @@ static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream, * Enable FIFO, compact mode, 16 bits per sample. * FIXME: double rate slots? */ - if (ret >= 0) { - aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; + if (ret >= 0) aacirun->cr |= channels_to_txmask[channels]; - aacirun->fifosz = aaci->fifosize * 4; - if (aacirun->cr & CR_COMPACT) - aacirun->fifosz >>= 1; - } return ret; } @@ -646,7 +588,7 @@ static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun) ie &= ~(IE_URIE|IE_TXIE); writel(ie, aacirun->base + AACI_IE); aacirun->cr &= ~CR_EN; - aaci_chan_wait_ready(aacirun); + aaci_chan_wait_ready(aacirun, SR_TXB); writel(aacirun->cr, aacirun->base + AACI_TXCR); } @@ -654,7 +596,7 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) { u32 ie; - aaci_chan_wait_ready(aacirun); + aaci_chan_wait_ready(aacirun, SR_TXB); aacirun->cr |= CR_EN; ie = readl(aacirun->base + AACI_IE); @@ -665,12 +607,12 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun) static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd) { - struct aaci *aaci = substream->private_data; struct aaci_runtime *aacirun = substream->runtime->private_data; unsigned long flags; int ret = 0; - spin_lock_irqsave(&aaci->lock, flags); + spin_lock_irqsave(&aacirun->lock, flags); + switch (cmd) { case SNDRV_PCM_TRIGGER_START: aaci_pcm_playback_start(aacirun); @@ -697,7 +639,8 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm default: ret = -EINVAL; } - spin_unlock_irqrestore(&aaci->lock, flags); + + spin_unlock_irqrestore(&aacirun->lock, flags); return ret; } @@ -716,23 +659,14 @@ static struct snd_pcm_ops aaci_playback_ops = { static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct aaci *aaci = substream->private_data; struct aaci_runtime *aacirun = substream->runtime->private_data; int ret; ret = aaci_pcm_hw_params(substream, aacirun, params); - - if (ret >= 0) { - aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16; - + if (ret >= 0) /* Line in record: slot 3 and 4 */ aacirun->cr |= CR_SL3 | CR_SL4; - aacirun->fifosz = aaci->fifosize * 4; - - if (aacirun->cr & CR_COMPACT) - aacirun->fifosz >>= 1; - } return ret; } @@ -740,7 +674,7 @@ static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun) { u32 ie; - aaci_chan_wait_ready(aacirun); + aaci_chan_wait_ready(aacirun, SR_RXB); ie = readl(aacirun->base + AACI_IE); ie &= ~(IE_ORIE | IE_RXIE); @@ -755,7 +689,7 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun) { u32 ie; - aaci_chan_wait_ready(aacirun); + aaci_chan_wait_ready(aacirun, SR_RXB); #ifdef DEBUG /* RX Timeout value: bits 28:17 in RXCR */ @@ -772,12 +706,11 @@ static void aaci_pcm_capture_start(struct aaci_runtime *aacirun) static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd) { - struct aaci *aaci = substream->private_data; struct aaci_runtime *aacirun = substream->runtime->private_data; unsigned long flags; int ret = 0; - spin_lock_irqsave(&aaci->lock, flags); + spin_lock_irqsave(&aacirun->lock, flags); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -806,7 +739,7 @@ static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd ret = -EINVAL; } - spin_unlock_irqrestore(&aaci->lock, flags); + spin_unlock_irqrestore(&aacirun->lock, flags); return ret; } @@ -889,6 +822,12 @@ static struct ac97_pcm ac97_defs[] __devinitdata = { (1 << AC97_SLOT_PCM_SRIGHT) | (1 << AC97_SLOT_LFE), }, + [1] = { + .slots = (1 << AC97_SLOT_PCM_LEFT) | + (1 << AC97_SLOT_PCM_RIGHT) | + (1 << AC97_SLOT_PCM_LEFT_0) | + (1 << AC97_SLOT_PCM_RIGHT_0), + }, }, }, [1] = { /* PCM in */ @@ -1001,7 +940,6 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev) aaci = card->private_data; mutex_init(&aaci->ac97_sem); - spin_lock_init(&aaci->lock); aaci->card = card; aaci->dev = dev; @@ -1028,7 +966,7 @@ static int __devinit aaci_init_pcm(struct aaci *aaci) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops); snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - NULL, 0, 64 * 104); + NULL, 0, 64 * 1024); } return ret; @@ -1088,12 +1026,14 @@ static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id) /* * Playback uses AACI channel 0 */ + spin_lock_init(&aaci->playback.lock); aaci->playback.base = aaci->base + AACI_CSCH1; aaci->playback.fifo = aaci->base + AACI_DR1; /* * Capture uses AACI channel 0 */ + spin_lock_init(&aaci->capture.lock); aaci->capture.base = aaci->base + AACI_CSCH1; aaci->capture.fifo = aaci->base + AACI_DR1; diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h index 924f69c1c44c..6a4a2eebdda1 100644 --- a/sound/arm/aaci.h +++ b/sound/arm/aaci.h @@ -202,6 +202,7 @@ struct aaci_runtime { void __iomem *base; void __iomem *fifo; + spinlock_t lock; struct ac97_pcm *pcm; int pcm_open; @@ -232,7 +233,6 @@ struct aaci { struct snd_ac97 *ac97; u32 maincr; - spinlock_t lock; struct aaci_runtime playback; struct aaci_runtime capture; diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index b4b48afb6de6..5d9411839cd7 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -159,7 +159,7 @@ static int pxa2xx_ac97_resume(struct device *dev) return ret; } -static struct dev_pm_ops pxa2xx_ac97_pm_ops = { +static const struct dev_pm_ops pxa2xx_ac97_pm_ops = { .suspend = pxa2xx_ac97_suspend, .resume = pxa2xx_ac97_resume, }; diff --git a/sound/core/Kconfig b/sound/core/Kconfig index c15682a2f9db..475455c76610 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -5,6 +5,7 @@ config SND_TIMER config SND_PCM tristate select SND_TIMER + select GCD config SND_HWDEP tristate diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index 34c7d48f5061..7f4d744ae40a 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -37,14 +37,22 @@ static unsigned int resolution; struct snd_hrtimer { struct snd_timer *timer; struct hrtimer hrt; + atomic_t running; }; static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) { struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt); struct snd_timer *t = stime->timer; + + if (!atomic_read(&stime->running)) + return HRTIMER_NORESTART; + hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution)); snd_timer_interrupt(stime->timer, t->sticks); + + if (!atomic_read(&stime->running)) + return HRTIMER_NORESTART; return HRTIMER_RESTART; } @@ -58,6 +66,7 @@ static int snd_hrtimer_open(struct snd_timer *t) hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); stime->timer = t; stime->hrt.function = snd_hrtimer_callback; + atomic_set(&stime->running, 0); t->private_data = stime; return 0; } @@ -78,16 +87,18 @@ static int snd_hrtimer_start(struct snd_timer *t) { struct snd_hrtimer *stime = t->private_data; + atomic_set(&stime->running, 0); + hrtimer_cancel(&stime->hrt); hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), HRTIMER_MODE_REL); + atomic_set(&stime->running, 1); return 0; } static int snd_hrtimer_stop(struct snd_timer *t) { struct snd_hrtimer *stime = t->private_data; - - hrtimer_cancel(&stime->hrt); + atomic_set(&stime->running, 0); return 0; } diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 30f410832a25..a27545b23ee9 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -758,7 +758,7 @@ int snd_interval_ratnum(struct snd_interval *i, int diff; if (q == 0) q = 1; - den = div_down(num, q); + den = div_up(num, q); if (den < rats[k].den_min) continue; if (den > rats[k].den_max) @@ -794,7 +794,7 @@ int snd_interval_ratnum(struct snd_interval *i, i->empty = 1; return -EINVAL; } - den = div_up(num, q); + den = div_down(num, q); if (den > rats[k].den_max) continue; if (den < rats[k].den_min) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 29ab46a12e11..25b0641e6b8c 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1918,13 +1918,13 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, hw->rate_min, hw->rate_max); - if (err < 0) - return err; + if (err < 0) + return err; err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, hw->period_bytes_min, hw->period_bytes_max); - if (err < 0) - return err; + if (err < 0) + return err; err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIODS, hw->periods_min, hw->periods_max); diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c index ca8068b63d6c..b01d9481d632 100644 --- a/sound/core/pcm_timer.c +++ b/sound/core/pcm_timer.c @@ -20,6 +20,7 @@ */ #include <linux/time.h> +#include <linux/gcd.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/timer.h> @@ -28,22 +29,6 @@ * Timer functions */ -/* Greatest common divisor */ -static unsigned long gcd(unsigned long a, unsigned long b) -{ - unsigned long r; - if (a < b) { - r = a; - a = b; - b = r; - } - while ((r = a % b) != 0) { - a = b; - b = r; - } - return b; -} - void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) { unsigned long rate, mult, fsize, l, post; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 2f766123b158..0f5a194695d9 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -1257,7 +1257,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, break; count -= count1; } - if (file->f_flags & O_SYNC) { + if (file->f_flags & O_DSYNC) { spin_lock_irq(&runtime->lock); while (runtime->avail != runtime->buffer_size) { wait_queue_t wait; diff --git a/sound/core/sound.c b/sound/core/sound.c index 7872a02f6ca9..563d1967a0ad 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -468,5 +468,5 @@ static void __exit alsa_sound_exit(void) unregister_chrdev(major, "alsa"); } -module_init(alsa_sound_init) -module_exit(alsa_sound_exit) +subsys_initcall(alsa_sound_init); +module_exit(alsa_sound_exit); diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 7fe12264ff80..0c164e5e4322 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -93,7 +93,7 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) default: return -EINVAL; } - if (snd_BUG_ON(minor < 0 || minor >= SNDRV_OSS_MINORS)) + if (minor < 0 || minor >= SNDRV_OSS_MINORS) return -EINVAL; return minor; } diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index 661205c4dcea..af888a022fc0 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c @@ -127,7 +127,8 @@ static struct snd_gf1_mem_block *snd_gf1_mem_share(struct snd_gf1_mem * alloc, !share_id[2] && !share_id[3]) return NULL; for (block = alloc->first; block; block = block->next) - if (!memcmp(share_id, block->share_id, sizeof(share_id))) + if (!memcmp(share_id, block->share_id, + sizeof(block->share_id))) return block; return NULL; } diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c index cb9aa4c4edd0..4be562b2cf21 100644 --- a/sound/isa/msnd/msnd_midi.c +++ b/sound/isa/msnd/msnd_midi.c @@ -162,7 +162,7 @@ int snd_msndmidi_new(struct snd_card *card, int device) err = snd_rawmidi_new(card, "MSND-MIDI", device, 1, 1, &rmidi); if (err < 0) return err; - mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL); + mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); if (mpu == NULL) { snd_device_free(card, rmidi); return -ENOMEM; diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 106be6e471f7..c8a8da0d4036 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -548,10 +548,13 @@ __skip_mpu: static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) { - struct snd_wss *codec = dev_id; - struct snd_opti9xx *chip = codec->card->private_data; + struct snd_opti9xx *chip = dev_id; + struct snd_wss *codec = chip->codec; unsigned char status; + if (!codec) + return IRQ_HANDLED; + status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11)); if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream) snd_pcm_period_elapsed(codec->playback_substream); @@ -691,10 +694,9 @@ static void snd_card_opti9xx_free(struct snd_card *card) if (chip) { #ifdef OPTi93X - struct snd_wss *codec = chip->codec; - if (codec && codec->irq > 0) { - disable_irq(codec->irq); - free_irq(codec->irq, codec); + if (chip->irq > 0) { + disable_irq(chip->irq); + free_irq(chip->irq, chip); } release_and_free_resource(chip->res_mc_indir); #endif @@ -759,9 +761,9 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) #endif #ifdef OPTi93X error = request_irq(irq, snd_opti93x_interrupt, - IRQF_DISABLED, DEV_NAME" - WSS", codec); + IRQF_DISABLED, DEV_NAME" - WSS", chip); if (error < 0) { - snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq); + snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq); return error; } #endif diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 96678d5d3834..0c40951b6523 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -377,12 +377,13 @@ init_arrays(struct snd_emu8000 *emu) static void __devinit size_dram(struct snd_emu8000 *emu) { - int i, size; + int i, size, detected_size; if (emu->dram_checked) return; size = 0; + detected_size = 0; /* write out a magic number */ snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE); @@ -414,7 +415,9 @@ size_dram(struct snd_emu8000 *emu) /*snd_emu8000_read_wait(emu);*/ EMU8000_SMLD_READ(emu); /* discard stale data */ if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2) - break; /* we must have wrapped around */ + break; /* no memory at this address */ + + detected_size = size; snd_emu8000_read_wait(emu); @@ -442,9 +445,9 @@ size_dram(struct snd_emu8000 *emu) snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE); snd_printdd("EMU8000 [0x%lx]: %d Kb on-board memory detected\n", - emu->port1, size/1024); + emu->port1, detected_size/1024); - emu->mem_size = size; + emu->mem_size = detected_size; emu->dram_checked = 1; } diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 8691f4cf6191..f1d9d16b5486 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -609,7 +609,7 @@ static int snd_sgio2audio_pcm_hw_params(struct snd_pcm_substream *substream, /* alloc virtual 'dma' area */ if (runtime->dma_area) vfree(runtime->dma_area); - runtime->dma_area = vmalloc(size); + runtime->dma_area = vmalloc_user(size); if (runtime->dma_area == NULL) return -ENOMEM; runtime->dma_bytes = size; diff --git a/sound/oss/dev_table.c b/sound/oss/dev_table.c index 08274c995d06..727bdb9ba2dc 100644 --- a/sound/oss/dev_table.c +++ b/sound/oss/dev_table.c @@ -67,14 +67,15 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, return -(EBUSY); } d = (struct audio_driver *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_driver))); - - if (sound_nblocks < 1024) - sound_nblocks++; + sound_nblocks++; + 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))); + sound_nblocks++; + if (sound_nblocks >= MAX_MEM_BLOCKS) + sound_nblocks = MAX_MEM_BLOCKS - 1; - if (sound_nblocks < 1024) - sound_nblocks++; if (d == NULL || op == NULL) { printk(KERN_ERR "Sound: Can't allocate driver for (%s)\n", name); sound_unload_audiodev(num); @@ -128,9 +129,10 @@ int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, until you unload sound! */ op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations))); + sound_nblocks++; + if (sound_nblocks >= MAX_MEM_BLOCKS) + sound_nblocks = MAX_MEM_BLOCKS - 1; - if (sound_nblocks < 1024) - sound_nblocks++; if (op == NULL) { printk(KERN_ERR "Sound: Can't allocate mixer driver for (%s)\n", name); return -ENOMEM; diff --git a/sound/oss/pss.c b/sound/oss/pss.c index 83f5ee236b12..e19dd5dcc2de 100644 --- a/sound/oss/pss.c +++ b/sound/oss/pss.c @@ -269,7 +269,7 @@ static int pss_reset_dsp(pss_confdata * devc) unsigned long i, limit = jiffies + HZ/10; outw(0x2000, REG(PSS_CONTROL)); - for (i = 0; i < 32768 && (limit-jiffies >= 0); i++) + for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++) inw(REG(PSS_CONTROL)); outw(0x0000, REG(PSS_CONTROL)); return 1; @@ -369,11 +369,11 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size outw(0, REG(PSS_DATA)); limit = jiffies + HZ/10; - for (i = 0; i < 32768 && (limit - jiffies >= 0); i++) + for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++) val = inw(REG(PSS_STATUS)); limit = jiffies + HZ/10; - for (i = 0; i < 32768 && (limit-jiffies >= 0); i++) + for (i = 0; i < 32768 && time_after_eq(limit, jiffies); i++) { val = inw(REG(PSS_STATUS)); if (val & 0x4000) diff --git a/sound/oss/sound_config.h b/sound/oss/sound_config.h index 55271fbe7f49..9d35c4c65b9b 100644 --- a/sound/oss/sound_config.h +++ b/sound/oss/sound_config.h @@ -142,4 +142,6 @@ static inline int translate_mode(struct file *file) #define TIMER_ARMED 121234 #define TIMER_NOT_ARMED 1 +#define MAX_MEM_BLOCKS 1024 + #endif diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 61aaedae6b7e..c62530943888 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -56,7 +56,7 @@ /* * Table for permanently allocated memory (used when unloading the module) */ -void * sound_mem_blocks[1024]; +void * sound_mem_blocks[MAX_MEM_BLOCKS]; int sound_nblocks = 0; /* Persistent DMA buffers */ @@ -574,7 +574,7 @@ static int __init oss_init(void) NULL, "%s%d", dev_list[i].name, j); } - if (sound_nblocks >= 1024) + if (sound_nblocks >= MAX_MEM_BLOCKS - 1) printk(KERN_ERR "Sound warning: Deallocation table was too small.\n"); return 0; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 20cb60afb200..a7630e9edf8a 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -83,6 +83,7 @@ static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = { { 0x4e534300, 0xffffff00, "National Semiconductor", NULL, NULL }, { 0x50534300, 0xffffff00, "Philips", NULL, NULL }, { 0x53494c00, 0xffffff00, "Silicon Laboratory", NULL, NULL }, +{ 0x53544d00, 0xffffff00, "STMicroelectronics", NULL, NULL }, { 0x54524100, 0xffffff00, "TriTech", NULL, NULL }, { 0x54584e00, 0xffffff00, "Texas Instruments", NULL, NULL }, { 0x56494100, 0xffffff00, "VIA Technologies", NULL, NULL }, @@ -161,6 +162,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { { 0x4e534350, 0xffffffff, "LM4550", patch_lm4550, NULL }, // volume wrap fix { 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL }, { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, +{ 0x53544d02, 0xffffffff, "ST7597", NULL, NULL }, { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, { 0x54524103, 0xffffffff, "TR28023", NULL, NULL }, { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, @@ -213,6 +215,14 @@ static int snd_ac97_valid_reg(struct snd_ac97 *ac97, unsigned short reg) { /* filter some registers for buggy codecs */ switch (ac97->id) { + case AC97_ID_ST_AC97_ID4: + if (reg == 0x08) + return 0; + /* fall through */ + case AC97_ID_ST7597: + if (reg == 0x22 || reg == 0x7a) + return 1; + /* fall through */ case AC97_ID_AK4540: case AC97_ID_AK4542: if (reg <= 0x1c || reg == 0x20 || reg == 0x26 || reg >= 0x7c) @@ -2122,7 +2132,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, } /* nothing should be in powerdown mode */ snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0); - end_time = jiffies + msecs_to_jiffies(120); + end_time = jiffies + msecs_to_jiffies(5000); do { if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f) goto __ready_ok; diff --git a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h index c129492c82b3..d603147c4a96 100644 --- a/sound/pci/ac97/ac97_id.h +++ b/sound/pci/ac97/ac97_id.h @@ -62,3 +62,5 @@ #define AC97_ID_CM9761_78 0x434d4978 #define AC97_ID_CM9761_82 0x434d4982 #define AC97_ID_CM9761_83 0x434d4983 +#define AC97_ID_ST7597 0x53544d02 +#define AC97_ID_ST_AC97_ID4 0x53544d04 diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 139cf3b2b9d7..d9266bae2849 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1870,6 +1870,7 @@ static unsigned int ad1981_jacks_blacklist[] = { 0x10140554, /* Thinkpad T42p/R50p */ 0x10140567, /* Thinkpad T43p 2668-G7U */ 0x10140581, /* Thinkpad X41-2527 */ + 0x10280160, /* Dell Dimension 2400 */ 0x104380b0, /* Asus A7V8X-MX */ 0x11790241, /* Toshiba Satellite A-15 S127 */ 0x144dc01a, /* Samsung NP-X20C004/SEG */ diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index d6752dff2a44..42b4fbbd8e2b 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -297,6 +297,7 @@ static struct pci_device_id snd_atiixp_ids[] = { MODULE_DEVICE_TABLE(pci, snd_atiixp_ids); static struct snd_pci_quirk atiixp_quirks[] __devinitdata = { + SND_PCI_QUIRK(0x105b, 0x0c81, "Foxconn RC4107MA-RS2", 0), SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0), { } /* terminator */ }; diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile index fda7a94c992f..ccc642269b9e 100644 --- a/sound/pci/cs5535audio/Makefile +++ b/sound/pci/cs5535audio/Makefile @@ -4,9 +4,7 @@ snd-cs5535audio-y := cs5535audio.o cs5535audio_pcm.o snd-cs5535audio-$(CONFIG_PM) += cs5535audio_pm.o -ifdef CONFIG_MGEODE_LX snd-cs5535audio-$(CONFIG_OLPC) += cs5535audio_olpc.o -endif # Toplevel Module Dependency obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 05f56e04849b..91e7faf69bbb 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c @@ -389,6 +389,7 @@ probefail_out: static void __devexit snd_cs5535audio_remove(struct pci_dev *pci) { + olpc_quirks_cleanup(); snd_card_free(pci_get_drvdata(pci)); pci_set_drvdata(pci, NULL); } diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h index 7a298ac662e3..51966d782a3c 100644 --- a/sound/pci/cs5535audio/cs5535audio.h +++ b/sound/pci/cs5535audio/cs5535audio.h @@ -99,10 +99,11 @@ int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state); int snd_cs5535audio_resume(struct pci_dev *pci); #endif -#if defined(CONFIG_OLPC) && defined(CONFIG_MGEODE_LX) +#ifdef CONFIG_OLPC void __devinit olpc_prequirks(struct snd_card *card, struct snd_ac97_template *ac97); int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97); +void __devexit olpc_quirks_cleanup(void); void olpc_analog_input(struct snd_ac97 *ac97, int on); void olpc_mic_bias(struct snd_ac97 *ac97, int on); @@ -128,6 +129,7 @@ static inline int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) { return 0; } +static inline void olpc_quirks_cleanup(void) { } static inline void olpc_analog_input(struct snd_ac97 *ac97, int on) { } static inline void olpc_mic_bias(struct snd_ac97 *ac97, int on) { } static inline void olpc_capture_open(struct snd_ac97 *ac97) { } diff --git a/sound/pci/cs5535audio/cs5535audio_olpc.c b/sound/pci/cs5535audio/cs5535audio_olpc.c index 5c6814335cd7..50da49be9ae5 100644 --- a/sound/pci/cs5535audio/cs5535audio_olpc.c +++ b/sound/pci/cs5535audio/cs5535audio_olpc.c @@ -13,10 +13,13 @@ #include <sound/info.h> #include <sound/control.h> #include <sound/ac97_codec.h> +#include <linux/gpio.h> #include <asm/olpc.h> #include "cs5535audio.h" +#define DRV_NAME "cs5535audio-olpc" + /* * OLPC has an additional feature on top of the regular AD1888 codec features. * It has an Analog Input mode that is switched into (after disabling the @@ -38,10 +41,7 @@ void olpc_analog_input(struct snd_ac97 *ac97, int on) } /* set Analog Input through GPIO */ - if (on) - geode_gpio_set(OLPC_GPIO_MIC_AC, GPIO_OUTPUT_VAL); - else - geode_gpio_clear(OLPC_GPIO_MIC_AC, GPIO_OUTPUT_VAL); + gpio_set_value(OLPC_GPIO_MIC_AC, on); } /* @@ -73,8 +73,7 @@ static int olpc_dc_info(struct snd_kcontrol *kctl, static int olpc_dc_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v) { - v->value.integer.value[0] = geode_gpio_isset(OLPC_GPIO_MIC_AC, - GPIO_OUTPUT_VAL); + v->value.integer.value[0] = gpio_get_value(OLPC_GPIO_MIC_AC); return 0; } @@ -153,6 +152,12 @@ int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) if (!machine_is_olpc()) return 0; + if (gpio_request(OLPC_GPIO_MIC_AC, DRV_NAME)) { + printk(KERN_ERR DRV_NAME ": unable to allocate MIC GPIO\n"); + return -EIO; + } + gpio_direction_output(OLPC_GPIO_MIC_AC, 0); + /* drop the original AD1888 HPF control */ memset(&elem, 0, sizeof(elem)); elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER; @@ -169,11 +174,18 @@ int __devinit olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97) for (i = 0; i < ARRAY_SIZE(olpc_cs5535audio_ctls); i++) { err = snd_ctl_add(card, snd_ctl_new1(&olpc_cs5535audio_ctls[i], ac97->private_data)); - if (err < 0) + if (err < 0) { + gpio_free(OLPC_GPIO_MIC_AC); return err; + } } /* turn off the mic by default */ olpc_mic_bias(ac97, 0); return 0; } + +void __devexit olpc_quirks_cleanup(void) +{ + gpio_free(OLPC_GPIO_MIC_AC); +} diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 5fe34a8d8c81..e4581a42ace5 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -42,7 +42,7 @@ static void snd_hda_generate_beep(struct work_struct *work) return; /* generate tone */ - snd_hda_codec_write_cache(codec, beep->nid, 0, + snd_hda_codec_write(codec, beep->nid, 0, AC_VERB_SET_BEEP_CONTROL, beep->tone); } @@ -119,7 +119,7 @@ static void snd_hda_do_detach(struct hda_beep *beep) beep->dev = NULL; cancel_work_sync(&beep->beep_work); /* turn off beep for sure */ - snd_hda_codec_write_cache(beep->codec, beep->nid, 0, + snd_hda_codec_write(beep->codec, beep->nid, 0, AC_VERB_SET_BEEP_CONTROL, 0); } @@ -192,7 +192,7 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) beep->enabled = enable; if (!enable) { /* turn off beep */ - snd_hda_codec_write_cache(beep->codec, beep->nid, 0, + snd_hda_codec_write(beep->codec, beep->nid, 0, AC_VERB_SET_BEEP_CONTROL, 0); } if (beep->mode == HDA_BEEP_MODE_SWREG) { @@ -239,8 +239,12 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) mutex_init(&beep->mutex); if (beep->mode == HDA_BEEP_MODE_ON) { - beep->enabled = 1; - snd_hda_do_register(&beep->register_work); + int err = snd_hda_do_attach(beep); + if (err < 0) { + kfree(beep); + codec->beep = NULL; + return err; + } } return 0; @@ -253,7 +257,7 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) if (beep) { cancel_work_sync(&beep->register_work); cancel_delayed_work(&beep->unregister_work); - if (beep->enabled) + if (beep->dev) snd_hda_do_detach(beep); codec->beep = NULL; kfree(beep); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 9cfdb771928c..f98b47cd6cfb 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1086,11 +1086,6 @@ int snd_hda_codec_configure(struct hda_codec *codec) if (err < 0) return err; } - /* audio codec should override the mixer name */ - if (codec->afg || !*codec->bus->card->mixername) - snprintf(codec->bus->card->mixername, - sizeof(codec->bus->card->mixername), - "%s %s", codec->vendor_name, codec->chip_name); if (is_generic_config(codec)) { err = snd_hda_parse_generic_codec(codec); @@ -1109,6 +1104,11 @@ int snd_hda_codec_configure(struct hda_codec *codec) patched: if (!err && codec->patch_ops.unsol_event) err = init_unsol_queue(codec->bus); + /* audio codec should override the mixer name */ + if (!err && (codec->afg || !*codec->bus->card->mixername)) + snprintf(codec->bus->card->mixername, + sizeof(codec->bus->card->mixername), + "%s %s", codec->vendor_name, codec->chip_name); return err; } EXPORT_SYMBOL_HDA(snd_hda_codec_configure); @@ -1327,11 +1327,13 @@ EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps); */ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) { - u32 pincap = snd_hda_query_pin_caps(codec, nid); - - if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ - snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); + u32 pincap; + if (!codec->no_trigger_sense) { + pincap = snd_hda_query_pin_caps(codec, nid); + if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ + snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0); + } return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0); } diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 2d627613aea3..0a770a28e71f 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -255,9 +255,13 @@ enum { * in HD-audio specification */ #define AC_PINCAP_HDMI (1<<7) /* HDMI pin */ +#define AC_PINCAP_DP (1<<24) /* DisplayPort pin, can + * coexist with AC_PINCAP_HDMI + */ #define AC_PINCAP_VREF (0x37<<8) #define AC_PINCAP_VREF_SHIFT 8 #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ +#define AC_PINCAP_HBR (1<<27) /* High Bit Rate */ /* Vref status (used in pin cap) */ #define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */ #define AC_PINCAP_VREF_50 (1<<1) /* 50% */ @@ -635,6 +639,7 @@ struct hda_bus { unsigned int rirb_error:1; /* error in codec communication */ unsigned int response_reset:1; /* controller was reset */ unsigned int in_reset:1; /* during reset operation */ + unsigned int power_keep_link_on:1; /* don't power off HDA link */ }; /* @@ -812,6 +817,7 @@ struct hda_codec { unsigned int pin_amp_workaround:1; /* pin out-amp takes index * (e.g. Conexant codecs) */ + unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ #ifdef CONFIG_SND_HDA_POWER_SAVE unsigned int power_on :1; /* current (global) power-state */ unsigned int power_transition :1; /* power-state in transition */ diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index d24328661c6a..40ccb419b6e9 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c @@ -24,6 +24,7 @@ #include <linux/compat.h> #include <linux/mutex.h> #include <linux/ctype.h> +#include <linux/string.h> #include <linux/firmware.h> #include <sound/core.h> #include "hda_codec.h" @@ -428,8 +429,7 @@ static int parse_hints(struct hda_codec *codec, const char *buf) char *key, *val; struct hda_hint *hint; - while (isspace(*buf)) - buf++; + buf = skip_spaces(buf); if (!*buf || *buf == '#' || *buf == '\n') return 0; if (*buf == '=') @@ -444,8 +444,7 @@ static int parse_hints(struct hda_codec *codec, const char *buf) return -EINVAL; } *val++ = 0; - while (isspace(*val)) - val++; + val = skip_spaces(val); remove_trail_spaces(key); remove_trail_spaces(val); hint = get_hint(codec, key); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index efcc4f7c57f2..565de38a3fc7 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -356,6 +356,7 @@ struct azx_dev { */ unsigned char stream_tag; /* assigned stream */ unsigned char index; /* stream index */ + int device; /* last device number assigned to */ unsigned int opened :1; unsigned int running :1; @@ -1441,10 +1442,13 @@ static int __devinit azx_codec_configure(struct azx *chip) */ /* assign a stream for the PCM */ -static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream) +static inline struct azx_dev * +azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) { int dev, i, nums; - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + struct azx_dev *res = NULL; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dev = chip->playback_index_offset; nums = chip->playback_streams; } else { @@ -1453,10 +1457,15 @@ static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream) } for (i = 0; i < nums; i++, dev++) if (!chip->azx_dev[dev].opened) { - chip->azx_dev[dev].opened = 1; - return &chip->azx_dev[dev]; + res = &chip->azx_dev[dev]; + if (res->device == substream->pcm->device) + break; } - return NULL; + if (res) { + res->opened = 1; + res->device = substream->pcm->device; + } + return res; } /* release the assigned stream */ @@ -1505,7 +1514,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) int err; mutex_lock(&chip->open_mutex); - azx_dev = azx_assign_device(chip, substream->stream); + azx_dev = azx_assign_device(chip, substream); if (azx_dev == NULL) { mutex_unlock(&chip->open_mutex); return -EBUSY; @@ -2082,7 +2091,8 @@ static void azx_power_notify(struct hda_bus *bus) } if (power_on) azx_init_chip(chip); - else if (chip->running && power_save_controller) + else if (chip->running && power_save_controller && + !bus->power_keep_link_on) azx_stop_chip(chip); } #endif /* CONFIG_SND_HDA_POWER_SAVE */ @@ -2321,6 +2331,8 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) * white/black-list for enable_msi */ static struct snd_pci_quirk msi_black_list[] __devinitdata = { + SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ + SND_PCI_QUIRK(0x1043, 0x829c, "ASUS", 0), /* nvidia */ {} }; @@ -2712,6 +2724,9 @@ static struct pci_device_id azx_ids[] = { { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA }, + { PCI_DEVICE(0x10de, 0x0be2), .driver_data = AZX_DRIVER_NVIDIA }, + { PCI_DEVICE(0x10de, 0x0be3), .driver_data = AZX_DRIVER_NVIDIA }, + { PCI_DEVICE(0x10de, 0x0be4), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA }, { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA }, diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 09476fc1ab64..c9afc04adac8 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -240,9 +240,14 @@ static void print_pin_caps(struct snd_info_buffer *buffer, /* Realtek uses this bit as a different meaning */ if ((codec->vendor_id >> 16) == 0x10ec) snd_iprintf(buffer, " R/L"); - else + else { + if (caps & AC_PINCAP_HBR) + snd_iprintf(buffer, " HBR"); snd_iprintf(buffer, " HDMI"); + } } + if (caps & AC_PINCAP_DP) + snd_iprintf(buffer, " DP"); if (caps & AC_PINCAP_TRIG_REQ) snd_iprintf(buffer, " Trigger"); if (caps & AC_PINCAP_IMP_SENSE) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 447eda1f6770..69a941c7b158 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -1186,6 +1186,8 @@ static int patch_ad1986a(struct hda_codec *codec) */ spec->multiout.no_share_stream = 1; + codec->no_trigger_sense = 1; + return 0; } @@ -1371,6 +1373,8 @@ static int patch_ad1983(struct hda_codec *codec) codec->patch_ops = ad198x_patch_ops; + codec->no_trigger_sense = 1; + return 0; } @@ -1789,6 +1793,14 @@ static int patch_ad1981(struct hda_codec *codec) codec->patch_ops.init = ad1981_hp_init; codec->patch_ops.unsol_event = ad1981_hp_unsol_event; + /* set the upper-limit for mixer amp to 0dB for avoiding the + * possible damage by overloading + */ + snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, + (0x17 << AC_AMPCAP_OFFSET_SHIFT) | + (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | + (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | + (1 << AC_AMPCAP_MUTE_SHIFT)); break; case AD1981_THINKPAD: spec->mixers[0] = ad1981_thinkpad_mixers; @@ -1805,6 +1817,9 @@ static int patch_ad1981(struct hda_codec *codec) codec->patch_ops.unsol_event = ad1981_hp_unsol_event; break; } + + codec->no_trigger_sense = 1; + return 0; } @@ -3110,6 +3125,8 @@ static int patch_ad1988(struct hda_codec *codec) #endif spec->vmaster_nid = 0x04; + codec->no_trigger_sense = 1; + return 0; } @@ -3322,6 +3339,8 @@ static int patch_ad1884(struct hda_codec *codec) codec->patch_ops = ad198x_patch_ops; + codec->no_trigger_sense = 1; + return 0; } @@ -4279,6 +4298,8 @@ static int patch_ad1884a(struct hda_codec *codec) break; } + codec->no_trigger_sense = 1; + return 0; } @@ -4615,6 +4636,9 @@ static int patch_ad1882(struct hda_codec *codec) spec->mixers[2] = ad1882_6stack_mixers; break; } + + codec->no_trigger_sense = 1; + return 0; } diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 4b200da1bd18..fe0423c39598 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -66,6 +66,7 @@ struct cs_spec { /* available models */ enum { CS420X_MBP55, + CS420X_IMAC27, CS420X_AUTO, CS420X_MODELS }; @@ -827,7 +828,8 @@ static void cs_automute(struct hda_codec *codec) AC_VERB_SET_PIN_WIDGET_CONTROL, hp_present ? 0 : PIN_OUT); } - if (spec->board_config == CS420X_MBP55) { + if (spec->board_config == CS420X_MBP55 || + spec->board_config == CS420X_IMAC27) { unsigned int gpio = hp_present ? 0x02 : 0x08; snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, gpio); @@ -1069,12 +1071,14 @@ static int cs_parse_auto_config(struct hda_codec *codec) static const char *cs420x_models[CS420X_MODELS] = { [CS420X_MBP55] = "mbp55", + [CS420X_IMAC27] = "imac27", [CS420X_AUTO] = "auto", }; static struct snd_pci_quirk cs420x_cfg_tbl[] = { SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), + SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), {} /* terminator */ }; @@ -1097,8 +1101,23 @@ static struct cs_pincfg mbp55_pincfgs[] = { {} /* terminator */ }; +static struct cs_pincfg imac27_pincfgs[] = { + { 0x09, 0x012b4050 }, + { 0x0a, 0x90100140 }, + { 0x0b, 0x90100142 }, + { 0x0c, 0x018b3020 }, + { 0x0d, 0x90a00110 }, + { 0x0e, 0x400000f0 }, + { 0x0f, 0x01cbe030 }, + { 0x10, 0x014be060 }, + { 0x12, 0x01ab9070 }, + { 0x15, 0x400000f0 }, + {} /* terminator */ +}; + static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { [CS420X_MBP55] = mbp55_pincfgs, + [CS420X_IMAC27] = imac27_pincfgs, }; static void fix_pincfg(struct hda_codec *codec, int model) @@ -1128,6 +1147,7 @@ static int patch_cs420x(struct hda_codec *codec) fix_pincfg(codec, spec->board_config); switch (spec->board_config) { + case CS420X_IMAC27: case CS420X_MBP55: /* GPIO1 = headphones */ /* GPIO3 = speakers */ diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index a09c03c3f62b..c578c28f368e 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -29,6 +29,7 @@ #include "hda_codec.h" #include "hda_local.h" +#include "hda_beep.h" #define CXT_PIN_DIR_IN 0x00 #define CXT_PIN_DIR_OUT 0x01 @@ -111,6 +112,7 @@ struct conexant_spec { unsigned int dell_automute; unsigned int port_d_mode; unsigned char ext_mic_bias; + unsigned int dell_vostro; }; static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo, @@ -476,6 +478,7 @@ static void conexant_free(struct hda_codec *codec) snd_array_free(&spec->jacks); } #endif + snd_hda_detach_beep_device(codec); kfree(codec->spec); } @@ -2109,9 +2112,12 @@ static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); int val; + hda_nid_t nid = kcontrol->private_value & 0xff; + int inout = (kcontrol->private_value & 0x100) ? + AC_AMP_GET_INPUT : AC_AMP_GET_OUTPUT; - val = snd_hda_codec_read(codec, 0x17, 0, - AC_VERB_GET_AMP_GAIN_MUTE, AC_AMP_GET_OUTPUT); + val = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_AMP_GAIN_MUTE, inout); ucontrol->value.enumerated.item[0] = val & AC_AMP_GAIN; return 0; @@ -2123,6 +2129,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, struct hda_codec *codec = snd_kcontrol_chip(kcontrol); const struct hda_input_mux *imux = &cxt5066_analog_mic_boost; unsigned int idx; + hda_nid_t nid = kcontrol->private_value & 0xff; + int inout = (kcontrol->private_value & 0x100) ? + AC_AMP_SET_INPUT : AC_AMP_SET_OUTPUT; if (!imux->num_items) return 0; @@ -2130,9 +2139,9 @@ static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol, if (idx >= imux->num_items) idx = imux->num_items - 1; - snd_hda_codec_write_cache(codec, 0x17, 0, + snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | + AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | inout | imux->items[idx].index); return 1; @@ -2201,10 +2210,11 @@ static struct snd_kcontrol_new cxt5066_mixers[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Mic Boost Capture Enum", + .name = "Ext Mic Boost Capture Enum", .info = cxt5066_mic_boost_mux_enum_info, .get = cxt5066_mic_boost_mux_enum_get, .put = cxt5066_mic_boost_mux_enum_put, + .private_value = 0x17, }, HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others), @@ -2212,6 +2222,19 @@ static struct snd_kcontrol_new cxt5066_mixers[] = { {} }; +static struct snd_kcontrol_new cxt5066_vostro_mixers[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Int Mic Boost Capture Enum", + .info = cxt5066_mic_boost_mux_enum_info, + .get = cxt5066_mic_boost_mux_enum_get, + .put = cxt5066_mic_boost_mux_enum_put, + .private_value = 0x23 | 0x100, + }, + HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), + {} +}; + static struct hda_verb cxt5066_init_verbs[] = { {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */ @@ -2397,11 +2420,16 @@ static struct hda_verb cxt5066_init_verbs_portd_lo[] = { /* initialize jack-sensing, too */ static int cxt5066_init(struct hda_codec *codec) { + struct conexant_spec *spec = codec->spec; + snd_printdd("CXT5066: init\n"); conexant_init(codec); if (codec->patch_ops.unsol_event) { cxt5066_hp_automute(codec); - cxt5066_automic(codec); + if (spec->dell_vostro) + cxt5066_vostro_automic(codec); + else + cxt5066_automic(codec); } return 0; } @@ -2500,7 +2528,10 @@ static int patch_cxt5066(struct hda_codec *codec) spec->init_verbs[0] = cxt5066_init_verbs_vostro; spec->mixers[spec->num_mixers++] = cxt5066_mixer_master_olpc; spec->mixers[spec->num_mixers++] = cxt5066_mixers; + spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers; spec->port_d_mode = 0; + spec->dell_vostro = 1; + snd_hda_attach_beep_device(codec, 0x13); /* no S/PDIF out */ spec->multiout.dig_out_nid = 0; diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index 928df59be5d8..918f40378d52 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c @@ -146,38 +146,78 @@ struct cea_channel_speaker_allocation { }; /* + * ALSA sequence is: + * + * surround40 surround41 surround50 surround51 surround71 + * ch0 front left = = = = + * ch1 front right = = = = + * ch2 rear left = = = = + * ch3 rear right = = = = + * ch4 LFE center center center + * ch5 LFE LFE + * ch6 side left + * ch7 side right + * + * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR} + */ +static int hdmi_channel_mapping[0x32][8] = { + /* stereo */ + [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* 2.1 */ + [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* Dolby Surround */ + [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 }, + /* surround40 */ + [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 }, + /* 4ch */ + [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, + /* surround41 */ + [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, + /* surround50 */ + [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, + /* surround51 */ + [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 }, + /* 7.1 */ + [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 }, +}; + +/* * This is an ordered list! * * The preceding ones have better chances to be selected by * hdmi_setup_channel_allocation(). */ static struct cea_channel_speaker_allocation channel_allocations[] = { -/* channel: 8 7 6 5 4 3 2 1 */ +/* channel: 7 6 5 4 3 2 1 0 */ { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, /* 2.1 */ { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, /* Dolby Surround */ { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, + /* surround40 */ +{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, + /* surround41 */ +{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, + /* surround50 */ +{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, + /* surround51 */ +{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, + /* 6.1 */ +{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, + /* surround71 */ +{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, + { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, - /* 5.1 */ -{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, - /* 6.1 */ -{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, - /* 7.1 */ -{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, @@ -210,7 +250,6 @@ static struct cea_channel_speaker_allocation channel_allocations[] = { { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, }; - /* * HDA/HDMI auto parsing */ @@ -344,7 +383,7 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec) break; case AC_WID_PIN: caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); - if (!(caps & AC_PINCAP_HDMI)) + if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) continue; if (intel_hdmi_add_pin(codec, nid) < 0) return -EINVAL; @@ -352,6 +391,17 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec) } } + /* + * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event + * can be lost and presence sense verb will become inaccurate if the + * HDA link is powered off at hot plug or hw initialization time. + */ +#ifdef CONFIG_SND_HDA_POWER_SAVE + if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & + AC_PWRST_EPSS)) + codec->bus->power_keep_link_on = 1; +#endif + return 0; } @@ -436,14 +486,15 @@ static void hdmi_set_channel_count(struct hda_codec *codec, AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); } -static void hdmi_debug_channel_mapping(struct hda_codec *codec, hda_nid_t nid) +static void hdmi_debug_channel_mapping(struct hda_codec *codec, + hda_nid_t pin_nid) { #ifdef CONFIG_SND_DEBUG_VERBOSE int i; int slot; for (i = 0; i < 8; i++) { - slot = snd_hda_codec_read(codec, nid, 0, + slot = snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_CHAN_SLOT, i); printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", slot >> 4, slot & 0xf); @@ -619,25 +670,32 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, return ai->CA; } -static void hdmi_setup_channel_mapping(struct hda_codec *codec, hda_nid_t nid, +static void hdmi_setup_channel_mapping(struct hda_codec *codec, + hda_nid_t pin_nid, struct hdmi_audio_infoframe *ai) { int i; + int ca = ai->CA; + int err; - if (!ai->CA) - return; - - /* - * TODO: adjust channel mapping if necessary - * ALSA sequence is front/surr/clfe/side? - */ + if (hdmi_channel_mapping[ca][1] == 0) { + for (i = 0; i < channel_allocations[ca].channels; i++) + hdmi_channel_mapping[ca][i] = i | (i << 4); + for (; i < 8; i++) + hdmi_channel_mapping[ca][i] = 0xf | (i << 4); + } - for (i = 0; i < 8; i++) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_HDMI_CHAN_SLOT, - (i << 4) | i); + for (i = 0; i < 8; i++) { + err = snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_HDMI_CHAN_SLOT, + hdmi_channel_mapping[ca][i]); + if (err) { + snd_printdd(KERN_INFO "HDMI: channel mapping failed\n"); + break; + } + } - hdmi_debug_channel_mapping(codec, nid); + hdmi_debug_channel_mapping(codec, pin_nid); } static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, @@ -676,7 +734,6 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, }; hdmi_setup_channel_allocation(codec, nid, &ai); - hdmi_setup_channel_mapping(codec, nid, &ai); for (i = 0; i < spec->num_pins; i++) { if (spec->pin_cvt[i] != nid) @@ -686,6 +743,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, pin_nid = spec->pin[i]; if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { + hdmi_setup_channel_mapping(codec, pin_nid, &ai); hdmi_stop_infoframe_trans(codec, pin_nid); hdmi_fill_audio_infoframe(codec, pin_nid, &ai); hdmi_start_infoframe_trans(codec, pin_nid); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 888b6313eeca..da34095c707f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -131,8 +131,8 @@ enum { enum { ALC269_BASIC, ALC269_QUANTA_FL1, - ALC269_ASUS_EEEPC_P703, - ALC269_ASUS_EEEPC_P901, + ALC269_ASUS_AMIC, + ALC269_ASUS_DMIC, ALC269_FUJITSU, ALC269_LIFEBOOK, ALC269_AUTO, @@ -188,6 +188,8 @@ enum { ALC663_ASUS_MODE4, ALC663_ASUS_MODE5, ALC663_ASUS_MODE6, + ALC663_ASUS_MODE7, + ALC663_ASUS_MODE8, ALC272_DELL, ALC272_DELL_ZM1, ALC272_SAMSUNG_NC10, @@ -335,6 +337,9 @@ struct alc_spec { /* hooks */ void (*init_hook)(struct hda_codec *codec); void (*unsol_event)(struct hda_codec *codec, unsigned int res); +#ifdef CONFIG_SND_HDA_POWER_SAVE + void (*power_hook)(struct hda_codec *codec, int power); +#endif /* for pin sensing */ unsigned int sense_updated: 1; @@ -386,6 +391,7 @@ struct alc_config_preset { void (*init_hook)(struct hda_codec *); #ifdef CONFIG_SND_HDA_POWER_SAVE struct hda_amp_list *loopbacks; + void (*power_hook)(struct hda_codec *codec, int power); #endif }; @@ -898,6 +904,7 @@ static void setup_preset(struct hda_codec *codec, spec->unsol_event = preset->unsol_event; spec->init_hook = preset->init_hook; #ifdef CONFIG_SND_HDA_POWER_SAVE + spec->power_hook = preset->power_hook; spec->loopback.amplist = preset->loopbacks; #endif @@ -1086,6 +1093,16 @@ static void alc889_coef_init(struct hda_codec *codec) snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010); } +/* turn on/off EAPD control (only if available) */ +static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on) +{ + if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) + return; + if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD) + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE, + on ? 2 : 0); +} + static void alc_auto_init_amp(struct hda_codec *codec, int type) { unsigned int tmp; @@ -1103,25 +1120,22 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) case ALC_INIT_DEFAULT: switch (codec->vendor_id) { case 0x10ec0260: - snd_hda_codec_write(codec, 0x0f, 0, - AC_VERB_SET_EAPD_BTLENABLE, 2); - snd_hda_codec_write(codec, 0x10, 0, - AC_VERB_SET_EAPD_BTLENABLE, 2); + set_eapd(codec, 0x0f, 1); + set_eapd(codec, 0x10, 1); break; case 0x10ec0262: case 0x10ec0267: case 0x10ec0268: case 0x10ec0269: + case 0x10ec0270: case 0x10ec0272: case 0x10ec0660: case 0x10ec0662: case 0x10ec0663: case 0x10ec0862: case 0x10ec0889: - snd_hda_codec_write(codec, 0x14, 0, - AC_VERB_SET_EAPD_BTLENABLE, 2); - snd_hda_codec_write(codec, 0x15, 0, - AC_VERB_SET_EAPD_BTLENABLE, 2); + set_eapd(codec, 0x14, 1); + set_eapd(codec, 0x15, 1); break; } switch (codec->vendor_id) { @@ -1223,6 +1237,8 @@ static void alc_init_auto_mic(struct hda_codec *codec) return; /* invalid entry */ } } + if (!ext || !fixed) + return; if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) return; /* no unsol support */ snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n", @@ -1663,9 +1679,6 @@ static struct hda_verb alc889_acer_aspire_8930g_verbs[] = { /* some bit here disables the other DACs. Init=0x4900 */ {0x20, AC_VERB_SET_COEF_INDEX, 0x08}, {0x20, AC_VERB_SET_PROC_COEF, 0x0000}, -/* Enable amplifiers */ - {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, - {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, /* DMIC fix * This laptop has a stereo digital microphone. The mics are only 1cm apart * which makes the stereo useless. However, either the mic or the ALC889 @@ -1778,6 +1791,25 @@ static struct snd_kcontrol_new alc888_base_mixer[] = { { } /* end */ }; +static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), + HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, + HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), + HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + { } /* end */ +}; + + static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -1808,6 +1840,14 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec) spec->autocfg.speaker_pins[2] = 0x1b; } +#ifdef CONFIG_SND_HDA_POWER_SAVE +static void alc889_power_eapd(struct hda_codec *codec, int power) +{ + set_eapd(codec, 0x14, power); + set_eapd(codec, 0x15, power); +} +#endif + /* * ALC880 3-stack model * @@ -3601,12 +3641,29 @@ static void alc_free(struct hda_codec *codec) snd_hda_detach_beep_device(codec); } +#ifdef CONFIG_SND_HDA_POWER_SAVE +static int alc_suspend(struct hda_codec *codec, pm_message_t state) +{ + struct alc_spec *spec = codec->spec; + if (spec && spec->power_hook) + spec->power_hook(codec, 0); + return 0; +} +#endif + #ifdef SND_HDA_NEEDS_RESUME static int alc_resume(struct hda_codec *codec) { +#ifdef CONFIG_SND_HDA_POWER_SAVE + struct alc_spec *spec = codec->spec; +#endif codec->patch_ops.init(codec); snd_hda_codec_resume_amp(codec); snd_hda_codec_resume_cache(codec); +#ifdef CONFIG_SND_HDA_POWER_SAVE + if (spec && spec->power_hook) + spec->power_hook(codec, 1); +#endif return 0; } #endif @@ -3623,6 +3680,7 @@ static struct hda_codec_ops alc_patch_ops = { .resume = alc_resume, #endif #ifdef CONFIG_SND_HDA_POWER_SAVE + .suspend = alc_suspend, .check_power_status = alc_check_power_status, #endif }; @@ -4761,6 +4819,49 @@ static void fixup_automic_adc(struct hda_codec *codec) spec->auto_mic = 0; /* disable auto-mic to be sure */ } +/* choose the ADC/MUX containing the input pin and initialize the setup */ +static void fixup_single_adc(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t pin; + int i; + + /* search for the input pin; there must be only one */ + for (i = 0; i < AUTO_PIN_LAST; i++) { + if (spec->autocfg.input_pins[i]) { + pin = spec->autocfg.input_pins[i]; + break; + } + } + if (!pin) + return; + + /* set the default connection to that pin */ + for (i = 0; i < spec->num_adc_nids; i++) { + hda_nid_t cap = spec->capsrc_nids ? + spec->capsrc_nids[i] : spec->adc_nids[i]; + int idx; + + idx = get_connection_index(codec, cap, pin); + if (idx < 0) + continue; + /* use only this ADC */ + if (spec->capsrc_nids) + spec->capsrc_nids += i; + spec->adc_nids += i; + spec->num_adc_nids = 1; + /* select or unmute this route */ + if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) { + snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx, + HDA_AMP_MUTE, 0); + } else { + snd_hda_codec_write_cache(codec, cap, 0, + AC_VERB_SET_CONNECT_SEL, idx); + } + return; + } +} + static void set_capture_mixer(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -4773,14 +4874,15 @@ static void set_capture_mixer(struct hda_codec *codec) alc_capture_mixer3 }, }; if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) { - int mux; - if (spec->auto_mic) { - mux = 0; + int mux = 0; + if (spec->auto_mic) fixup_automic_adc(codec); - } else if (spec->input_mux && spec->input_mux->num_items > 1) - mux = 1; - else - mux = 0; + else if (spec->input_mux) { + if (spec->input_mux->num_items > 1) + mux = 1; + else if (spec->input_mux->num_items == 1) + fixup_single_adc(codec); + } spec->cap_mixer = caps[mux][spec->num_adc_nids - 1]; } } @@ -6248,6 +6350,7 @@ static const char *alc260_models[ALC260_MODEL_LAST] = { static struct snd_pci_quirk alc260_cfg_tbl[] = { SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER), + SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL), SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER), SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100), SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013), @@ -7042,8 +7145,8 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = { HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT), HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("HP Playback Volume", 0x0f, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("HP Playback Switch", 0x0f, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT), + HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), @@ -7444,6 +7547,7 @@ static struct hda_verb alc885_mb5_init_verbs[] = { {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, {0x14, AC_VERB_SET_CONNECT_SEL, 0x03}, + {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, /* Front Mic pin: input vref at 80% */ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, @@ -7628,6 +7732,27 @@ static void alc885_mbp3_setup(struct hda_codec *codec) spec->autocfg.speaker_pins[0] = 0x14; } +static void alc885_mb5_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x14, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0, + HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); + snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0, + HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); + +} + +static void alc885_mb5_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + /* Headphone insertion or removal. */ + if ((res >> 26) == ALC880_HP_EVENT) + alc885_mb5_automute(codec); +} + static void alc885_imac91_automute(struct hda_codec *codec) { unsigned int present; @@ -8918,7 +9043,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ - SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC883_TARGA_2ch_DIG), + SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO), SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG), SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG), @@ -9074,6 +9199,8 @@ static struct alc_config_preset alc882_presets[] = { .input_mux = &mb5_capture_source, .dig_out_nid = ALC882_DIGOUT_NID, .dig_in_nid = ALC882_DIGIN_NID, + .unsol_event = alc885_mb5_unsol_event, + .init_hook = alc885_mb5_automute, }, [ALC885_MACPRO] = { .mixers = { alc882_macpro_mixer }, @@ -9281,6 +9408,7 @@ static struct alc_config_preset alc882_presets[] = { .dac_nids = alc883_dac_nids, .adc_nids = alc883_adc_nids_alt, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), + .capsrc_nids = alc883_capsrc_nids, .dig_out_nid = ALC883_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), .channel_mode = alc883_3ST_2ch_modes, @@ -9350,6 +9478,7 @@ static struct alc_config_preset alc882_presets[] = { .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), .channel_mode = alc883_3ST_6ch_modes, .need_dac_fix = 1, + .const_channel_count = 6, .num_mux_defs = ARRAY_SIZE(alc888_2_capture_sources), .input_mux = alc888_2_capture_sources, @@ -9377,10 +9506,11 @@ static struct alc_config_preset alc882_presets[] = { .init_hook = alc_automute_amp, }, [ALC888_ACER_ASPIRE_8930G] = { - .mixers = { alc888_base_mixer, + .mixers = { alc889_acer_aspire_8930g_mixer, alc883_chmode_mixer }, .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs, - alc889_acer_aspire_8930g_verbs }, + alc889_acer_aspire_8930g_verbs, + alc889_eapd_verbs}, .num_dacs = ARRAY_SIZE(alc883_dac_nids), .dac_nids = alc883_dac_nids, .num_adc_nids = ARRAY_SIZE(alc889_adc_nids), @@ -9397,6 +9527,9 @@ static struct alc_config_preset alc882_presets[] = { .unsol_event = alc_automute_amp_unsol_event, .setup = alc889_acer_aspire_8930g_setup, .init_hook = alc_automute_amp, +#ifdef CONFIG_SND_HDA_POWER_SAVE + .power_hook = alc889_power_eapd, +#endif }, [ALC888_ACER_ASPIRE_7730G] = { .mixers = { alc883_3ST_6ch_mixer, @@ -9427,6 +9560,7 @@ static struct alc_config_preset alc882_presets[] = { .dac_nids = alc883_dac_nids, .adc_nids = alc883_adc_nids_alt, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), + .capsrc_nids = alc883_capsrc_nids, .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), .channel_mode = alc883_sixstack_modes, .input_mux = &alc883_capture_source, @@ -9488,6 +9622,7 @@ static struct alc_config_preset alc882_presets[] = { .dac_nids = alc883_dac_nids, .adc_nids = alc883_adc_nids_alt, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt), + .capsrc_nids = alc883_capsrc_nids, .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), .channel_mode = alc883_3ST_2ch_modes, .input_mux = &alc883_lenovo_101e_capture_source, @@ -9667,6 +9802,7 @@ static struct alc_config_preset alc882_presets[] = { alc880_gpio1_init_verbs }, .adc_nids = alc883_adc_nids, .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), + .capsrc_nids = alc883_capsrc_nids, .dac_nids = alc883_dac_nids, .num_dacs = ARRAY_SIZE(alc883_dac_nids), .channel_mode = alc889A_mb31_6ch_modes, @@ -10247,7 +10383,7 @@ static void alc262_hp_t5735_setup(struct hda_codec *codec) struct alc_spec *spec = codec->spec; spec->autocfg.hp_pins[0] = 0x15; - spec->autocfg.speaker_pins[0] = 0x0c; /* HACK: not actually a pin */ + spec->autocfg.speaker_pins[0] = 0x14; } static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = { @@ -10677,6 +10813,13 @@ static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = { {} }; +static struct hda_verb alc262_lenovo_3000_init_verbs[] = { + /* Front Mic pin: input vref at 50% */ + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, + {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {} +}; + static struct hda_input_mux alc262_fujitsu_capture_source = { .num_items = 3, .items = { @@ -11112,7 +11255,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, } #define alc262_auto_create_input_ctls \ - alc880_auto_create_input_ctls + alc882_auto_create_input_ctls /* * generic initialization of ADC, input mixers and output mixers @@ -11651,9 +11794,9 @@ static struct alc_config_preset alc262_presets[] = { .num_channel_mode = ARRAY_SIZE(alc262_modes), .channel_mode = alc262_modes, .input_mux = &alc262_capture_source, - .unsol_event = alc_automute_amp_unsol_event, + .unsol_event = alc_sku_unsol_event, .setup = alc262_hp_t5735_setup, - .init_hook = alc_automute_amp, + .init_hook = alc_inithook, }, [ALC262_HP_RP5700] = { .mixers = { alc262_hp_rp5700_mixer }, @@ -11719,7 +11862,8 @@ static struct alc_config_preset alc262_presets[] = { [ALC262_LENOVO_3000] = { .mixers = { alc262_lenovo_3000_mixer }, .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs, - alc262_lenovo_3000_unsol_verbs }, + alc262_lenovo_3000_unsol_verbs, + alc262_lenovo_3000_init_verbs }, .num_dacs = ARRAY_SIZE(alc262_dac_nids), .dac_nids = alc262_dac_nids, .hp_nid = 0x03, @@ -12403,6 +12547,7 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, dac = 0x02; break; case 0x15: + case 0x21: dac = 0x03; break; default: @@ -12856,7 +13001,7 @@ static int patch_alc268(struct hda_codec *codec) int board_config; int i, has_beep, err; - spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); + spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; @@ -13231,10 +13376,12 @@ static struct hda_verb alc269_eeepc_amic_init_verbs[] = { /* toggle speaker-output according to the hp-jack state */ static void alc269_speaker_automute(struct hda_codec *codec) { + struct alc_spec *spec = codec->spec; + unsigned int nid = spec->autocfg.hp_pins[0]; unsigned int present; unsigned char bits; - present = snd_hda_jack_detect(codec, 0x15); + present = snd_hda_jack_detect(codec, nid); bits = present ? AMP_IN_MUTE(0) : 0; snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, AMP_IN_MUTE(0), bits); @@ -13459,8 +13606,8 @@ static void alc269_auto_init(struct hda_codec *codec) static const char *alc269_models[ALC269_MODEL_LAST] = { [ALC269_BASIC] = "basic", [ALC269_QUANTA_FL1] = "quanta", - [ALC269_ASUS_EEEPC_P703] = "eeepc-p703", - [ALC269_ASUS_EEEPC_P901] = "eeepc-p901", + [ALC269_ASUS_AMIC] = "asus-amic", + [ALC269_ASUS_DMIC] = "asus-dmic", [ALC269_FUJITSU] = "fujitsu", [ALC269_LIFEBOOK] = "lifebook", [ALC269_AUTO] = "auto", @@ -13469,18 +13616,41 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { static struct snd_pci_quirk alc269_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", - ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_EEEPC_P703), - SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_EEEPC_P703), + ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80JT", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_DMIC), + SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_AMIC), + SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", - ALC269_ASUS_EEEPC_P901), + ALC269_ASUS_DMIC), SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", - ALC269_ASUS_EEEPC_P901), - SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_EEEPC_P901), + ALC269_ASUS_DMIC), + SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_ASUS_DMIC), + SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_ASUS_DMIC), SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), {} @@ -13510,7 +13680,7 @@ static struct alc_config_preset alc269_presets[] = { .setup = alc269_quanta_fl1_setup, .init_hook = alc269_quanta_fl1_init_hook, }, - [ALC269_ASUS_EEEPC_P703] = { + [ALC269_ASUS_AMIC] = { .mixers = { alc269_eeepc_mixer }, .cap_mixer = alc269_epc_capture_mixer, .init_verbs = { alc269_init_verbs, @@ -13524,7 +13694,7 @@ static struct alc_config_preset alc269_presets[] = { .setup = alc269_eeepc_amic_setup, .init_hook = alc269_eeepc_inithook, }, - [ALC269_ASUS_EEEPC_P901] = { + [ALC269_ASUS_DMIC] = { .mixers = { alc269_eeepc_mixer }, .cap_mixer = alc269_epc_capture_mixer, .init_verbs = { alc269_init_verbs, @@ -14762,6 +14932,8 @@ static int patch_alc861(struct hda_codec *codec) spec->stream_digital_playback = &alc861_pcm_digital_playback; spec->stream_digital_capture = &alc861_pcm_digital_capture; + if (!spec->cap_mixer) + set_capture_mixer(codec); set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); spec->vmaster_nid = 0x03; @@ -15400,7 +15572,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, 0x15, 0x22, 0); } @@ -16159,6 +16331,52 @@ static struct snd_kcontrol_new alc663_g50v_mixer[] = { { } /* end */ }; +static struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = { + .ops = &snd_hda_bind_sw, + .values = { + HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), + 0 + }, +}; + +static struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = { + .ops = &snd_hda_bind_sw, + .values = { + HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), + 0 + }, +}; + +static struct snd_kcontrol_new alc663_mode7_mixer[] = { + HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch), + HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol), + HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch), + HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), + { } /* end */ +}; + +static struct snd_kcontrol_new alc663_mode8_mixer[] = { + HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch), + HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol), + HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch), + HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), + { } /* end */ +}; + + static struct snd_kcontrol_new alc662_chmode_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -16446,6 +16664,45 @@ static struct hda_verb alc272_dell_init_verbs[] = { {} }; +static struct hda_verb alc663_mode7_init_verbs[] = { + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01}, + {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)}, + {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, + {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {} +}; + +static struct hda_verb alc663_mode8_init_verbs[] = { + {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, + {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */ + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)}, + {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, + {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, + {} +}; + static struct snd_kcontrol_new alc662_auto_capture_mixer[] = { HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT), @@ -16625,6 +16882,54 @@ static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec) } } +static void alc663_two_hp_m7_speaker_automute(struct hda_codec *codec) +{ + unsigned int present1, present2; + + present1 = snd_hda_codec_read(codec, 0x1b, 0, + AC_VERB_GET_PIN_SENSE, 0) + & AC_PINSENSE_PRESENCE; + present2 = snd_hda_codec_read(codec, 0x21, 0, + AC_VERB_GET_PIN_SENSE, 0) + & AC_PINSENSE_PRESENCE; + + if (present1 || present2) { + snd_hda_codec_write_cache(codec, 0x14, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0); + snd_hda_codec_write_cache(codec, 0x17, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0); + } else { + snd_hda_codec_write_cache(codec, 0x14, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + snd_hda_codec_write_cache(codec, 0x17, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + } +} + +static void alc663_two_hp_m8_speaker_automute(struct hda_codec *codec) +{ + unsigned int present1, present2; + + present1 = snd_hda_codec_read(codec, 0x21, 0, + AC_VERB_GET_PIN_SENSE, 0) + & AC_PINSENSE_PRESENCE; + present2 = snd_hda_codec_read(codec, 0x15, 0, + AC_VERB_GET_PIN_SENSE, 0) + & AC_PINSENSE_PRESENCE; + + if (present1 || present2) { + snd_hda_codec_write_cache(codec, 0x14, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0); + snd_hda_codec_write_cache(codec, 0x17, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0); + } else { + snd_hda_codec_write_cache(codec, 0x14, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + snd_hda_codec_write_cache(codec, 0x17, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + } +} + static void alc663_m51va_unsol_event(struct hda_codec *codec, unsigned int res) { @@ -16644,7 +16949,7 @@ static void alc663_m51va_setup(struct hda_codec *codec) spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; - spec->int_mic.mux_idx = 1; + spec->int_mic.mux_idx = 9; spec->auto_mic = 1; } @@ -16656,7 +16961,17 @@ static void alc663_m51va_inithook(struct hda_codec *codec) /* ***************** Mode1 ******************************/ #define alc663_mode1_unsol_event alc663_m51va_unsol_event -#define alc663_mode1_setup alc663_m51va_setup + +static void alc663_mode1_setup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + spec->ext_mic.pin = 0x18; + spec->ext_mic.mux_idx = 0; + spec->int_mic.pin = 0x19; + spec->int_mic.mux_idx = 1; + spec->auto_mic = 1; +} + #define alc663_mode1_inithook alc663_m51va_inithook /* ***************** Mode2 ******************************/ @@ -16673,7 +16988,7 @@ static void alc662_mode2_unsol_event(struct hda_codec *codec, } } -#define alc662_mode2_setup alc663_m51va_setup +#define alc662_mode2_setup alc663_mode1_setup static void alc662_mode2_inithook(struct hda_codec *codec) { @@ -16694,7 +17009,7 @@ static void alc663_mode3_unsol_event(struct hda_codec *codec, } } -#define alc663_mode3_setup alc663_m51va_setup +#define alc663_mode3_setup alc663_mode1_setup static void alc663_mode3_inithook(struct hda_codec *codec) { @@ -16715,7 +17030,7 @@ static void alc663_mode4_unsol_event(struct hda_codec *codec, } } -#define alc663_mode4_setup alc663_m51va_setup +#define alc663_mode4_setup alc663_mode1_setup static void alc663_mode4_inithook(struct hda_codec *codec) { @@ -16736,7 +17051,7 @@ static void alc663_mode5_unsol_event(struct hda_codec *codec, } } -#define alc663_mode5_setup alc663_m51va_setup +#define alc663_mode5_setup alc663_mode1_setup static void alc663_mode5_inithook(struct hda_codec *codec) { @@ -16757,7 +17072,7 @@ static void alc663_mode6_unsol_event(struct hda_codec *codec, } } -#define alc663_mode6_setup alc663_m51va_setup +#define alc663_mode6_setup alc663_mode1_setup static void alc663_mode6_inithook(struct hda_codec *codec) { @@ -16765,6 +17080,50 @@ static void alc663_mode6_inithook(struct hda_codec *codec) alc_mic_automute(codec); } +/* ***************** Mode7 ******************************/ +static void alc663_mode7_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + switch (res >> 26) { + case ALC880_HP_EVENT: + alc663_two_hp_m7_speaker_automute(codec); + break; + case ALC880_MIC_EVENT: + alc_mic_automute(codec); + break; + } +} + +#define alc663_mode7_setup alc663_mode1_setup + +static void alc663_mode7_inithook(struct hda_codec *codec) +{ + alc663_two_hp_m7_speaker_automute(codec); + alc_mic_automute(codec); +} + +/* ***************** Mode8 ******************************/ +static void alc663_mode8_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + switch (res >> 26) { + case ALC880_HP_EVENT: + alc663_two_hp_m8_speaker_automute(codec); + break; + case ALC880_MIC_EVENT: + alc_mic_automute(codec); + break; + } +} + +#define alc663_mode8_setup alc663_m51va_setup + +static void alc663_mode8_inithook(struct hda_codec *codec) +{ + alc663_two_hp_m8_speaker_automute(codec); + alc_mic_automute(codec); +} + static void alc663_g71v_hp_automute(struct hda_codec *codec) { unsigned int present; @@ -16899,6 +17258,8 @@ static const char *alc662_models[ALC662_MODEL_LAST] = { [ALC663_ASUS_MODE4] = "asus-mode4", [ALC663_ASUS_MODE5] = "asus-mode5", [ALC663_ASUS_MODE6] = "asus-mode6", + [ALC663_ASUS_MODE7] = "asus-mode7", + [ALC663_ASUS_MODE8] = "asus-mode8", [ALC272_DELL] = "dell", [ALC272_DELL_ZM1] = "dell-zm1", [ALC272_SAMSUNG_NC10] = "samsung-nc10", @@ -16915,12 +17276,22 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1), + SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7), + SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7), + SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8), + SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3), + SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6), SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6), SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2), + SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA), SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2), @@ -16959,7 +17330,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS), SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K", ALC662_3ST_6ch_DIG), - SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB200", ALC663_ASUS_MODE4), + SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO), SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", ALC662_3ST_6ch_DIG), @@ -17204,6 +17575,36 @@ static struct alc_config_preset alc662_presets[] = { .setup = alc663_mode6_setup, .init_hook = alc663_mode6_inithook, }, + [ALC663_ASUS_MODE7] = { + .mixers = { alc663_mode7_mixer }, + .cap_mixer = alc662_auto_capture_mixer, + .init_verbs = { alc662_init_verbs, + alc663_mode7_init_verbs }, + .num_dacs = ARRAY_SIZE(alc662_dac_nids), + .hp_nid = 0x03, + .dac_nids = alc662_dac_nids, + .dig_out_nid = ALC662_DIGOUT_NID, + .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), + .channel_mode = alc662_3ST_2ch_modes, + .unsol_event = alc663_mode7_unsol_event, + .setup = alc663_mode7_setup, + .init_hook = alc663_mode7_inithook, + }, + [ALC663_ASUS_MODE8] = { + .mixers = { alc663_mode8_mixer }, + .cap_mixer = alc662_auto_capture_mixer, + .init_verbs = { alc662_init_verbs, + alc663_mode8_init_verbs }, + .num_dacs = ARRAY_SIZE(alc662_dac_nids), + .hp_nid = 0x03, + .dac_nids = alc662_dac_nids, + .dig_out_nid = ALC662_DIGOUT_NID, + .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes), + .channel_mode = alc662_3ST_2ch_modes, + .unsol_event = alc663_mode8_unsol_event, + .setup = alc663_mode8_setup, + .init_hook = alc663_mode8_inithook, + }, [ALC272_DELL] = { .mixers = { alc663_m51va_mixer }, .cap_mixer = alc272_auto_capture_mixer, @@ -17687,7 +18088,9 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 }, { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 }, { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 }, + { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 }, { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 }, + { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 6b0bc040c3b1..799ba2570902 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -209,6 +209,7 @@ struct sigmatel_spec { unsigned int gpio_data; unsigned int gpio_mute; unsigned int gpio_led; + unsigned int gpio_led_polarity; /* stream */ unsigned int stream_delay; @@ -1538,6 +1539,13 @@ static unsigned int alienware_m17x_pin_configs[13] = { 0x904601b0, }; +static unsigned int intel_dg45id_pin_configs[14] = { + 0x02214230, 0x02A19240, 0x01013214, 0x01014210, + 0x01A19250, 0x01011212, 0x01016211, 0x40f000f0, + 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x014510A0, + 0x074510B0, 0x40f000f0 +}; + static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, [STAC_DELL_M6_AMIC] = dell_m6_pin_configs, @@ -1545,6 +1553,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { [STAC_DELL_M6_BOTH] = dell_m6_pin_configs, [STAC_DELL_EQ] = dell_m6_pin_configs, [STAC_ALIENWARE_M17X] = alienware_m17x_pin_configs, + [STAC_92HD73XX_INTEL] = intel_dg45id_pin_configs, }; static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { @@ -2095,6 +2104,7 @@ static unsigned int ref9205_pin_configs[12] = { 10280204 1028021F 10280228 (Dell Vostro 1500) + 10280229 (Dell Vostro 1700) */ static unsigned int dell_9205_m42_pin_configs[12] = { 0x0321101F, 0x03A11020, 0x400003FA, 0x90170310, @@ -2180,6 +2190,8 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { "Dell Inspiron", STAC_9205_DELL_M44), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, "Dell Vostro 1500", STAC_9205_DELL_M42), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0229, + "Dell Vostro 1700", STAC_9205_DELL_M42), /* Gateway */ SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD), SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD), @@ -3770,15 +3782,16 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out err = snd_hda_attach_beep_device(codec, nid); if (err < 0) return err; - /* IDT/STAC codecs have linear beep tone parameter */ - codec->beep->linear_tone = 1; - /* if no beep switch is available, make its own one */ - caps = query_amp_caps(codec, nid, HDA_OUTPUT); - if (codec->beep && - !((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT)) { - err = stac92xx_beep_switch_ctl(codec); - if (err < 0) - return err; + if (codec->beep) { + /* IDT/STAC codecs have linear beep tone parameter */ + codec->beep->linear_tone = 1; + /* if no beep switch is available, make its own one */ + caps = query_amp_caps(codec, nid, HDA_OUTPUT); + if (!(caps & AC_AMPCAP_MUTE)) { + err = stac92xx_beep_switch_ctl(codec); + if (err < 0) + return err; + } } } #endif @@ -4440,14 +4453,7 @@ static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) { if (!nid) return 0; - /* NOTE: we can't use snd_hda_jack_detect() here because STAC/IDT - * codecs behave wrongly when SET_PIN_SENSE is triggered, although - * the pincap gives TRIG_REQ bit. - */ - if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0) & - AC_PINSENSE_PRESENCE) - return 1; - return 0; + return snd_hda_jack_detect(codec, nid); } static void stac92xx_line_out_detect(struct hda_codec *codec, @@ -4724,13 +4730,88 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) } } -static int hp_bseries_system(u32 subsystem_id) +static int hp_blike_system(u32 subsystem_id); + +static void set_hp_led_gpio(struct hda_codec *codec) +{ + struct sigmatel_spec *spec = codec->spec; + switch (codec->vendor_id) { + case 0x111d7608: + /* GPIO 0 */ + spec->gpio_led = 0x01; + break; + case 0x111d7600: + case 0x111d7601: + case 0x111d7602: + case 0x111d7603: + /* GPIO 3 */ + spec->gpio_led = 0x08; + break; + } +} + +/* + * This method searches for the mute LED GPIO configuration + * provided as OEM string in SMBIOS. The format of that string + * is HP_Mute_LED_P_G or HP_Mute_LED_P + * where P can be 0 or 1 and defines mute LED GPIO control state (low/high) + * that corresponds to the NOT muted state of the master volume + * and G is the index of the GPIO to use as the mute LED control (0..9) + * If _G portion is missing it is assigned based on the codec ID + * + * So, HP B-series like systems may have HP_Mute_LED_0 (current models) + * or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings + * + * + * The dv-series laptops don't seem to have the HP_Mute_LED* strings in + * SMBIOS - at least the ones I have seen do not have them - which include + * my own system (HP Pavilion dv6-1110ax) and my cousin's + * HP Pavilion dv9500t CTO. + * Need more information on whether it is true across the entire series. + * -- kunal + */ +static int find_mute_led_gpio(struct hda_codec *codec) +{ + struct sigmatel_spec *spec = codec->spec; + const struct dmi_device *dev = NULL; + + if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { + while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, + NULL, dev))) { + if (sscanf(dev->name, "HP_Mute_LED_%d_%d", + &spec->gpio_led_polarity, + &spec->gpio_led) == 2) { + spec->gpio_led = 1 << spec->gpio_led; + return 1; + } + if (sscanf(dev->name, "HP_Mute_LED_%d", + &spec->gpio_led_polarity) == 1) { + set_hp_led_gpio(codec); + return 1; + } + } + + /* + * Fallback case - if we don't find the DMI strings, + * we statically set the GPIO - if not a B-series system. + */ + if (!hp_blike_system(codec->subsystem_id)) { + set_hp_led_gpio(codec); + spec->gpio_led_polarity = 1; + return 1; + } + } + return 0; +} + +static int hp_blike_system(u32 subsystem_id) { switch (subsystem_id) { - case 0x103c307e: - case 0x103c307f: - case 0x103c3080: - case 0x103c3081: + case 0x103c1520: + case 0x103c1521: + case 0x103c1523: + case 0x103c1524: + case 0x103c1525: case 0x103c1722: case 0x103c1723: case 0x103c1724: @@ -4739,6 +4820,14 @@ static int hp_bseries_system(u32 subsystem_id) case 0x103c1727: case 0x103c1728: case 0x103c1729: + case 0x103c172a: + case 0x103c172b: + case 0x103c307e: + case 0x103c307f: + case 0x103c3080: + case 0x103c3081: + case 0x103c7007: + case 0x103c7008: return 1; } return 0; @@ -4833,7 +4922,7 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, else spec->gpio_data |= spec->gpio_led; /* white */ - if (hp_bseries_system(codec->subsystem_id)) { + if (!spec->gpio_led_polarity) { /* LED state is inverted on these systems */ spec->gpio_data ^= spec->gpio_led; } @@ -4893,6 +4982,7 @@ static int patch_stac9200(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; + codec->no_trigger_sense = 1; codec->spec = spec; spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); spec->pin_nids = stac9200_pin_nids; @@ -4955,6 +5045,7 @@ static int patch_stac925x(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; + codec->no_trigger_sense = 1; codec->spec = spec; spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); spec->pin_nids = stac925x_pin_nids; @@ -5039,6 +5130,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; + codec->no_trigger_sense = 1; codec->spec = spec; codec->slave_dig_outs = stac92hd73xx_slave_dig_outs; spec->num_pins = ARRAY_SIZE(stac92hd73xx_pin_nids); @@ -5186,6 +5278,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; + codec->no_trigger_sense = 1; codec->spec = spec; codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; spec->digbeep_nid = 0x21; @@ -5349,6 +5442,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; + codec->no_trigger_sense = 1; codec->spec = spec; codec->patch_ops = stac92xx_patch_ops; spec->num_pins = STAC92HD71BXX_NUM_PINS; @@ -5481,6 +5575,8 @@ again: spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); spec->num_smuxes = stac92hd71bxx_connected_smuxes(codec, 0x1e); + snd_printdd("Found board config: %d\n", spec->board_config); + switch (spec->board_config) { case STAC_HP_M4: /* enable internal microphone */ @@ -5526,7 +5622,7 @@ again: break; } - if (hp_bseries_system(codec->subsystem_id)) { + if (hp_blike_system(codec->subsystem_id)) { pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || @@ -5544,26 +5640,10 @@ again: } } - if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { - const struct dmi_device *dev = NULL; - while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, - NULL, dev))) { - if (strcmp(dev->name, "HP_Mute_LED_1")) { - switch (codec->vendor_id) { - case 0x111d7608: - spec->gpio_led = 0x01; - break; - case 0x111d7600: - case 0x111d7601: - case 0x111d7602: - case 0x111d7603: - spec->gpio_led = 0x08; - break; - } - break; - } - } - } + if (find_mute_led_gpio(codec)) + snd_printd("mute LED gpio %d polarity %d\n", + spec->gpio_led, + spec->gpio_led_polarity); #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { @@ -5608,6 +5688,7 @@ static int patch_stac922x(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; + codec->no_trigger_sense = 1; codec->spec = spec; spec->num_pins = ARRAY_SIZE(stac922x_pin_nids); spec->pin_nids = stac922x_pin_nids; @@ -5711,6 +5792,7 @@ static int patch_stac927x(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; + codec->no_trigger_sense = 1; codec->spec = spec; codec->slave_dig_outs = stac927x_slave_dig_outs; spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); @@ -5845,6 +5927,7 @@ static int patch_stac9205(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; + codec->no_trigger_sense = 1; codec->spec = spec; spec->num_pins = ARRAY_SIZE(stac9205_pin_nids); spec->pin_nids = stac9205_pin_nids; @@ -6000,6 +6083,7 @@ static int patch_stac9872(struct hda_codec *codec) spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) return -ENOMEM; + codec->no_trigger_sense = 1; codec->spec = spec; spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); spec->pin_nids = stac9872_pin_nids; diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index b5ca02e2038c..e66ef2b69b5d 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1058,7 +1058,7 @@ setsamplerate(struct cmdif *cif, unsigned char *intdec, unsigned int rate) rptr.retwords[2] != M && rptr.retwords[3] != N && i++ < MAX_WRITE_RETRY); - if (i == MAX_WRITE_RETRY) { + if (i > MAX_WRITE_RETRY) { snd_printdd("sent samplerate %d: %d failed\n", *intdec, rate); return -EIO; diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 7717e01fc071..edaa729126bb 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -143,7 +143,8 @@ static int snd_pdacf_probe(struct pcmcia_device *link) link->io.NumPorts1 = 16; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_FORCED_PULSE; - // link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + /* FIXME: This driver should be updated to allow for dynamic IRQ sharing */ + /* link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FORCED_PULSE; */ link->irq.Handler = pdacf_interrupt; link->conf.Attributes = CONF_ENABLE_IRQ; diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index d057e6489643..5cfa608823f7 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -51,7 +51,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s return 0; /* already enough large */ vfree(runtime->dma_area); } - runtime->dma_area = vmalloc_32(size); + runtime->dma_area = vmalloc_32_user(size); if (! runtime->dma_area) return -ENOMEM; runtime->dma_bytes = size; diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index 69bd0acc81c8..a1bbe16b7f96 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -102,6 +102,12 @@ static int ac97_soc_probe(struct platform_device *pdev) INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); + ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); + if (ret < 0) { + printk(KERN_ERR "ASoC: failed to init gen ac97 glue\n"); + goto err; + } + /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index b69861d52161..3ef16bbc8c83 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -470,7 +470,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642); static int __init ak4642_modinit(void) { - int ret; + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&ak4642_i2c_driver); #endif diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index bbc72c2ddfca..81b8c9dfe7fc 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -191,6 +191,7 @@ static int ac97_analog_prepare(struct snd_pcm_substream *substream, vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); vra |= 0x1; /* enable variable rate audio */ + vra &= ~0x4; /* disable SPDIF output */ stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); @@ -221,22 +222,6 @@ static int ac97_digital_prepare(struct snd_pcm_substream *substream, return stac9766_ac97_write(codec, reg, runtime->rate); } -static int ac97_digital_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - unsigned short vra; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_STOP: - vra = stac9766_ac97_read(codec, AC97_EXTENDED_STATUS); - vra &= !0x04; - stac9766_ac97_write(codec, AC97_EXTENDED_STATUS, vra); - break; - } - return 0; -} - static int stac9766_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -315,7 +300,6 @@ static struct snd_soc_dai_ops stac9766_dai_ops_analog = { static struct snd_soc_dai_ops stac9766_dai_ops_digital = { .prepare = ac97_digital_prepare, - .trigger = ac97_digital_trigger, }; struct snd_soc_dai stac9766_dai[] = { diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index a9dc5fb54774..da589d8664d0 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -627,7 +627,7 @@ static int tlv320aic23_resume(struct platform_device *pdev) u16 reg; /* Sync reg_cache with the hardware */ - for (reg = 0; reg < TLV320AIC23_RESET; reg++) { + for (reg = 0; reg <= TLV320AIC23_ACTIVE; reg++) { u16 val = tlv320aic23_read_reg_cache(codec, reg); tlv320aic23_write(codec, reg, val); } diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 5f1681f6ca76..2a27f7b56726 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -26,7 +26,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> -#include <linux/i2c/twl4030.h> +#include <linux/i2c/twl.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -175,7 +175,7 @@ static int twl4030_write(struct snd_soc_codec *codec, { twl4030_write_reg_cache(codec, reg, value); if (likely(reg < TWL4030_REG_SW_SHADOW)) - return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, + return twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); else return 0; @@ -261,7 +261,7 @@ static void twl4030_power_up(struct snd_soc_codec *codec) do { /* this takes a little while, so don't slam i2c */ udelay(2000); - twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, TWL4030_REG_ANAMICL); } while ((i++ < 100) && ((byte & TWL4030_CNCL_OFFSET_START) == @@ -542,7 +542,7 @@ static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ break; \ case SND_SOC_DAPM_POST_PMD: \ reg_val = twl4030_read_reg_cache(w->codec, reg); \ - twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ reg_val & (~mask), \ reg); \ break; \ @@ -679,7 +679,7 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / twl4030->sysclk) + 1); /* Bypass the reg_cache to mute the headset */ - twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, hs_gain & (~0x0f), TWL4030_REG_HS_GAIN_SET); diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index f82125d9e85a..718ef912e758 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -925,7 +925,7 @@ static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) iface |= 0x3 << 8; break; case SND_SOC_DAIFMT_DSP_B: - iface |= 0x3 << 8; /* lg not sure which mode */ + iface |= 0x3 << 8 | WM8350_AIF_LRCLK_INV; break; default: return -EINVAL; @@ -1340,9 +1340,10 @@ static int wm8350_resume(struct platform_device *pdev) return 0; } -static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) +static irqreturn_t wm8350_hp_jack_handler(int irq, void *data) { struct wm8350_data *priv = data; + struct wm8350 *wm8350 = priv->codec.control_data; u16 reg; int report; int mask; @@ -1365,7 +1366,7 @@ static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) if (!jack->jack) { dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); - return; + return IRQ_NONE; } /* Debounce */ @@ -1378,6 +1379,8 @@ static void wm8350_hp_jack_handler(struct wm8350 *wm8350, int irq, void *data) report = 0; snd_soc_jack_report(jack->jack, report, jack->report); + + return IRQ_HANDLED; } /** @@ -1421,9 +1424,7 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which, wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena); /* Sync status */ - wm8350_hp_jack_handler(wm8350, irq, priv); - - wm8350_unmask_irq(wm8350, irq); + wm8350_hp_jack_handler(irq, priv); return 0; } @@ -1482,12 +1483,16 @@ static int wm8350_probe(struct platform_device *pdev) wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, WM8350_OUT2_VU | WM8350_OUT2R_MUTE); - wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); - wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); + /* Make sure jack detect is disabled to start off with */ + wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, + WM8350_JDL_ENA | WM8350_JDR_ENA); + wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, - wm8350_hp_jack_handler, priv); + wm8350_hp_jack_handler, 0, "Left jack detect", + priv); wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, - wm8350_hp_jack_handler, priv); + wm8350_hp_jack_handler, 0, "Right jack detect", + priv); ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { @@ -1516,8 +1521,6 @@ static int wm8350_remove(struct platform_device *pdev) WM8350_JDL_ENA | WM8350_JDR_ENA); wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); - wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); - wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 265e68c75df8..af8cb6995a1f 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -424,23 +424,23 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, /* filter coefficient */ switch (params_rate(params)) { - case SNDRV_PCM_RATE_8000: + case 8000: adn |= 0x5 << 1; break; - case SNDRV_PCM_RATE_11025: + case 11025: adn |= 0x4 << 1; break; - case SNDRV_PCM_RATE_16000: + case 16000: adn |= 0x3 << 1; break; - case SNDRV_PCM_RATE_22050: + case 22050: adn |= 0x2 << 1; break; - case SNDRV_PCM_RATE_32000: + case 32000: adn |= 0x1 << 1; break; - case SNDRV_PCM_RATE_44100: - case SNDRV_PCM_RATE_48000: + case 44100: + case 48000: break; } diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index c9438dd62df3..dbc368c08263 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -199,7 +199,7 @@ static void wm8900_reset(struct snd_soc_codec *codec) snd_soc_write(codec, WM8900_REG_RESET, 0); memcpy(codec->reg_cache, wm8900_reg_defaults, - sizeof(codec->reg_cache)); + sizeof(wm8900_reg_defaults)); } static int wm8900_hp_event(struct snd_soc_dapm_widget *w, diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index ce5515e3f2b0..3595bd57c4eb 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1504,7 +1504,7 @@ static int wm8903_resume(struct platform_device *pdev) struct i2c_client *i2c = codec->control_data; int i; u16 *reg_cache = codec->reg_cache; - u16 *tmp_cache = kmemdup(codec->reg_cache, sizeof(wm8903_reg_defaults), + u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), GFP_KERNEL); /* Bring the codec back up to standby first to minimise pop/clicks */ @@ -1516,6 +1516,7 @@ static int wm8903_resume(struct platform_device *pdev) for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++) if (tmp_cache[i] != reg_cache[i]) snd_soc_write(codec, i, tmp_cache[i]); + kfree(tmp_cache); } else { dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); } diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 3d850b97037a..31e39ffd1d8e 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -378,23 +378,23 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, iface |= (1 << 9); switch (params_rate(params)) { - case SNDRV_PCM_RATE_8000: + case 8000: addcntrl |= (0x5 << 1); break; - case SNDRV_PCM_RATE_11025: + case 11025: addcntrl |= (0x4 << 1); break; - case SNDRV_PCM_RATE_16000: + case 16000: addcntrl |= (0x3 << 1); break; - case SNDRV_PCM_RATE_22050: + case 22050: addcntrl |= (0x2 << 1); break; - case SNDRV_PCM_RATE_32000: + case 32000: addcntrl |= (0x1 << 1); break; - case SNDRV_PCM_RATE_44100: - case SNDRV_PCM_RATE_48000: + case 44100: + case 48000: break; } ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl); diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 81c57b5c591c..8812751da8c9 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -47,7 +47,7 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { }; #define WM8974_POWER1_BIASEN 0x08 -#define WM8974_POWER1_BUFIOEN 0x10 +#define WM8974_POWER1_BUFIOEN 0x04 struct wm8974_priv { struct snd_soc_codec codec; @@ -482,23 +482,23 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, /* filter coefficient */ switch (params_rate(params)) { - case SNDRV_PCM_RATE_8000: + case 8000: adn |= 0x5 << 1; break; - case SNDRV_PCM_RATE_11025: + case 11025: adn |= 0x4 << 1; break; - case SNDRV_PCM_RATE_16000: + case 16000: adn |= 0x3 << 1; break; - case SNDRV_PCM_RATE_22050: + case 22050: adn |= 0x2 << 1; break; - case SNDRV_PCM_RATE_32000: + case 32000: adn |= 0x1 << 1; break; - case SNDRV_PCM_RATE_44100: - case SNDRV_PCM_RATE_48000: + case 44100: + case 48000: break; } diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 0ac1215dcd9b..e237bf615129 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -463,7 +463,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, { u16 *cache = codec->reg_cache; - soc_ac97_ops.write(codec->ac97, reg, val); + if (reg < 0x7c) + soc_ac97_ops.write(codec->ac97, reg, val); reg = reg >> 1; if (reg < (ARRAY_SIZE(wm9712_reg))) cache[reg] = val; diff --git a/sound/soc/imx/mx27vis_wm8974.c b/sound/soc/imx/mx27vis_wm8974.c index 0267d2d91685..07d2a248438c 100644 --- a/sound/soc/imx/mx27vis_wm8974.c +++ b/sound/soc/imx/mx27vis_wm8974.c @@ -180,7 +180,8 @@ static int mx27vis_hifi_hw_free(struct snd_pcm_substream *substream) struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; /* disable the PLL */ - return codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, 0, 0); + return codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, IGNORED_ARG, + 0, 0); } /* diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index d49458a29bb7..19283e5edfbf 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile @@ -23,9 +23,9 @@ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o -obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o -obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o -obj-$(CONFIG_MACH_OMAP3517EVM) += snd-soc-am3517evm.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o +obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o +obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c index c071f9603a38..3c85c0f92823 100644 --- a/sound/soc/omap/sdp3430.c +++ b/sound/soc/omap/sdp3430.c @@ -24,7 +24,7 @@ #include <linux/clk.h> #include <linux/platform_device.h> -#include <linux/i2c/twl4030.h> +#include <linux/i2c/twl.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> @@ -321,11 +321,11 @@ static int __init sdp3430_soc_init(void) *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ /* Set TWL4030 GPIO6 as EXTMUTE signal */ - twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, + twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, TWL4030_INTBR_PMBR1); pin_mux &= ~TWL4030_GPIO6_PWM0_MUTE(0x03); pin_mux |= TWL4030_GPIO6_PWM0_MUTE(0x02); - twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux, + twl_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux, TWL4030_INTBR_PMBR1); ret = platform_device_add(sdp3430_snd_device); diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c index d441c3b64631..4984754f3298 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.c +++ b/sound/soc/s3c24xx/s3c24xx_simtec.c @@ -312,7 +312,7 @@ int simtec_audio_resume(struct device *dev) return 0; } -struct dev_pm_ops simtec_audio_pmops = { +const struct dev_pm_ops simtec_audio_pmops = { .resume = simtec_audio_resume, }; EXPORT_SYMBOL_GPL(simtec_audio_pmops); diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.h b/sound/soc/s3c24xx/s3c24xx_simtec.h index 2714203af161..e18faee30cce 100644 --- a/sound/soc/s3c24xx/s3c24xx_simtec.h +++ b/sound/soc/s3c24xx/s3c24xx_simtec.h @@ -15,7 +15,7 @@ extern int simtec_audio_core_probe(struct platform_device *pdev, extern int simtec_audio_remove(struct platform_device *pdev); #ifdef CONFIG_PM -extern struct dev_pm_ops simtec_audio_pmops; +extern const struct dev_pm_ops simtec_audio_pmops; #define simtec_audio_pm &simtec_audio_pmops #else #define simtec_audio_pm NULL diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c index c7af09729c6e..5263ab18f827 100644 --- a/sound/soc/sh/fsi-ak4642.c +++ b/sound/soc/sh/fsi-ak4642.c @@ -42,42 +42,12 @@ static struct snd_soc_device fsi_snd_devdata = { .codec_dev = &soc_codec_dev_ak4642, }; -#define AK4642_BUS 0 -#define AK4642_ADR 0x12 -static int ak4642_add_i2c_device(void) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = AK4642_ADR; - strlcpy(info.type, "ak4642", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(AK4642_BUS); - if (!adapter) { - printk(KERN_DEBUG "can't get i2c adapter\n"); - return -ENODEV; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - printk(KERN_DEBUG "can't add i2c device\n"); - return -ENODEV; - } - - return 0; -} - static struct platform_device *fsi_snd_device; static int __init fsi_ak4642_init(void) { int ret = -ENOMEM; - ak4642_add_i2c_device(); - fsi_snd_device = platform_device_alloc("soc-audio", -1); if (!fsi_snd_device) goto out; diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 9c49c11c43ce..42813b808389 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -876,7 +876,7 @@ static int fsi_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!res || !irq) { + if (!res || (int)irq <= 0) { dev_err(&pdev->dev, "Not enough FSI platform resources.\n"); ret = -ENODEV; goto exit; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ef8f28284cb9..0a6440c6f54a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1236,7 +1236,7 @@ static int soc_poweroff(struct device *dev) return 0; } -static struct dev_pm_ops soc_pm_ops = { +static const struct dev_pm_ops soc_pm_ops = { .suspend = soc_suspend, .resume = soc_resume, .poweroff = soc_poweroff, diff --git a/sound/sound_core.c b/sound/sound_core.c index dbca7c909a31..7c2d677a2df5 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -61,7 +61,7 @@ static void __exit cleanup_soundcore(void) class_destroy(sound_class); } -module_init(init_soundcore); +subsys_initcall(init_soundcore); module_exit(cleanup_soundcore); diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index b074a594c595..9edef4684978 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -752,7 +752,7 @@ static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t s return 0; /* already large enough */ vfree(runtime->dma_area); } - runtime->dma_area = vmalloc(size); + runtime->dma_area = vmalloc_user(size); if (!runtime->dma_area) return -ENOMEM; runtime->dma_bytes = size; @@ -1936,7 +1936,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) struct snd_usb_stream *as = snd_pcm_substream_chip(substream); struct snd_usb_substream *subs = &as->substream[direction]; - if (subs->interface >= 0) { + if (!as->chip->shutdown && subs->interface >= 0) { usb_set_interface(subs->dev, subs->interface, 0); subs->interface = -1; } |