diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-05-03 09:17:01 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-05-03 09:17:01 +0200 |
commit | 53ba4f2fa73225113a488584df0d85d3cba52943 (patch) | |
tree | d85b984d9818abc3ccc0237eb53b710d9e96c39e /sound | |
parent | bd6d29c25bb1a24a4c160ec5de43e0004e01f72b (diff) | |
parent | 66f41d4c5c8a5deed66fdcc84509376c9a0bf9d8 (diff) | |
download | linux-53ba4f2fa73225113a488584df0d85d3cba52943.tar.bz2 |
Merge commit 'v2.6.34-rc6' into core/locking
Diffstat (limited to 'sound')
267 files changed, 2391 insertions, 1590 deletions
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 84bb07d39a7f..91852e49910e 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -33,6 +33,7 @@ */ #include <linux/delay.h> #include <linux/module.h> +#include <linux/slab.h> MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa"); diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index 1dd66ddffcaf..fd2188c3df2b 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -66,6 +66,7 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/mutex.h> +#include <linux/slab.h> MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); MODULE_LICENSE("GPL"); diff --git a/sound/aoa/codecs/toonie.c b/sound/aoa/codecs/toonie.c index f13827e17562..69d2cb601f2a 100644 --- a/sound/aoa/codecs/toonie.c +++ b/sound/aoa/codecs/toonie.c @@ -11,6 +11,7 @@ */ #include <linux/delay.h> #include <linux/module.h> +#include <linux/slab.h> MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("toonie codec driver for snd-aoa"); diff --git a/sound/aoa/core/gpio-pmf.c b/sound/aoa/core/gpio-pmf.c index 1dd0c28d1fb7..6776d1c12b63 100644 --- a/sound/aoa/core/gpio-pmf.c +++ b/sound/aoa/core/gpio-pmf.c @@ -6,6 +6,7 @@ * GPL v2, can be found in COPYING. */ +#include <linux/slab.h> #include <asm/pmac_feature.h> #include <asm/pmac_pfunc.h> #include "../aoa.h" diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index 7a437da05646..1cd9b301df03 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -12,6 +12,7 @@ #include <asm/prom.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/slab.h> #include "../aoa.h" #include "../soundbus/soundbus.h" diff --git a/sound/aoa/soundbus/i2sbus/control.c b/sound/aoa/soundbus/i2sbus/control.c index 87beb4ad4d63..47f854c2001f 100644 --- a/sound/aoa/soundbus/i2sbus/control.c +++ b/sound/aoa/soundbus/i2sbus/control.c @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/delay.h> +#include <linux/slab.h> #include <asm/io.h> #include <asm/prom.h> diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c index 4e3b819d4993..9d6f3b176ed1 100644 --- a/sound/aoa/soundbus/i2sbus/core.c +++ b/sound/aoa/soundbus/i2sbus/core.c @@ -7,6 +7,7 @@ */ #include <linux/module.h> +#include <linux/slab.h> #include <linux/pci.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c index 59bacd365733..be838993926d 100644 --- a/sound/aoa/soundbus/i2sbus/pcm.c +++ b/sound/aoa/soundbus/i2sbus/pcm.c @@ -8,6 +8,7 @@ #include <asm/io.h> #include <linux/delay.h> +#include <linux/slab.h> #include <sound/core.h> #include <asm/macio.h> #include <linux/pci.h> diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 656e474dca47..91acc9a243ec 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c @@ -863,7 +863,6 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci) struct snd_ac97 *ac97; int ret; - writel(0, aaci->base + AC97_POWERDOWN); /* * Assert AACIRESET for 2us */ @@ -1047,7 +1046,11 @@ static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id) writel(0x1fff, aaci->base + AACI_INTCLR); writel(aaci->maincr, aaci->base + AACI_MAINCR); - + /* + * Fix: ac97 read back fail errors by reading + * from any arbitrary aaci register. + */ + readl(aaci->base + AACI_CSCH1); ret = aaci_probe_ac97(aaci); if (ret) goto out; diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 6fdca97186e7..88eec3847df2 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -22,7 +22,6 @@ #include <asm/irq.h> #include <mach/regs-ac97.h> -#include <mach/pxa2xx-gpio.h> #include <mach/audio.h> static DEFINE_MUTEX(car_mutex); @@ -32,6 +31,8 @@ static struct clk *ac97_clk; static struct clk *ac97conf_clk; static int reset_gpio; +extern void pxa27x_assert_ac97reset(int reset_gpio, int on); + /* * Beware PXA27x bugs: * @@ -42,45 +43,6 @@ static int reset_gpio; * 1 jiffy timeout if interrupt never comes). */ -enum { - RESETGPIO_FORCE_HIGH, - RESETGPIO_FORCE_LOW, - RESETGPIO_NORMAL_ALTFUNC -}; - -/** - * set_resetgpio_mode - computes and sets the AC97_RESET gpio mode on PXA - * @mode: chosen action - * - * As the PXA27x CPUs suffer from a AC97 bug, a manual control of the reset line - * must be done to insure proper work of AC97 reset line. This function - * computes the correct gpio_mode for further use by reset functions, and - * applied the change through pxa_gpio_mode. - */ -static void set_resetgpio_mode(int resetgpio_action) -{ - int mode = 0; - - if (reset_gpio) - switch (resetgpio_action) { - case RESETGPIO_NORMAL_ALTFUNC: - if (reset_gpio == 113) - mode = 113 | GPIO_ALT_FN_2_OUT; - if (reset_gpio == 95) - mode = 95 | GPIO_ALT_FN_1_OUT; - break; - case RESETGPIO_FORCE_LOW: - mode = reset_gpio | GPIO_OUT | GPIO_DFLT_LOW; - break; - case RESETGPIO_FORCE_HIGH: - mode = reset_gpio | GPIO_OUT | GPIO_DFLT_HIGH; - break; - }; - - if (mode) - pxa_gpio_mode(mode); -} - unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { unsigned short val = -1; @@ -174,12 +136,11 @@ static inline void pxa_ac97_warm_pxa27x(void) { gsr_bits = 0; - /* warm reset broken on Bulverde, - so manually keep AC97 reset high */ - set_resetgpio_mode(RESETGPIO_FORCE_HIGH); + /* warm reset broken on Bulverde, so manually keep AC97 reset high */ + pxa27x_assert_ac97reset(reset_gpio, 1); udelay(10); GCR |= GCR_WARM_RST; - set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); + pxa27x_assert_ac97reset(reset_gpio, 0); udelay(500); } @@ -345,16 +306,6 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend); int pxa2xx_ac97_hw_resume(void) { - if (cpu_is_pxa25x() || cpu_is_pxa27x()) { - pxa_gpio_mode(GPIO31_SYNC_AC97_MD); - pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); - pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); - pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); - } - if (cpu_is_pxa27x()) { - /* Use GPIO 113 or 95 as AC97 Reset on Bulverde */ - set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); - } clk_enable(ac97_clk); return 0; } @@ -386,16 +337,9 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) reset_gpio = 113; } - if (cpu_is_pxa25x() || cpu_is_pxa27x()) { - pxa_gpio_mode(GPIO31_SYNC_AC97_MD); - pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); - pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); - pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); - } - if (cpu_is_pxa27x()) { /* Use GPIO 113 as AC97 Reset on Bulverde */ - set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); + pxa27x_assert_ac97reset(reset_gpio, 0); ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); if (IS_ERR(ac97conf_clk)) { ret = PTR_ERR(ac97conf_clk); diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c index 743ac6a29065..8808b82311b1 100644 --- a/sound/arm/pxa2xx-pcm-lib.c +++ b/sound/arm/pxa2xx-pcm-lib.c @@ -4,6 +4,7 @@ * published by the Free Software Foundation. */ +#include <linux/slab.h> #include <linux/module.h> #include <linux/dma-mapping.h> @@ -205,6 +206,7 @@ int __pxa2xx_pcm_open(struct snd_pcm_substream *substream) if (!rtd->dma_desc_array) goto err1; + rtd->dma_ch = -1; runtime->private_data = rtd; return 0; diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 368dc9c4aef8..426874429a5e 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -21,6 +21,7 @@ /* this file included from control.c */ #include <linux/compat.h> +#include <linux/slab.h> struct snd_ctl_elem_list32 { u32 offset; diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c index 7f4d744ae40a..7730575bfadd 100644 --- a/sound/core/hrtimer.c +++ b/sound/core/hrtimer.c @@ -19,6 +19,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/hrtimer.h> diff --git a/sound/core/info.c b/sound/core/info.c index d749a0d394a7..cc4a53d4b7f8 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -22,6 +22,7 @@ #include <linux/init.h> #include <linux/time.h> #include <linux/mm.h> +#include <linux/slab.h> #include <linux/smp_lock.h> #include <linux/string.h> #include <sound/core.h> diff --git a/sound/core/jack.c b/sound/core/jack.c index f705eec7372a..14b8a4ee690d 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -20,6 +20,7 @@ */ #include <linux/input.h> +#include <linux/slab.h> #include <sound/jack.h> #include <sound/core.h> diff --git a/sound/core/misc.c b/sound/core/misc.c index 3da4f92427d8..2c41825c836e 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/time.h> +#include <linux/slab.h> #include <linux/ioport.h> #include <sound/core.h> diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c index 0dcc2870d537..bbe25d8c450a 100644 --- a/sound/core/oss/route.c +++ b/sound/core/oss/route.c @@ -19,7 +19,6 @@ * */ -#include <linux/slab.h> #include <linux/time.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 08bfed594a83..5fb2e28e796f 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -21,6 +21,7 @@ /* This file included from pcm_native.c */ #include <linux/compat.h> +#include <linux/slab.h> static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream, s32 __user *src) diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index b546ac2660f9..a2ff86189d2a 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -148,6 +148,9 @@ static void pcm_debug_name(struct snd_pcm_substream *substream, #define xrun_debug(substream, mask) \ ((substream)->pstr->xrun_debug & (mask)) +#else +#define xrun_debug(substream, mask) 0 +#endif #define dump_stack_on_xrun(substream) do { \ if (xrun_debug(substream, XRUN_DEBUG_STACK)) \ @@ -169,6 +172,7 @@ static void xrun(struct snd_pcm_substream *substream) } } +#ifdef CONFIG_SND_PCM_XRUN_DEBUG #define hw_ptr_error(substream, fmt, args...) \ do { \ if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { \ @@ -255,8 +259,6 @@ static void xrun_log_show(struct snd_pcm_substream *substream) #else /* ! CONFIG_SND_PCM_XRUN_DEBUG */ -#define xrun_debug(substream, mask) 0 -#define xrun(substream) do { } while (0) #define hw_ptr_error(substream, fmt, args...) do { } while (0) #define xrun_log(substream, pos) do { } while (0) #define xrun_log_show(substream) do { } while (0) diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index d6d49d6651f9..917e4055ee30 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -22,6 +22,7 @@ #include <asm/io.h> #include <linux/time.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/vmalloc.h> #include <sound/core.h> diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c index d0d721c22eac..685712276ac9 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c @@ -29,6 +29,7 @@ #include "seq_oss_event.h" #include <linux/init.h> #include <linux/moduleparam.h> +#include <linux/slab.h> /* * common variables diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c index 9dfb2f77be60..677dc84590c7 100644 --- a/sound/core/seq/oss/seq_oss_midi.c +++ b/sound/core/seq/oss/seq_oss_midi.c @@ -28,6 +28,7 @@ #include <sound/seq_midi_event.h> #include "../seq_lock.h" #include <linux/init.h> +#include <linux/slab.h> /* diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c index f5de79f29f1e..73661c4ab82a 100644 --- a/sound/core/seq/oss/seq_oss_readq.c +++ b/sound/core/seq/oss/seq_oss_readq.c @@ -25,6 +25,7 @@ #include <sound/seq_oss_legacy.h> #include "../seq_lock.h" #include <linux/wait.h> +#include <linux/slab.h> /* * constants diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index 945a27c34a9d..ee44ab9593c0 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c @@ -24,6 +24,7 @@ #include "seq_oss_midi.h" #include "../seq_lock.h" #include <linux/init.h> +#include <linux/slab.h> /* * constants diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c index c440fdacec93..ab59cbfbcaf2 100644 --- a/sound/core/seq/oss/seq_oss_timer.c +++ b/sound/core/seq/oss/seq_oss_timer.c @@ -23,6 +23,7 @@ #include "seq_oss_timer.h" #include "seq_oss_event.h" #include <sound/seq_oss_legacy.h> +#include <linux/slab.h> /* */ diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c index 217424858191..d50338bbc21f 100644 --- a/sound/core/seq/oss/seq_oss_writeq.c +++ b/sound/core/seq/oss/seq_oss_writeq.c @@ -27,6 +27,7 @@ #include "../seq_lock.h" #include "../seq_clientmgr.h" #include <linux/wait.h> +#include <linux/slab.h> /* diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c index c956fe462569..81f7c109dc46 100644 --- a/sound/core/seq/seq_compat.c +++ b/sound/core/seq/seq_compat.c @@ -21,6 +21,7 @@ /* This file included from seq.c */ #include <linux/compat.h> +#include <linux/slab.h> struct snd_seq_port_info32 { struct snd_seq_addr addr; /* client/port numbers */ diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c index 77884e62b648..c38b90cf3cb0 100644 --- a/sound/core/seq/seq_system.c +++ b/sound/core/seq/seq_system.c @@ -20,6 +20,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <sound/core.h> #include "seq_system.h" #include "seq_timer.h" diff --git a/sound/core/timer.c b/sound/core/timer.c index 8f8b17ac074d..73943651caed 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -393,7 +393,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) event == SNDRV_TIMER_EVENT_CONTINUE) resolution = snd_timer_resolution(ti); if (ti->ccallback) - ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution); + ti->ccallback(ti, event, &tstamp, resolution); if (ti->flags & SNDRV_TIMER_IFLG_SLAVE) return; timer = ti->timer; diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c index 1950ffce2b54..a1282c1c0591 100644 --- a/sound/drivers/ml403-ac97cr.c +++ b/sound/drivers/ml403-ac97cr.c @@ -39,6 +39,7 @@ #include <linux/platform_device.h> #include <linux/ioport.h> +#include <linux/slab.h> #include <linux/io.h> #include <linux/interrupt.h> diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index 2f8f295d6b0c..da03597fc893 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c @@ -54,7 +54,6 @@ #include <linux/interrupt.h> #include <linux/err.h> #include <linux/platform_device.h> -#include <linux/slab.h> #include <linux/ioport.h> #include <linux/moduleparam.h> #include <sound/core.h> diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c index 9284829bf927..8539ab0a0893 100644 --- a/sound/drivers/mts64.c +++ b/sound/drivers/mts64.c @@ -23,6 +23,7 @@ #include <linux/parport.h> #include <linux/spinlock.h> #include <linux/delay.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/initval.h> #include <sound/rawmidi.h> diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index a54b1dc5cc78..ade3ca52422e 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -19,7 +19,6 @@ */ #include "opl3_voice.h" -#include <linux/slab.h> static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure); static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg); diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index 6d57b6441dec..301acb6b9cf9 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c @@ -19,6 +19,7 @@ * */ +#include <linux/slab.h> #include <sound/opl3.h> #include <sound/asound_fm.h> diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index 01997f24c895..f07e38da59b8 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c @@ -20,6 +20,7 @@ #include "opl4_local.h" #include <sound/initval.h> #include <linux/ioport.h> +#include <linux/slab.h> #include <linux/init.h> #include <asm/io.h> diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index f6a2e72b8cde..ce9e7d170c0d 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -7,6 +7,7 @@ */ #include <linux/module.h> +#include <linux/gfp.h> #include <linux/moduleparam.h> #include <linux/interrupt.h> #include <sound/pcm.h> diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index 60158e2e0eaf..f2b0ba22d9ce 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c @@ -42,6 +42,7 @@ #include <linux/parport.h> #include <linux/spinlock.h> #include <linux/delay.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/initval.h> #include <sound/rawmidi.h> diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c index 46df8817c18f..f7a6fbd313e3 100644 --- a/sound/drivers/vx/vx_hwdep.c +++ b/sound/drivers/vx/vx_hwdep.c @@ -22,6 +22,7 @@ #include <linux/device.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <linux/vmalloc.h> #include <sound/core.h> #include <sound/hwdep.h> diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index fff62cc8607c..971a84a4fa77 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c @@ -70,7 +70,7 @@ static int snd_ak4113_dev_free(struct snd_device *device) } int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read, - ak4113_write_t *write, const unsigned char pgm[5], + ak4113_write_t *write, const unsigned char *pgm, void *private_data, struct ak4113 **r_ak4113) { struct ak4113 *chip; diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index c4c6ef73f9bf..ee538f1ae846 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c @@ -24,6 +24,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/version.h> #include <sound/core.h> #include <sound/tea575x-tuner.h> diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 8246aae32ab4..fe79a169acb5 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -46,7 +46,6 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/isa.h> -#include <linux/slab.h> #include <linux/pnp.h> #include <linux/moduleparam.h> #include <sound/core.h> diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index cc15d1d65a22..999dc1e0fdbd 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c @@ -22,7 +22,6 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/isa.h> -#include <linux/slab.h> #include <linux/pnp.h> #include <linux/moduleparam.h> #include <sound/core.h> diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 9a43baae7250..fb4d6b34bbca 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -80,7 +80,6 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/isa.h> -#include <linux/slab.h> #include <linux/pnp.h> #include <linux/isapnp.h> #include <linux/moduleparam.h> diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 534a6eced2b8..c7b80e4730fc 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c @@ -26,7 +26,6 @@ #include <linux/err.h> #include <linux/isa.h> #include <linux/delay.h> -#include <linux/slab.h> #include <linux/pnp.h> #include <linux/moduleparam.h> #include <asm/dma.h> diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c index 4be562b2cf21..787495674235 100644 --- a/sound/isa/msnd/msnd_midi.c +++ b/sound/isa/msnd/msnd_midi.c @@ -25,6 +25,7 @@ */ #include <linux/io.h> +#include <linux/slab.h> #include <linux/delay.h> #include <linux/ioport.h> #include <linux/errno.h> diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 0481a55334b9..265abcce9dba 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c @@ -24,7 +24,6 @@ #include <linux/isa.h> #include <linux/interrupt.h> #include <linux/pm.h> -#include <linux/slab.h> #include <linux/pnp.h> #include <linux/moduleparam.h> #include <sound/core.h> diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index b865e45a8f9b..8c24102d0d93 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -27,7 +27,6 @@ #include <linux/isa.h> #include <linux/pnp.h> #include <linux/delay.h> -#include <linux/slab.h> #include <linux/ioport.h> #include <linux/moduleparam.h> #include <asm/io.h> @@ -1558,7 +1557,7 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip, err = pnp_activate_dev(devmc); if (err < 0) { - snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n", + snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); return err; } diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index a4af53b5c1cf..c35dc68930dc 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -27,7 +27,6 @@ #include <linux/err.h> #include <linux/isa.h> #include <linux/delay.h> -#include <linux/slab.h> #include <linux/pnp.h> #include <linux/moduleparam.h> #include <asm/io.h> @@ -144,12 +143,8 @@ struct snd_opti9xx { spinlock_t lock; + long wss_base; int irq; - -#ifdef CONFIG_PNP - struct pnp_dev *dev; - struct pnp_dev *devmpu; -#endif /* CONFIG_PNP */ }; static int snd_opti9xx_pnp_is_probed; @@ -159,12 +154,17 @@ static int snd_opti9xx_pnp_is_probed; static struct pnp_card_device_id snd_opti9xx_pnpids[] = { #ifndef OPTi93X /* OPTi 82C924 */ - { .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 }, + { .id = "OPT0924", + .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } }, + .driver_data = 0x0924 }, /* OPTi 82C925 */ - { .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 }, + { .id = "OPT0925", + .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } }, + .driver_data = 0x0925 }, #else /* OPTi 82C931/3 */ - { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 }, + { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, + .driver_data = 0x0931 }, #endif /* OPTi93X */ { .id = "" } }; @@ -207,24 +207,35 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, chip->hardware = hardware; strcpy(chip->name, snd_opti9xx_names[hardware]); - chip->mc_base_size = opti9xx_mc_size[hardware]; - spin_lock_init(&chip->lock); chip->irq = -1; +#ifndef OPTi93X +#ifdef CONFIG_PNP + if (isapnp && chip->mc_base) + /* PnP resource gives the least 10 bits */ + chip->mc_base |= 0xc00; + else +#endif /* CONFIG_PNP */ + { + chip->mc_base = 0xf8c; + chip->mc_base_size = opti9xx_mc_size[hardware]; + } +#else + chip->mc_base_size = opti9xx_mc_size[hardware]; +#endif + switch (hardware) { #ifndef OPTi93X case OPTi9XX_HW_82C928: case OPTi9XX_HW_82C929: - chip->mc_base = 0xf8c; chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3; chip->pwd_reg = 3; break; case OPTi9XX_HW_82C924: case OPTi9XX_HW_82C925: - chip->mc_base = 0xf8c; chip->password = 0xe5; chip->pwd_reg = 3; break; @@ -292,7 +303,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip, spin_unlock_irqrestore(&chip->lock, flags); return retval; } - + static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, unsigned char value) { @@ -341,7 +352,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg, static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, - long wss_base, + long port, int irq, int dma1, int dma2, long mpu_port, int mpu_irq) { @@ -354,16 +365,23 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, switch (chip->hardware) { #ifndef OPTi93X case OPTi9XX_HW_82C924: + /* opti 929 mode (?), OPL3 clock output, audio enable */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); + /* enable wave audio */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); case OPTi9XX_HW_82C925: + /* enable WSS mode */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); + /* OPL3 FM synthesis */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); + /* disable Sound Blaster IRQ and DMA */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff); #ifdef CS4231 + /* cs4231/4248 fix enabled */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02); #else + /* cs4231/4248 fix disabled */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02); #endif /* CS4231 */ break; @@ -411,21 +429,26 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, return -EINVAL; } - switch (wss_base) { - case 0x530: + /* PnP resource says it decodes only 10 bits of address */ + switch (port & 0x3ff) { + case 0x130: + chip->wss_base = 0x530; wss_base_bits = 0x00; break; - case 0x604: + case 0x204: + chip->wss_base = 0x604; wss_base_bits = 0x03; break; - case 0xe80: + case 0x280: + chip->wss_base = 0xe80; wss_base_bits = 0x01; break; - case 0xf40: + case 0x340: + chip->wss_base = 0xf40; wss_base_bits = 0x02; break; default: - snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base); + snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port); goto __skip_base; } snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30); @@ -487,7 +510,7 @@ __skip_base: #endif /* CS4231 || OPTi93X */ #ifndef OPTi93X - outb(irq_bits << 3 | dma_bits, wss_base); + outb(irq_bits << 3 | dma_bits, chip->wss_base); #else /* OPTi93X */ snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits)); #endif /* OPTi93X */ @@ -729,15 +752,15 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, { struct pnp_dev *pdev; int err; + struct pnp_dev *devmpu; +#ifndef OPTi93X + struct pnp_dev *devmc; +#endif - chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL); - if (chip->dev == NULL) + pdev = pnp_request_card_device(card, pid->devs[0].id, NULL); + if (pdev == NULL) return -EBUSY; - chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); - - pdev = chip->dev; - err = pnp_activate_dev(pdev); if (err < 0) { snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err); @@ -750,9 +773,24 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, chip->mc_indir_index = pnp_port_start(pdev, 3) + 2; chip->mc_indir_size = pnp_port_len(pdev, 3) - 2; #else - if (pid->driver_data != 0x0924) - port = pnp_port_start(pdev, 1); + devmc = pnp_request_card_device(card, pid->devs[2].id, NULL); + if (devmc == NULL) + return -EBUSY; + + err = pnp_activate_dev(devmc); + if (err < 0) { + snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err); + return err; + } + + port = pnp_port_start(pdev, 1); fm_port = pnp_port_start(pdev, 2) + 8; + /* + * The MC(0) is never accessed and card does not + * include it in the PnP resource range. OPTI93x include it. + */ + chip->mc_base = pnp_port_start(devmc, 0) - 1; + chip->mc_base_size = pnp_port_len(devmc, 0) + 1; #endif /* OPTi93X */ irq = pnp_irq(pdev, 0); dma1 = pnp_dma(pdev, 0); @@ -760,16 +798,16 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip, dma2 = pnp_dma(pdev, 1); #endif /* CS4231 || OPTi93X */ - pdev = chip->devmpu; - if (pdev && mpu_port > 0) { - err = pnp_activate_dev(pdev); + devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL); + + if (devmpu && mpu_port > 0) { + err = pnp_activate_dev(devmpu); if (err < 0) { - snd_printk(KERN_ERR "AUDIO pnp configure failure\n"); + snd_printk(KERN_ERR "MPU401 pnp configure failure\n"); mpu_port = -1; - chip->devmpu = NULL; } else { - mpu_port = pnp_port_start(pdev, 0); - mpu_irq = pnp_irq(pdev, 0); + mpu_port = pnp_port_start(devmpu, 0); + mpu_irq = pnp_irq(devmpu, 0); } } return pid->driver_data; @@ -824,7 +862,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) if (error) return error; - error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2, + error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2, #ifdef OPTi93X WSS_HW_OPTI93X, WSS_HWSHARE_IRQ, #else @@ -865,10 +903,11 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) sprintf(card->shortname, "OPTi %s", card->driver); #if defined(CS4231) || defined(OPTi93X) sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d", - card->shortname, pcm->name, port + 4, irq, dma1, xdma2); + card->shortname, pcm->name, + chip->wss_base + 4, irq, dma1, xdma2); #else sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d", - card->shortname, pcm->name, port + 4, irq, dma1); + card->shortname, pcm->name, chip->wss_base + 4, irq, dma1); #endif /* CS4231 || OPTi93X */ if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) @@ -1062,9 +1101,6 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard, snd_card_free(card); return error; } - if (hw <= OPTi9XX_HW_82C930) - chip->mc_base -= 0x80; - error = snd_opti9xx_read_check(chip); if (error) { snd_printk(KERN_ERR "OPTI chip not found\n"); diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index 91dc3d83e2cf..ccedbfed061a 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -20,6 +20,7 @@ #include "emu8000_local.h" #include <linux/init.h> +#include <linux/slab.h> #include <sound/initval.h> #include <sound/pcm.h> diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c index 8d21a3feda3a..8ccbcddf08e1 100644 --- a/sound/isa/sb/jazz16.c +++ b/sound/isa/sb/jazz16.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/io.h> +#include <linux/delay.h> #include <asm/dma.h> #include <linux/isa.h> #include <sound/core.h> diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 519c36346dec..4d1c5a300ff8 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -21,7 +21,6 @@ #include <asm/dma.h> #include <linux/init.h> -#include <linux/slab.h> #include <linux/pnp.h> #include <linux/err.h> #include <linux/isa.h> diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index 3cd57ee54660..81284a8fa0ce 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c @@ -22,7 +22,6 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/isa.h> -#include <linux/slab.h> #include <linux/ioport.h> #include <linux/moduleparam.h> #include <sound/core.h> diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index a34ae7b1f7d0..711670e4a425 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c @@ -21,7 +21,6 @@ #include <linux/init.h> #include <linux/interrupt.h> -#include <linux/slab.h> #include <linux/err.h> #include <linux/isa.h> #include <linux/pnp.h> diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c index 2bb1cee09255..657e2d6c01ac 100644 --- a/sound/isa/wavefront/wavefront_fx.c +++ b/sound/isa/wavefront/wavefront_fx.c @@ -20,6 +20,7 @@ #include <linux/init.h> #include <linux/time.h> #include <linux/wait.h> +#include <linux/slab.h> #include <linux/firmware.h> #include <sound/core.h> #include <sound/snd_wavefront.h> diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 5d4ff48c4345..4fb7b19ff393 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -28,6 +28,7 @@ #include <linux/wait.h> #include <linux/firmware.h> #include <linux/moduleparam.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/snd_wavefront.h> #include <sound/initval.h> diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index 9a88cdfd952a..453d343550a8 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c @@ -25,6 +25,7 @@ #include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/slab.h> #include <asm/sgi/hpc3.h> #include <asm/sgi/ip22.h> diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index 6aff217379d9..717604c00f0a 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -25,11 +25,11 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/spinlock.h> -#include <linux/gfp.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/slab.h> #include <asm/ip32/ip32_ints.h> #include <asm/ip32/mace.h> diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index d12bd98a37ba..24793c5b65ac 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c @@ -45,6 +45,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/stddef.h> +#include <linux/slab.h> #include <linux/isapnp.h> #include <linux/pnp.h> #include <linux/spinlock.h> diff --git a/sound/oss/coproc.h b/sound/oss/coproc.h index 7306346e9ac4..7bec21bbdd88 100644 --- a/sound/oss/coproc.h +++ b/sound/oss/coproc.h @@ -4,7 +4,7 @@ */ /* - * Coprocessor access types + * Coprocessor access types */ #define COPR_CUSTOM 0x0001 /* Custom applications */ #define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */ diff --git a/sound/oss/dmabuf.c b/sound/oss/dmabuf.c index 1bfcf7e88546..bcc3e8e07122 100644 --- a/sound/oss/dmabuf.c +++ b/sound/oss/dmabuf.c @@ -26,6 +26,7 @@ #define SAMPLE_ROUNDUP 0 #include <linux/mm.h> +#include <linux/gfp.h> #include "sound_config.h" #define DMAP_FREE_ON_CLOSE 0 diff --git a/sound/oss/kahlua.c b/sound/oss/kahlua.c index 24d152ccf80d..52d06a334e8f 100644 --- a/sound/oss/kahlua.c +++ b/sound/oss/kahlua.c @@ -31,6 +31,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/slab.h> #include "sound_config.h" diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c index 0af9d24feb8f..25e4609f8339 100644 --- a/sound/oss/mpu401.c +++ b/sound/oss/mpu401.c @@ -19,6 +19,7 @@ */ #include <linux/module.h> +#include <linux/slab.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/spinlock.h> diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c index 21eb6dce46df..c0cc951ba97d 100644 --- a/sound/oss/msnd.c +++ b/sound/oss/msnd.c @@ -24,7 +24,6 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/slab.h> #include <linux/vmalloc.h> #include <linux/types.h> #include <linux/delay.h> diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c index bf27e008f465..a1e3f9671bea 100644 --- a/sound/oss/msnd_pinnacle.c +++ b/sound/oss/msnd_pinnacle.c @@ -35,12 +35,12 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/slab.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/smp_lock.h> +#include <linux/gfp.h> #include <asm/irq.h> #include <asm/io.h> #include "sound_config.h" diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c index 7781c13c1476..938c48c43585 100644 --- a/sound/oss/opl3.c +++ b/sound/oss/opl3.c @@ -24,6 +24,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/delay.h> diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c index 7de18b58f2cd..84ef4d06c1c2 100644 --- a/sound/oss/sb_card.c +++ b/sound/oss/sb_card.c @@ -24,6 +24,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/slab.h> #include <linux/init.h> #include "sound_config.h" #include "sb_mixer.h" diff --git a/sound/oss/sb_common.c b/sound/oss/sb_common.c index ce4db49291f7..7d42c5418d1b 100644 --- a/sound/oss/sb_common.c +++ b/sound/oss/sb_common.c @@ -31,6 +31,7 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/spinlock.h> +#include <linux/slab.h> #include "sound_config.h" #include "sound_firmware.h" diff --git a/sound/oss/sb_midi.c b/sound/oss/sb_midi.c index 8b796704e112..f139028e85c0 100644 --- a/sound/oss/sb_midi.c +++ b/sound/oss/sb_midi.c @@ -12,6 +12,7 @@ */ #include <linux/spinlock.h> +#include <linux/slab.h> #include "sound_config.h" diff --git a/sound/oss/sb_mixer.c b/sound/oss/sb_mixer.c index fad1a4f25ad6..2039d31b7e22 100644 --- a/sound/oss/sb_mixer.c +++ b/sound/oss/sb_mixer.c @@ -16,6 +16,8 @@ * Stanislav Voronyi <stas@esc.kharkov.com> : Support for AWE 3DSE device (Jun 7 1999) */ +#include <linux/slab.h> + #include "sound_config.h" #define __SB_MIXER_C__ diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c index c79874696bec..e85789e53816 100644 --- a/sound/oss/sequencer.c +++ b/sound/oss/sequencer.c @@ -1631,8 +1631,6 @@ unsigned long compute_finetune(unsigned long base_freq, int bend, int range, } semitones = bend / 100; - if (semitones > 99) - semitones = 99; cents = bend % 100; amount = (int) (semitone_tuning[semitones] * multiplier * cent_tuning[cents]) / 10000; diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index fde7c12fe5da..2d9c51312622 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -36,7 +36,6 @@ #include <asm/dma.h> #include <asm/io.h> #include <linux/wait.h> -#include <linux/slab.h> #include <linux/ioport.h> #include <linux/major.h> #include <linux/delay.h> diff --git a/sound/oss/uart401.c b/sound/oss/uart401.c index a446b826d5fc..8e514a676a0d 100644 --- a/sound/oss/uart401.c +++ b/sound/oss/uart401.c @@ -24,6 +24,7 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/spinlock.h> #include "sound_config.h" diff --git a/sound/oss/v_midi.c b/sound/oss/v_midi.c index 103940fd5b4f..f0b4151d9b17 100644 --- a/sound/oss/v_midi.c +++ b/sound/oss/v_midi.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/spinlock.h> #include "sound_config.h" diff --git a/sound/oss/v_midi.h b/sound/oss/v_midi.h index 1b86cb45c607..08e2185ee816 100644 --- a/sound/oss/v_midi.h +++ b/sound/oss/v_midi.h @@ -2,9 +2,9 @@ typedef struct vmidi_devc { int dev; /* State variables */ - int opened; + int opened; spinlock_t lock; - + /* MIDI fields */ int my_mididev; int pair_mididev; @@ -12,4 +12,3 @@ typedef struct vmidi_devc { int intr_active; void (*midi_input_intr) (int dev, unsigned char data); } vmidi_devc; - diff --git a/sound/oss/vidc.c b/sound/oss/vidc.c index 725fef0f59a3..ac39a531df19 100644 --- a/sound/oss/vidc.c +++ b/sound/oss/vidc.c @@ -17,6 +17,7 @@ * We currently support a mixer device, but it is currently non-functional. */ +#include <linux/gfp.h> #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> @@ -363,13 +364,13 @@ static void vidc_audio_trigger(int dev, int enable_bits) struct audio_operations *adev = audio_devs[dev]; if (enable_bits & PCM_ENABLE_OUTPUT) { - if (!(adev->flags & DMA_ACTIVE)) { + if (!(adev->dmap_out->flags & DMA_ACTIVE)) { unsigned long flags; local_irq_save(flags); /* prevent recusion */ - adev->flags |= DMA_ACTIVE; + adev->dmap_out->flags |= DMA_ACTIVE; dma_interrupt = vidc_audio_dma_interrupt; vidc_sound_dma_irq(0, NULL); diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c index 6713110bdc75..20b3b325aa80 100644 --- a/sound/oss/vwsnd.c +++ b/sound/oss/vwsnd.c @@ -149,6 +149,7 @@ #include <linux/wait.h> #include <linux/interrupt.h> #include <linux/mutex.h> +#include <linux/slab.h> #include <asm/visws/cobalt.h> diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c index 2c63bb9da74a..e688dde6bbde 100644 --- a/sound/oss/waveartist.c +++ b/sound/oss/waveartist.c @@ -35,6 +35,7 @@ #include <linux/module.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/delay.h> diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 1caf5e3c1f6a..e68c98ef4041 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c @@ -1852,12 +1852,14 @@ static unsigned int ad1981_jacks_blacklist[] = { 0x10140523, /* Thinkpad R40 */ 0x10140534, /* Thinkpad X31 */ 0x10140537, /* Thinkpad T41p */ + 0x1014053e, /* Thinkpad R40e */ 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 */ + 0x1179ff10, /* Toshiba P500 */ 0x144dc01a, /* Samsung NP-X20C004/SEG */ 0 /* end */ }; diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 73b17d526c8b..6320bf084e47 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c @@ -22,7 +22,6 @@ * */ -#include <linux/slab.h> #include <linux/mutex.h> #include <sound/core.h> diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index d75cf7b06426..6cf1de8042e8 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c @@ -68,7 +68,6 @@ #include <asm/io.h> #include <linux/init.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/gameport.h> #include <linux/moduleparam.h> #include <linux/dma-mapping.h> diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c index 296123ab74f7..8afd8b5d1ac7 100644 --- a/sound/pci/aw2/aw2-saa7146.c +++ b/sound/pci/aw2/aw2-saa7146.c @@ -25,7 +25,6 @@ #include <linux/init.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/interrupt.h> #include <linux/delay.h> #include <asm/system.h> diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 8f443a9d61ec..85fd315d9999 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -63,7 +63,6 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/interrupt.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <sound/core.h> #include <sound/initval.h> diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index 0470461cc03e..ba96428c9f4c 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c @@ -63,7 +63,6 @@ #include <linux/delay.h> #include <linux/init.h> #include <linux/interrupt.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <sound/core.h> #include <sound/initval.h> diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 1ded64e05643..329968edca9b 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -941,13 +941,21 @@ static snd_pcm_uframes_t snd_cmipci_pcm_pointer(struct cmipci *cm, struct cmipci struct snd_pcm_substream *substream) { size_t ptr; - unsigned int reg; + unsigned int reg, rem, tries; + if (!rec->running) return 0; #if 1 // this seems better.. reg = rec->ch ? CM_REG_CH1_FRAME2 : CM_REG_CH0_FRAME2; - ptr = rec->dma_size - (snd_cmipci_read_w(cm, reg) + 1); - ptr >>= rec->shift; + for (tries = 0; tries < 3; tries++) { + rem = snd_cmipci_read_w(cm, reg); + if (rem < rec->dma_size) + goto ok; + } + printk(KERN_ERR "cmipci: invalid PCM pointer: %#x\n", rem); + return SNDRV_PCM_POS_XRUN; +ok: + ptr = (rec->dma_size - (rem + 1)) >> rec->shift; #else reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1; ptr = snd_cmipci_read(cm, reg) - rec->offset; diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index 207479a641cf..bc07e275d4d4 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c @@ -39,6 +39,7 @@ #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/pci.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/sb.h> #include <sound/initval.h> diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index 0f48a871f17b..f16bc8aad6ed 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -23,7 +23,6 @@ */ #include <linux/init.h> -#include <linux/slab.h> #include <linux/pci.h> #include <sound/core.h> #include <sound/control.h> diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c index 564c33b60953..a3301cc4ab82 100644 --- a/sound/pci/cs5535audio/cs5535audio_pm.c +++ b/sound/pci/cs5535audio/cs5535audio_pm.c @@ -19,7 +19,6 @@ */ #include <linux/init.h> -#include <linux/slab.h> #include <linux/pci.h> #include <linux/delay.h> #include <sound/core.h> diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 480cb1e905b6..1bff80cde0a2 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -24,6 +24,7 @@ #include "ctdaio.h" #include "cttimer.h" #include <linux/delay.h> +#include <linux/slab.h> #include <sound/pcm.h> #include <sound/control.h> #include <sound/asoundef.h> diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index d0dc227fbdd3..85ab43e89212 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c @@ -17,6 +17,7 @@ #include "ctpcm.h" #include "cttimer.h" +#include <linux/slab.h> #include <sound/pcm.h> /* Hardware descriptions for playback */ diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c index a65bafe0800f..fe7ad64dccd7 100644 --- a/sound/pci/echoaudio/darla20.c +++ b/sound/pci/echoaudio/darla20.c @@ -40,9 +40,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c index 0a6c50bcd758..d1fd34b1a8e3 100644 --- a/sound/pci/echoaudio/darla24.c +++ b/sound/pci/echoaudio/darla24.c @@ -44,9 +44,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c index f5142796989b..1dffdc54416d 100644 --- a/sound/pci/echoaudio/echo3g.c +++ b/sound/pci/echoaudio/echo3g.c @@ -51,9 +51,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 8dab82d7d19d..668a5ec04499 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -2184,10 +2184,9 @@ static int __devinit snd_echo_probe(struct pci_dev *pci, goto ctl_error; #endif - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); + err = snd_card_register(card); + if (err < 0) goto ctl_error; - } snd_printk(KERN_INFO "Card registered: %s\n", card->longname); pci_set_drvdata(pci, chip); diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c index 2364f8a1bc21..050e54aa693f 100644 --- a/sound/pci/echoaudio/gina20.c +++ b/sound/pci/echoaudio/gina20.c @@ -44,9 +44,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c index 616b55825a19..5748fc6d29d6 100644 --- a/sound/pci/echoaudio/gina24.c +++ b/sound/pci/echoaudio/gina24.c @@ -50,9 +50,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c index 776175c0bdad..4ae5e35cb5f1 100644 --- a/sound/pci/echoaudio/indigo.c +++ b/sound/pci/echoaudio/indigo.c @@ -42,9 +42,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c index 8816b0bd2ba6..3550715bab1c 100644 --- a/sound/pci/echoaudio/indigodj.c +++ b/sound/pci/echoaudio/indigodj.c @@ -42,9 +42,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c index b1e3652f2f48..19b191fd0120 100644 --- a/sound/pci/echoaudio/indigodjx.c +++ b/sound/pci/echoaudio/indigodjx.c @@ -42,10 +42,10 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> #include <linux/io.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c index 1035125336d6..a9fcedf317a4 100644 --- a/sound/pci/echoaudio/indigoio.c +++ b/sound/pci/echoaudio/indigoio.c @@ -43,9 +43,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c index 60b7cb2753cf..bcdfac63212c 100644 --- a/sound/pci/echoaudio/indigoiox.c +++ b/sound/pci/echoaudio/indigoiox.c @@ -43,10 +43,10 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> #include <linux/io.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c index 8c3f5c5b5301..d3a98c5dac86 100644 --- a/sound/pci/echoaudio/layla20.c +++ b/sound/pci/echoaudio/layla20.c @@ -49,9 +49,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c index ed1cc0abc2b8..2a1dca6dce17 100644 --- a/sound/pci/echoaudio/layla24.c +++ b/sound/pci/echoaudio/layla24.c @@ -51,9 +51,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c index cc2bbfc65327..9cdf14cfdd74 100644 --- a/sound/pci/echoaudio/mia.c +++ b/sound/pci/echoaudio/mia.c @@ -50,9 +50,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c index 3e7e01824b40..1047be405ebe 100644 --- a/sound/pci/echoaudio/mona.c +++ b/sound/pci/echoaudio/mona.c @@ -48,9 +48,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/firmware.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include <sound/control.h> diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 6a47672f930a..ffb1ddb8dc28 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -22,6 +22,7 @@ */ #include <linux/pci.h> +#include <linux/gfp.h> #include <linux/time.h> #include <linux/mutex.h> diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 556cff937be7..567348b05b5a 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -157,7 +157,7 @@ config SND_HDA_CODEC_INTELHDMI config SND_HDA_ELD def_bool y - depends on SND_HDA_CODEC_INTELHDMI + depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI config SND_HDA_CODEC_CIRRUS bool "Build Cirrus Logic codec support" diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 315a1c4f8998..24bc195b02da 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -3,7 +3,7 @@ snd-hda-intel-objs := hda_intel.o snd-hda-codec-y := hda_codec.o snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o -# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o +snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o @@ -18,7 +18,7 @@ snd-hda-codec-ca0110-objs := patch_ca0110.o snd-hda-codec-conexant-objs := patch_conexant.o snd-hda-codec-via-objs := patch_via.o snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o -snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o +snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o # common driver obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index e4581a42ace5..29714c818b53 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -21,6 +21,7 @@ #include <linux/input.h> #include <linux/pci.h> +#include <linux/slab.h> #include <linux/workqueue.h> #include <sound/core.h> #include "hda_beep.h" diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 76d3c4c049db..0e76ac2b2ace 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -978,8 +978,9 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, * * Returns 0 if successful, or a negative error code. */ -int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, - struct hda_codec **codecp) +int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, + unsigned int codec_addr, + struct hda_codec **codecp) { struct hda_codec *codec; char component[31]; @@ -1186,7 +1187,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream); */ /* FIXME: more better hash key? */ -#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) +#define HDA_HASH_KEY(nid, dir, idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24)) #define HDA_HASH_PINCAP_KEY(nid) (u32)((nid) + (0x02 << 24)) #define HDA_HASH_PARPCM_KEY(nid) (u32)((nid) + (0x03 << 24)) #define HDA_HASH_PARSTR_KEY(nid) (u32)((nid) + (0x04 << 24)) @@ -1356,7 +1357,8 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) 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); + 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); @@ -1372,8 +1374,8 @@ EXPORT_SYMBOL_HDA(snd_hda_pin_sense); */ int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) { - u32 sense = snd_hda_pin_sense(codec, nid); - return !!(sense & AC_PINSENSE_PRESENCE); + u32 sense = snd_hda_pin_sense(codec, nid); + return !!(sense & AC_PINSENSE_PRESENCE); } EXPORT_SYMBOL_HDA(snd_hda_jack_detect); @@ -1804,6 +1806,8 @@ int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl, item->nid = nid; return 0; } + printk(KERN_ERR "hda-codec: no NID for mapping control %s:%d:%d\n", + kctl->id.name, kctl->id.index, index); return -EINVAL; } EXPORT_SYMBOL_HDA(snd_hda_add_nid); @@ -1952,7 +1956,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, err = snd_hda_ctl_add(codec, 0, kctl); if (err < 0) return err; - + for (s = slaves; *s; s++) { struct snd_kcontrol *sctl; int i = 0; @@ -2439,27 +2443,27 @@ static struct snd_kcontrol_new dig_mixes[] = { { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_cmask_get, }, { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_pmask_get, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_default_get, .put = snd_hda_spdif_default_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), .info = snd_hda_spdif_out_switch_info, .get = snd_hda_spdif_out_switch_get, .put = snd_hda_spdif_out_switch_put, @@ -2610,7 +2614,7 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, static struct snd_kcontrol_new dig_in_ctls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH), .info = snd_hda_spdif_in_switch_info, .get = snd_hda_spdif_in_switch_get, .put = snd_hda_spdif_in_switch_put, @@ -2618,7 +2622,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = { { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT), + .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), .info = snd_hda_spdif_mask_info, .get = snd_hda_spdif_in_status_get, }, @@ -2882,8 +2886,8 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) list_for_each_entry(codec, &bus->codec_list, list) { int err = snd_hda_codec_build_controls(codec); if (err < 0) { - printk(KERN_ERR "hda_codec: cannot build controls" - "for #%d (error %d)\n", codec->addr, err); + printk(KERN_ERR "hda_codec: cannot build controls " + "for #%d (error %d)\n", codec->addr, err); err = snd_hda_codec_reset(codec); if (err < 0) { printk(KERN_ERR @@ -2979,8 +2983,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, val |= channels - 1; switch (snd_pcm_format_width(format)) { - case 8: val |= 0x00; break; - case 16: val |= 0x10; break; + case 8: + val |= 0x00; + break; + case 16: + val |= 0x10; + break; case 20: case 24: case 32: @@ -3298,7 +3306,8 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type) if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits)) return audio_idx[type][i]; - snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]); + snd_printk(KERN_WARNING "Too many %s devices\n", + snd_hda_pcm_type_name[type]); return -EAGAIN; } @@ -3336,7 +3345,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) err = codec->patch_ops.build_pcms(codec); if (err < 0) { printk(KERN_ERR "hda_codec: cannot build PCMs" - "for #%d (error %d)\n", codec->addr, err); + "for #%d (error %d)\n", codec->addr, err); err = snd_hda_codec_reset(codec); if (err < 0) { printk(KERN_ERR @@ -3466,8 +3475,8 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_config); /** * snd_hda_check_board_codec_sid_config - compare the current codec - subsystem ID with the - config table + subsystem ID with the + config table This is important for Gateway notebooks with SB450 HDA Audio where the vendor ID of the PCI device is: @@ -3607,7 +3616,7 @@ void snd_hda_update_power_acct(struct hda_codec *codec) * * Increment the power-up counter and power up the hardware really when * not turned on yet. - */ + */ void snd_hda_power_up(struct hda_codec *codec) { struct hda_bus *bus = codec->bus; @@ -3636,7 +3645,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up); * * Decrement the power-up counter and schedules the power-off work if * the counter rearches to zero. - */ + */ void snd_hda_power_down(struct hda_codec *codec) { --codec->power_count; @@ -3662,7 +3671,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_down); * * This function is supposed to be set or called from the check_power_status * patch ops. - */ + */ int snd_hda_check_amp_list_power(struct hda_codec *codec, struct hda_loopback_check *check, hda_nid_t nid) @@ -3830,7 +3839,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, { /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) - set_dig_out_convert(codec, nid, + set_dig_out_convert(codec, nid, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff, -1); snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); @@ -4089,13 +4098,13 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) /* * Sort an associated group of pins according to their sequence numbers. */ -static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, +static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, int num_pins) { int i, j; short seq; hda_nid_t nid; - + for (i = 0; i < num_pins; i++) { for (j = i + 1; j < num_pins; j++) { if (sequences[i] > sequences[j]) { @@ -4123,7 +4132,7 @@ static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences, * is detected, one of speaker of HP pins is assigned as the primary * output, i.e. to line_out_pins[0]. So, line_outs is always positive * if any analog output exists. - * + * * The analog input pins are assigned to input_pins array. * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, * respectively. @@ -4186,9 +4195,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, case AC_JACK_SPEAKER: seq = get_defcfg_sequence(def_conf); assoc = get_defcfg_association(def_conf); - if (! assoc) + if (!assoc) continue; - if (! assoc_speaker) + if (!assoc_speaker) assoc_speaker = assoc; else if (assoc_speaker != assoc) continue; @@ -4286,7 +4295,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, cfg->speaker_outs); sort_pins_by_sequence(cfg->hp_pins, sequences_hp, cfg->hp_outs); - + /* if we have only one mic, make it AUTO_PIN_MIC */ if (!cfg->input_pins[AUTO_PIN_MIC] && cfg->input_pins[AUTO_PIN_FRONT_MIC]) { @@ -4436,7 +4445,7 @@ EXPORT_SYMBOL_HDA(snd_hda_resume); /** * snd_array_new - get a new element from the given array * @array: the array object - * + * * Get a new element from the given array. If it exceeds the * pre-allocated array size, re-allocate the array. * diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 4228f2fe5956..d8da18a9e98b 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -22,6 +22,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <sound/core.h> #include <asm/unaligned.h> #include "hda_codec.h" @@ -331,6 +332,7 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, AC_DIPSIZE_ELD_BUF); } +EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size); int snd_hdmi_get_eld(struct hdmi_eld *eld, struct hda_codec *codec, hda_nid_t nid) @@ -366,6 +368,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, kfree(buf); return ret; } +EXPORT_SYMBOL_HDA(snd_hdmi_get_eld); static void hdmi_show_short_audio_desc(struct cea_sad *a) { @@ -404,6 +407,7 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) } buf[j] = '\0'; /* necessary when j == 0 */ } +EXPORT_SYMBOL_HDA(snd_print_channel_allocation); void snd_hdmi_show_eld(struct hdmi_eld *e) { @@ -422,6 +426,7 @@ void snd_hdmi_show_eld(struct hdmi_eld *e) for (i = 0; i < e->sad_count; i++) hdmi_show_short_audio_desc(e->sad + i); } +EXPORT_SYMBOL_HDA(snd_hdmi_show_eld); #ifdef CONFIG_PROC_FS @@ -580,6 +585,7 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, return 0; } +EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new); void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) { @@ -588,5 +594,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) eld->proc_entry = NULL; } } +EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); #endif /* CONFIG_PROC_FS */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d5c93ad852ee..cec68152dcb1 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -267,7 +267,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define RIRB_INT_MASK 0x05 /* STATESTS int mask: S3,SD2,SD1,SD0 */ -#define AZX_MAX_CODECS 4 +#define AZX_MAX_CODECS 8 +#define AZX_DEFAULT_CODECS 4 #define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1) /* SD_CTL bits */ @@ -1367,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus) /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = { + [AZX_DRIVER_NVIDIA] = 8, [AZX_DRIVER_TERA] = 1, }; @@ -1399,7 +1401,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) codecs = 0; max_slots = azx_max_codecs[chip->driver_type]; if (!max_slots) - max_slots = AZX_MAX_CODECS; + max_slots = AZX_DEFAULT_CODECS; /* First try to probe all given codec slots */ for (c = 0; c < max_slots; c++) { @@ -2263,10 +2265,16 @@ static int azx_dev_free(struct snd_device *device) static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB), SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1565, 0x8218, "Biostar Microtech", POS_FIX_LPIB), + SND_PCI_QUIRK(0x8086, 0x2503, "DG965OT AAD63733-203", POS_FIX_LPIB), + SND_PCI_QUIRK(0x8086, 0xd601, "eMachines T5212", POS_FIX_LPIB), {} }; @@ -2354,6 +2362,9 @@ static void __devinit check_probe_mask(struct azx *chip, int dev) static struct snd_pci_quirk msi_black_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */ + SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */ + SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */ + SND_PCI_QUIRK(0xa0a0, 0x0575, "Aopen MZ915-M", 0), /* ICH6 */ {} }; @@ -2372,6 +2383,13 @@ static void __devinit check_msi(struct azx *chip) "hda_intel: msi for device %04x:%04x set to %d\n", q->subvendor, q->subdevice, q->value); chip->msi = q->value; + return; + } + + /* NVidia chipsets seem to cause troubles with MSI */ + if (chip->driver_type == AZX_DRIVER_NVIDIA) { + printk(KERN_INFO "hda_intel: Disable MSI for Nvidia chipset\n"); + chip->msi = 0; } } @@ -2700,6 +2718,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH }, /* PCH */ { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH }, + { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH }, /* CPT */ { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, /* SCH */ diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index e6d1bdff1b6e..e9fdfc4b1c57 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -519,14 +519,6 @@ static int ad198x_suspend(struct hda_codec *codec, pm_message_t state) ad198x_power_eapd(codec); return 0; } - -static int ad198x_resume(struct hda_codec *codec) -{ - ad198x_init(codec); - snd_hda_codec_resume_amp(codec); - snd_hda_codec_resume_cache(codec); - return 0; -} #endif static struct hda_codec_ops ad198x_patch_ops = { @@ -539,7 +531,6 @@ static struct hda_codec_ops ad198x_patch_ops = { #endif #ifdef SND_HDA_NEEDS_RESUME .suspend = ad198x_suspend, - .resume = ad198x_resume, #endif .reboot_notify = ad198x_shutup, }; @@ -1896,6 +1887,14 @@ static int patch_ad1981(struct hda_codec *codec) case AD1981_THINKPAD: spec->mixers[0] = ad1981_thinkpad_mixers; spec->input_mux = &ad1981_thinkpad_capture_source; + /* set the upper-limit for mixer amp to 0dB for avoiding the + * possible damage by overloading + */ + snd_hda_override_amp_caps(codec, 0x11, HDA_INPUT, + (0x17 << AC_AMPCAP_OFFSET_SHIFT) | + (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | + (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) | + (1 << AC_AMPCAP_MUTE_SHIFT)); break; case AD1981_TOSHIBA: spec->mixers[0] = ad1981_hp_mixers; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 194a28c54992..61682e1d09da 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1591,6 +1591,21 @@ static int patch_cxt5047(struct hda_codec *codec) #endif } spec->vmaster_nid = 0x13; + + switch (codec->subsystem_id >> 16) { + case 0x103c: + /* HP laptops have really bad sound over 0 dB on NID 0x10. + * Fix max PCM level to 0 dB (originally it has 0x1e steps + * with 0 dB offset 0x17) + */ + snd_hda_override_amp_caps(codec, 0x10, 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; + } + return 0; } diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c new file mode 100644 index 000000000000..2c2bafbf0258 --- /dev/null +++ b/sound/pci/hda/patch_hdmi.c @@ -0,0 +1,849 @@ +/* + * + * patch_hdmi.c - routines for HDMI/DisplayPort codecs + * + * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. + * + * Authors: + * Wu Fengguang <wfg@linux.intel.com> + * + * Maintained by: + * Wu Fengguang <wfg@linux.intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +struct hdmi_spec { + int num_cvts; + int num_pins; + hda_nid_t cvt[MAX_HDMI_CVTS+1]; /* audio sources */ + hda_nid_t pin[MAX_HDMI_PINS+1]; /* audio sinks */ + + /* + * source connection for each pin + */ + hda_nid_t pin_cvt[MAX_HDMI_PINS+1]; + + /* + * HDMI sink attached to each pin + */ + struct hdmi_eld sink_eld[MAX_HDMI_PINS]; + + /* + * export one pcm per pipe + */ + struct hda_pcm pcm_rec[MAX_HDMI_CVTS]; + + /* + * nvhdmi specific + */ + struct hda_multi_out multiout; + unsigned int codec_type; +}; + + +struct hdmi_audio_infoframe { + u8 type; /* 0x84 */ + u8 ver; /* 0x01 */ + u8 len; /* 0x0a */ + + u8 checksum; /* PB0 */ + u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ + u8 SS01_SF24; + u8 CXT04; + u8 CA; + u8 LFEPBL01_LSV36_DM_INH7; + u8 reserved[5]; /* PB6 - PB10 */ +}; + +/* + * CEA speaker placement: + * + * FLH FCH FRH + * FLW FL FLC FC FRC FR FRW + * + * LFE + * TC + * + * RL RLC RC RRC RR + * + * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to + * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. + */ +enum cea_speaker_placement { + FL = (1 << 0), /* Front Left */ + FC = (1 << 1), /* Front Center */ + FR = (1 << 2), /* Front Right */ + FLC = (1 << 3), /* Front Left Center */ + FRC = (1 << 4), /* Front Right Center */ + RL = (1 << 5), /* Rear Left */ + RC = (1 << 6), /* Rear Center */ + RR = (1 << 7), /* Rear Right */ + RLC = (1 << 8), /* Rear Left Center */ + RRC = (1 << 9), /* Rear Right Center */ + LFE = (1 << 10), /* Low Frequency Effect */ + FLW = (1 << 11), /* Front Left Wide */ + FRW = (1 << 12), /* Front Right Wide */ + FLH = (1 << 13), /* Front Left High */ + FCH = (1 << 14), /* Front Center High */ + FRH = (1 << 15), /* Front Right High */ + TC = (1 << 16), /* Top Center */ +}; + +/* + * ELD SA bits in the CEA Speaker Allocation data block + */ +static int eld_speaker_allocation_bits[] = { + [0] = FL | FR, + [1] = LFE, + [2] = FC, + [3] = RL | RR, + [4] = RC, + [5] = FLC | FRC, + [6] = RLC | RRC, + /* the following are not defined in ELD yet */ + [7] = FLW | FRW, + [8] = FLH | FRH, + [9] = TC, + [10] = FCH, +}; + +struct cea_channel_speaker_allocation { + int ca_index; + int speakers[8]; + + /* derived values, just for convenience */ + int channels; + int spk_mask; +}; + +/* + * 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: 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 = 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 } }, +{ .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 } }, +{ .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 } }, +{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, +{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, +{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, +{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, +{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, +{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, +{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, +{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, +{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, +{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, +}; + + +/* + * HDMI routines + */ + +static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) +{ + int i; + + for (i = 0; nids[i]; i++) + if (nids[i] == nid) + return i; + + snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); + return -EINVAL; +} + +static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_eld *eld) +{ + if (!snd_hdmi_get_eld(eld, codec, pin_nid)) + snd_hdmi_show_eld(eld); +} + +#ifdef BE_PARANOID +static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, + int *packet_index, int *byte_index) +{ + int val; + + val = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_INDEX, 0); + + *packet_index = val >> 5; + *byte_index = val & 0x1f; +} +#endif + +static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, + int packet_index, int byte_index) +{ + int val; + + val = (packet_index << 5) | (byte_index & 0x1f); + + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); +} + +static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, + unsigned char val) +{ + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); +} + +static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) +{ + /* Unmute */ + if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + /* Enable pin out */ + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); +} + +static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) +{ + return 1 + snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_CVT_CHAN_COUNT, 0); +} + +static void hdmi_set_channel_count(struct hda_codec *codec, + hda_nid_t nid, int chs) +{ + if (chs != hdmi_get_channel_count(codec, nid)) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); +} + + +/* + * Channel mapping routines + */ + +/* + * Compute derived values in channel_allocations[]. + */ +static void init_channel_allocations(void) +{ + int i, j; + struct cea_channel_speaker_allocation *p; + + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { + p = channel_allocations + i; + p->channels = 0; + p->spk_mask = 0; + for (j = 0; j < ARRAY_SIZE(p->speakers); j++) + if (p->speakers[j]) { + p->channels++; + p->spk_mask |= p->speakers[j]; + } + } +} + +/* + * The transformation takes two steps: + * + * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask + * spk_mask => (channel_allocations[]) => ai->CA + * + * TODO: it could select the wrong CA from multiple candidates. +*/ +static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, + struct hdmi_audio_infoframe *ai) +{ + struct hdmi_spec *spec = codec->spec; + struct hdmi_eld *eld; + int i; + int spk_mask = 0; + int channels = 1 + (ai->CC02_CT47 & 0x7); + char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; + + /* + * CA defaults to 0 for basic stereo audio + */ + if (channels <= 2) + return 0; + + i = hda_node_index(spec->pin_cvt, nid); + if (i < 0) + return 0; + eld = &spec->sink_eld[i]; + + /* + * HDMI sink's ELD info cannot always be retrieved for now, e.g. + * in console or for audio devices. Assume the highest speakers + * configuration, to _not_ prohibit multi-channel audio playback. + */ + if (!eld->spk_alloc) + eld->spk_alloc = 0xffff; + + /* + * expand ELD's speaker allocation mask + * + * ELD tells the speaker mask in a compact(paired) form, + * expand ELD's notions to match the ones used by Audio InfoFrame. + */ + for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { + if (eld->spk_alloc & (1 << i)) + spk_mask |= eld_speaker_allocation_bits[i]; + } + + /* search for the first working match in the CA table */ + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { + if (channels == channel_allocations[i].channels && + (spk_mask & channel_allocations[i].spk_mask) == + channel_allocations[i].spk_mask) { + ai->CA = channel_allocations[i].ca_index; + break; + } + } + + snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); + snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", + ai->CA, channels, buf); + + return ai->CA; +} + +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, pin_nid, 0, + AC_VERB_GET_HDMI_CHAN_SLOT, i); + printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", + slot >> 4, slot & 0xf); + } +#endif +} + + +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 (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++) { + 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_NOTICE + "HDMI: channel mapping failed\n"); + break; + } + } + + hdmi_debug_channel_mapping(codec, pin_nid); +} + + +/* + * Audio InfoFrame routines + */ + +/* + * Enable Audio InfoFrame Transmission + */ +static void hdmi_start_infoframe_trans(struct hda_codec *codec, + hda_nid_t pin_nid) +{ + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, + AC_DIPXMIT_BEST); +} + +/* + * Disable Audio InfoFrame Transmission + */ +static void hdmi_stop_infoframe_trans(struct hda_codec *codec, + hda_nid_t pin_nid) +{ + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, + AC_DIPXMIT_DISABLE); +} + +static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) +{ +#ifdef CONFIG_SND_DEBUG_VERBOSE + int i; + int size; + + size = snd_hdmi_get_eld_size(codec, pin_nid); + printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); + + for (i = 0; i < 8; i++) { + size = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_SIZE, i); + printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); + } +#endif +} + +static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) +{ +#ifdef BE_PARANOID + int i, j; + int size; + int pi, bi; + for (i = 0; i < 8; i++) { + size = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_SIZE, i); + if (size == 0) + continue; + + hdmi_set_dip_index(codec, pin_nid, i, 0x0); + for (j = 1; j < 1000; j++) { + hdmi_write_dip_byte(codec, pin_nid, 0x0); + hdmi_get_dip_index(codec, pin_nid, &pi, &bi); + if (pi != i) + snd_printd(KERN_INFO "dip index %d: %d != %d\n", + bi, pi, i); + if (bi == 0) /* byte index wrapped around */ + break; + } + snd_printd(KERN_INFO + "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", + i, size, j); + } +#endif +} + +static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + u8 sum = 0; + int i; + + ai->checksum = 0; + + for (i = 0; i < sizeof(*ai); i++) + sum += bytes[i]; + + ai->checksum = -sum; +} + +static void hdmi_fill_audio_infoframe(struct hda_codec *codec, + hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + int i; + + hdmi_debug_dip_size(codec, pin_nid); + hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ + + hdmi_checksum_audio_infoframe(ai); + + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + for (i = 0; i < sizeof(*ai); i++) + hdmi_write_dip_byte(codec, pin_nid, bytes[i]); +} + +static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_audio_infoframe *ai) +{ + u8 *bytes = (u8 *)ai; + u8 val; + int i; + + if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) + != AC_DIPXMIT_BEST) + return false; + + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); + for (i = 0; i < sizeof(*ai); i++) { + val = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_HDMI_DIP_DATA, 0); + if (val != bytes[i]) + return false; + } + + return true; +} + +static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, + struct snd_pcm_substream *substream) +{ + struct hdmi_spec *spec = codec->spec; + hda_nid_t pin_nid; + int i; + struct hdmi_audio_infoframe ai = { + .type = 0x84, + .ver = 0x01, + .len = 0x0a, + .CC02_CT47 = substream->runtime->channels - 1, + }; + + hdmi_setup_channel_allocation(codec, nid, &ai); + + for (i = 0; i < spec->num_pins; i++) { + if (spec->pin_cvt[i] != nid) + continue; + if (!spec->sink_eld[i].monitor_present) + continue; + + pin_nid = spec->pin[i]; + if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { + snd_printdd("hdmi_setup_audio_infoframe: " + "cvt=%d pin=%d channels=%d\n", + nid, pin_nid, + substream->runtime->channels); + 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); + } + } +} + + +/* + * Unsolicited events + */ + +static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) +{ + struct hdmi_spec *spec = codec->spec; + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int pind = !!(res & AC_UNSOL_RES_PD); + int eldv = !!(res & AC_UNSOL_RES_ELDV); + int index; + + printk(KERN_INFO + "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", + tag, pind, eldv); + + index = hda_node_index(spec->pin, tag); + if (index < 0) + return; + + spec->sink_eld[index].monitor_present = pind; + spec->sink_eld[index].eld_valid = eldv; + + if (pind && eldv) { + hdmi_get_show_eld(codec, spec->pin[index], + &spec->sink_eld[index]); + /* TODO: do real things about ELD */ + } +} + +static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) +{ + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); + int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); + + printk(KERN_INFO + "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", + tag, + subtag, + cp_state, + cp_ready); + + /* TODO */ + if (cp_state) + ; + if (cp_ready) + ; +} + + +static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) +{ + struct hdmi_spec *spec = codec->spec; + int tag = res >> AC_UNSOL_RES_TAG_SHIFT; + int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + + if (hda_node_index(spec->pin, tag) < 0) { + snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); + return; + } + + if (subtag == 0) + hdmi_intrinsic_event(codec, res); + else + hdmi_non_intrinsic_event(codec, res); +} + +/* + * Callbacks + */ + +static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, + u32 stream_tag, int format) +{ + int tag; + int fmt; + + tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; + fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); + + snd_printdd("hdmi_setup_stream: " + "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", + nid, + tag == stream_tag ? "" : "new-", + stream_tag, + fmt == format ? "" : "new-", + format); + + if (tag != stream_tag) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_CHANNEL_STREAMID, + stream_tag << 4); + if (fmt != format) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_STREAM_FORMAT, format); +} + +/* + * HDA/HDMI auto parsing + */ + +static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) +{ + struct hdmi_spec *spec = codec->spec; + hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; + int conn_len, curr; + int index; + + if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { + snd_printk(KERN_WARNING + "HDMI: pin %d wcaps %#x " + "does not support connection list\n", + pin_nid, get_wcaps(codec, pin_nid)); + return -EINVAL; + } + + conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, + HDA_MAX_CONNECTIONS); + if (conn_len > 1) + curr = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_CONNECT_SEL, 0); + else + curr = 0; + + index = hda_node_index(spec->pin, pin_nid); + if (index < 0) + return -EINVAL; + + spec->pin_cvt[index] = conn_list[curr]; + + return 0; +} + +static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, + struct hdmi_eld *eld) +{ + int present = snd_hda_pin_sense(codec, pin_nid); + + eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); + eld->eld_valid = !!(present & AC_PINSENSE_ELDV); + + if (present & AC_PINSENSE_ELDV) + hdmi_get_show_eld(codec, pin_nid, eld); +} + +static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) +{ + struct hdmi_spec *spec = codec->spec; + + if (spec->num_pins >= MAX_HDMI_PINS) { + snd_printk(KERN_WARNING + "HDMI: no space for pin %d\n", pin_nid); + return -EINVAL; + } + + hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); + + spec->pin[spec->num_pins] = pin_nid; + spec->num_pins++; + + /* + * It is assumed that converter nodes come first in the node list and + * hence have been registered and usable now. + */ + return hdmi_read_pin_conn(codec, pin_nid); +} + +static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) +{ + struct hdmi_spec *spec = codec->spec; + + if (spec->num_cvts >= MAX_HDMI_CVTS) { + snd_printk(KERN_WARNING + "HDMI: no space for converter %d\n", nid); + return -EINVAL; + } + + spec->cvt[spec->num_cvts] = nid; + spec->num_cvts++; + + return 0; +} + +static int hdmi_parse_codec(struct hda_codec *codec) +{ + hda_nid_t nid; + int i, nodes; + + nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); + if (!nid || nodes < 0) { + snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); + return -EINVAL; + } + + for (i = 0; i < nodes; i++, nid++) { + unsigned int caps; + unsigned int type; + + caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); + type = get_wcaps_type(caps); + + if (!(caps & AC_WCAP_DIGITAL)) + continue; + + switch (type) { + case AC_WID_AUD_OUT: + if (hdmi_add_cvt(codec, nid) < 0) + return -EINVAL; + break; + case AC_WID_PIN: + caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); + if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) + continue; + if (hdmi_add_pin(codec, nid) < 0) + return -EINVAL; + break; + } + } + + /* + * 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; +} + diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c index 918f40378d52..88d035104cc5 100644 --- a/sound/pci/hda/patch_intelhdmi.c +++ b/sound/pci/hda/patch_intelhdmi.c @@ -40,815 +40,20 @@ * * The HDA correspondence of pipes/ports are converter/pin nodes. */ -#define INTEL_HDMI_CVTS 2 -#define INTEL_HDMI_PINS 3 +#define MAX_HDMI_CVTS 2 +#define MAX_HDMI_PINS 3 -static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = { +#include "patch_hdmi.c" + +static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = { "INTEL HDMI 0", "INTEL HDMI 1", }; -struct intel_hdmi_spec { - int num_cvts; - int num_pins; - hda_nid_t cvt[INTEL_HDMI_CVTS+1]; /* audio sources */ - hda_nid_t pin[INTEL_HDMI_PINS+1]; /* audio sinks */ - - /* - * source connection for each pin - */ - hda_nid_t pin_cvt[INTEL_HDMI_PINS+1]; - - /* - * HDMI sink attached to each pin - */ - struct hdmi_eld sink_eld[INTEL_HDMI_PINS]; - - /* - * export one pcm per pipe - */ - struct hda_pcm pcm_rec[INTEL_HDMI_CVTS]; -}; - -struct hdmi_audio_infoframe { - u8 type; /* 0x84 */ - u8 ver; /* 0x01 */ - u8 len; /* 0x0a */ - - u8 checksum; /* PB0 */ - u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ - u8 SS01_SF24; - u8 CXT04; - u8 CA; - u8 LFEPBL01_LSV36_DM_INH7; - u8 reserved[5]; /* PB6 - PB10 */ -}; - -/* - * CEA speaker placement: - * - * FLH FCH FRH - * FLW FL FLC FC FRC FR FRW - * - * LFE - * TC - * - * RL RLC RC RRC RR - * - * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to - * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC. - */ -enum cea_speaker_placement { - FL = (1 << 0), /* Front Left */ - FC = (1 << 1), /* Front Center */ - FR = (1 << 2), /* Front Right */ - FLC = (1 << 3), /* Front Left Center */ - FRC = (1 << 4), /* Front Right Center */ - RL = (1 << 5), /* Rear Left */ - RC = (1 << 6), /* Rear Center */ - RR = (1 << 7), /* Rear Right */ - RLC = (1 << 8), /* Rear Left Center */ - RRC = (1 << 9), /* Rear Right Center */ - LFE = (1 << 10), /* Low Frequency Effect */ - FLW = (1 << 11), /* Front Left Wide */ - FRW = (1 << 12), /* Front Right Wide */ - FLH = (1 << 13), /* Front Left High */ - FCH = (1 << 14), /* Front Center High */ - FRH = (1 << 15), /* Front Right High */ - TC = (1 << 16), /* Top Center */ -}; - -/* - * ELD SA bits in the CEA Speaker Allocation data block - */ -static int eld_speaker_allocation_bits[] = { - [0] = FL | FR, - [1] = LFE, - [2] = FC, - [3] = RL | RR, - [4] = RC, - [5] = FLC | FRC, - [6] = RLC | RRC, - /* the following are not defined in ELD yet */ - [7] = FLW | FRW, - [8] = FLH | FRH, - [9] = TC, - [10] = FCH, -}; - -struct cea_channel_speaker_allocation { - int ca_index; - int speakers[8]; - - /* derived values, just for convenience */ - int channels; - int spk_mask; -}; - -/* - * 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: 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 = 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 } }, -{ .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 } }, -{ .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 } }, -{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, -{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, -{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, -{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, -{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, -{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, -{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, -{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, -{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, -{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, -}; - -/* - * HDA/HDMI auto parsing - */ - -static int hda_node_index(hda_nid_t *nids, hda_nid_t nid) -{ - int i; - - for (i = 0; nids[i]; i++) - if (nids[i] == nid) - return i; - - snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid); - return -EINVAL; -} - -static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) -{ - struct intel_hdmi_spec *spec = codec->spec; - hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; - int conn_len, curr; - int index; - - if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { - snd_printk(KERN_WARNING - "HDMI: pin %d wcaps %#x " - "does not support connection list\n", - pin_nid, get_wcaps(codec, pin_nid)); - return -EINVAL; - } - - conn_len = snd_hda_get_connections(codec, pin_nid, conn_list, - HDA_MAX_CONNECTIONS); - if (conn_len > 1) - curr = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_CONNECT_SEL, 0); - else - curr = 0; - - index = hda_node_index(spec->pin, pin_nid); - if (index < 0) - return -EINVAL; - - spec->pin_cvt[index] = conn_list[curr]; - - return 0; -} - -static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) -{ - if (!snd_hdmi_get_eld(eld, codec, pin_nid)) - snd_hdmi_show_eld(eld); -} - -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) -{ - int present = snd_hda_pin_sense(codec, pin_nid); - - eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); - eld->eld_valid = !!(present & AC_PINSENSE_ELDV); - - if (present & AC_PINSENSE_ELDV) - hdmi_get_show_eld(codec, pin_nid, eld); -} - -static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) -{ - struct intel_hdmi_spec *spec = codec->spec; - - if (spec->num_pins >= INTEL_HDMI_PINS) { - snd_printk(KERN_WARNING - "HDMI: no space for pin %d \n", pin_nid); - return -EINVAL; - } - - hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]); - - spec->pin[spec->num_pins] = pin_nid; - spec->num_pins++; - - /* - * It is assumed that converter nodes come first in the node list and - * hence have been registered and usable now. - */ - return intel_hdmi_read_pin_conn(codec, pin_nid); -} - -static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid) -{ - struct intel_hdmi_spec *spec = codec->spec; - - if (spec->num_cvts >= INTEL_HDMI_CVTS) { - snd_printk(KERN_WARNING - "HDMI: no space for converter %d \n", nid); - return -EINVAL; - } - - spec->cvt[spec->num_cvts] = nid; - spec->num_cvts++; - - return 0; -} - -static int intel_hdmi_parse_codec(struct hda_codec *codec) -{ - hda_nid_t nid; - int i, nodes; - - nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid); - if (!nid || nodes < 0) { - snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n"); - return -EINVAL; - } - - for (i = 0; i < nodes; i++, nid++) { - unsigned int caps; - unsigned int type; - - caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP); - type = get_wcaps_type(caps); - - if (!(caps & AC_WCAP_DIGITAL)) - continue; - - switch (type) { - case AC_WID_AUD_OUT: - if (intel_hdmi_add_cvt(codec, nid) < 0) - return -EINVAL; - break; - case AC_WID_PIN: - caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); - if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP))) - continue; - if (intel_hdmi_add_pin(codec, nid) < 0) - return -EINVAL; - break; - } - } - - /* - * 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; -} - -/* - * HDMI routines - */ - -#ifdef BE_PARANOID -static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, - int *packet_index, int *byte_index) -{ - int val; - - val = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_INDEX, 0); - - *packet_index = val >> 5; - *byte_index = val & 0x1f; -} -#endif - -static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid, - int packet_index, int byte_index) -{ - int val; - - val = (packet_index << 5) | (byte_index & 0x1f); - - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val); -} - -static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid, - unsigned char val) -{ - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val); -} - -static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid) -{ - /* Unmute */ - if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - /* Enable pin out */ - snd_hda_codec_write(codec, pin_nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); -} - -/* - * Enable Audio InfoFrame Transmission - */ -static void hdmi_start_infoframe_trans(struct hda_codec *codec, - hda_nid_t pin_nid) -{ - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, - AC_DIPXMIT_BEST); -} - -/* - * Disable Audio InfoFrame Transmission - */ -static void hdmi_stop_infoframe_trans(struct hda_codec *codec, - hda_nid_t pin_nid) -{ - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT, - AC_DIPXMIT_DISABLE); -} - -static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid) -{ - return 1 + snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CVT_CHAN_COUNT, 0); -} - -static void hdmi_set_channel_count(struct hda_codec *codec, - hda_nid_t nid, int chs) -{ - if (chs != hdmi_get_channel_count(codec, nid)) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); -} - -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, pin_nid, 0, - AC_VERB_GET_HDMI_CHAN_SLOT, i); - printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", - slot >> 4, slot & 0xf); - } -#endif -} - - -/* - * Audio InfoFrame routines - */ - -static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid) -{ -#ifdef CONFIG_SND_DEBUG_VERBOSE - int i; - int size; - - size = snd_hdmi_get_eld_size(codec, pin_nid); - printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size); - - for (i = 0; i < 8; i++) { - size = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_SIZE, i); - printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size); - } -#endif -} - -static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) -{ -#ifdef BE_PARANOID - int i, j; - int size; - int pi, bi; - for (i = 0; i < 8; i++) { - size = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_SIZE, i); - if (size == 0) - continue; - - hdmi_set_dip_index(codec, pin_nid, i, 0x0); - for (j = 1; j < 1000; j++) { - hdmi_write_dip_byte(codec, pin_nid, 0x0); - hdmi_get_dip_index(codec, pin_nid, &pi, &bi); - if (pi != i) - snd_printd(KERN_INFO "dip index %d: %d != %d\n", - bi, pi, i); - if (bi == 0) /* byte index wrapped around */ - break; - } - snd_printd(KERN_INFO - "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n", - i, size, j); - } -#endif -} - -static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - u8 sum = 0; - int i; - - ai->checksum = 0; - - for (i = 0; i < sizeof(*ai); i++) - sum += bytes[i]; - - ai->checksum = - sum; -} - -static void hdmi_fill_audio_infoframe(struct hda_codec *codec, - hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - int i; - - hdmi_debug_dip_size(codec, pin_nid); - hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ - - hdmi_checksum_audio_infoframe(ai); - - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - for (i = 0; i < sizeof(*ai); i++) - hdmi_write_dip_byte(codec, pin_nid, bytes[i]); -} - -/* - * Compute derived values in channel_allocations[]. - */ -static void init_channel_allocations(void) -{ - int i, j; - struct cea_channel_speaker_allocation *p; - - for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { - p = channel_allocations + i; - p->channels = 0; - p->spk_mask = 0; - for (j = 0; j < ARRAY_SIZE(p->speakers); j++) - if (p->speakers[j]) { - p->channels++; - p->spk_mask |= p->speakers[j]; - } - } -} - -/* - * The transformation takes two steps: - * - * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask - * spk_mask => (channel_allocations[]) => ai->CA - * - * TODO: it could select the wrong CA from multiple candidates. -*/ -static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, - struct hdmi_audio_infoframe *ai) -{ - struct intel_hdmi_spec *spec = codec->spec; - struct hdmi_eld *eld; - int i; - int spk_mask = 0; - int channels = 1 + (ai->CC02_CT47 & 0x7); - char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; - - /* - * CA defaults to 0 for basic stereo audio - */ - if (channels <= 2) - return 0; - - i = hda_node_index(spec->pin_cvt, nid); - if (i < 0) - return 0; - eld = &spec->sink_eld[i]; - - /* - * HDMI sink's ELD info cannot always be retrieved for now, e.g. - * in console or for audio devices. Assume the highest speakers - * configuration, to _not_ prohibit multi-channel audio playback. - */ - if (!eld->spk_alloc) - eld->spk_alloc = 0xffff; - - /* - * expand ELD's speaker allocation mask - * - * ELD tells the speaker mask in a compact(paired) form, - * expand ELD's notions to match the ones used by Audio InfoFrame. - */ - for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) { - if (eld->spk_alloc & (1 << i)) - spk_mask |= eld_speaker_allocation_bits[i]; - } - - /* search for the first working match in the CA table */ - for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { - if (channels == channel_allocations[i].channels && - (spk_mask & channel_allocations[i].spk_mask) == - channel_allocations[i].spk_mask) { - ai->CA = channel_allocations[i].ca_index; - break; - } - } - - snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); - snd_printdd(KERN_INFO - "HDMI: select CA 0x%x for %d-channel allocation: %s\n", - ai->CA, channels, buf); - - return ai->CA; -} - -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 (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++) { - 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, pin_nid); -} - -static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_audio_infoframe *ai) -{ - u8 *bytes = (u8 *)ai; - u8 val; - int i; - - if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0) - != AC_DIPXMIT_BEST) - return false; - - hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); - for (i = 0; i < sizeof(*ai); i++) { - val = snd_hda_codec_read(codec, pin_nid, 0, - AC_VERB_GET_HDMI_DIP_DATA, 0); - if (val != bytes[i]) - return false; - } - - return true; -} - -static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, - struct snd_pcm_substream *substream) -{ - struct intel_hdmi_spec *spec = codec->spec; - hda_nid_t pin_nid; - int i; - struct hdmi_audio_infoframe ai = { - .type = 0x84, - .ver = 0x01, - .len = 0x0a, - .CC02_CT47 = substream->runtime->channels - 1, - }; - - hdmi_setup_channel_allocation(codec, nid, &ai); - - for (i = 0; i < spec->num_pins; i++) { - if (spec->pin_cvt[i] != nid) - continue; - if (!spec->sink_eld[i].monitor_present) - continue; - - 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); - } - } -} - - /* - * Unsolicited events + * HDMI callbacks */ -static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) -{ - struct intel_hdmi_spec *spec = codec->spec; - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int pind = !!(res & AC_UNSOL_RES_PD); - int eldv = !!(res & AC_UNSOL_RES_ELDV); - int index; - - printk(KERN_INFO - "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - tag, pind, eldv); - - index = hda_node_index(spec->pin, tag); - if (index < 0) - return; - - spec->sink_eld[index].monitor_present = pind; - spec->sink_eld[index].eld_valid = eldv; - - if (pind && eldv) { - hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]); - /* TODO: do real things about ELD */ - } -} - -static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) -{ - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; - int cp_state = !!(res & AC_UNSOL_RES_CP_STATE); - int cp_ready = !!(res & AC_UNSOL_RES_CP_READY); - - printk(KERN_INFO - "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n", - tag, - subtag, - cp_state, - cp_ready); - - /* TODO */ - if (cp_state) - ; - if (cp_ready) - ; -} - - -static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res) -{ - struct intel_hdmi_spec *spec = codec->spec; - int tag = res >> AC_UNSOL_RES_TAG_SHIFT; - int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; - - if (hda_node_index(spec->pin, tag) < 0) { - snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); - return; - } - - if (subtag == 0) - hdmi_intrinsic_event(codec, res); - else - hdmi_non_intrinsic_event(codec, res); -} - -/* - * Callbacks - */ - -static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid, - u32 stream_tag, int format) -{ - int tag; - int fmt; - - tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4; - fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0); - - snd_printdd("hdmi_setup_stream: " - "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n", - nid, - tag == stream_tag ? "" : "new-", - stream_tag, - fmt == format ? "" : "new-", - format); - - if (tag != stream_tag) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4); - if (fmt != format) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_STREAM_FORMAT, format); -} - static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -882,7 +87,7 @@ static struct hda_pcm_stream intel_hdmi_pcm_playback = { static int intel_hdmi_build_pcms(struct hda_codec *codec) { - struct intel_hdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; struct hda_pcm *info = spec->pcm_rec; int i; @@ -908,7 +113,7 @@ static int intel_hdmi_build_pcms(struct hda_codec *codec) static int intel_hdmi_build_controls(struct hda_codec *codec) { - struct intel_hdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int err; int i; @@ -923,7 +128,7 @@ static int intel_hdmi_build_controls(struct hda_codec *codec) static int intel_hdmi_init(struct hda_codec *codec) { - struct intel_hdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int i; for (i = 0; spec->pin[i]; i++) { @@ -937,7 +142,7 @@ static int intel_hdmi_init(struct hda_codec *codec) static void intel_hdmi_free(struct hda_codec *codec) { - struct intel_hdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int i; for (i = 0; i < spec->num_pins; i++) @@ -951,12 +156,12 @@ static struct hda_codec_ops intel_hdmi_patch_ops = { .free = intel_hdmi_free, .build_pcms = intel_hdmi_build_pcms, .build_controls = intel_hdmi_build_controls, - .unsol_event = intel_hdmi_unsol_event, + .unsol_event = hdmi_unsol_event, }; static int patch_intel_hdmi(struct hda_codec *codec) { - struct intel_hdmi_spec *spec; + struct hdmi_spec *spec; int i; spec = kzalloc(sizeof(*spec), GFP_KERNEL); @@ -964,7 +169,7 @@ static int patch_intel_hdmi(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; - if (intel_hdmi_parse_codec(codec) < 0) { + if (hdmi_parse_codec(codec) < 0) { codec->spec = NULL; kfree(spec); return -EINVAL; diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index 6afdab09bab7..3c10c0b149f4 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c @@ -29,13 +29,23 @@ #include "hda_codec.h" #include "hda_local.h" +#define MAX_HDMI_CVTS 1 +#define MAX_HDMI_PINS 1 + +#include "patch_hdmi.c" + +static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = { + "NVIDIA HDMI", +}; + /* define below to restrict the supported rates and formats */ /* #define LIMITED_RATE_FMT_SUPPORT */ -struct nvhdmi_spec { - struct hda_multi_out multiout; - - struct hda_pcm pcm_rec; +enum HDACodec { + HDA_CODEC_NVIDIA_MCP7X, + HDA_CODEC_NVIDIA_MCP89, + HDA_CODEC_NVIDIA_GT21X, + HDA_CODEC_INVALID }; #define Nv_VERB_SET_Channel_Allocation 0xF79 @@ -43,15 +53,18 @@ struct nvhdmi_spec { #define Nv_VERB_SET_Audio_Protection_On 0xF98 #define Nv_VERB_SET_Audio_Protection_Off 0xF99 -#define Nv_Master_Convert_nid 0x04 -#define Nv_Master_Pin_nid 0x05 +#define nvhdmi_master_con_nid_7x 0x04 +#define nvhdmi_master_pin_nid_7x 0x05 -static hda_nid_t nvhdmi_convert_nids[4] = { +#define nvhdmi_master_con_nid_89 0x04 +#define nvhdmi_master_pin_nid_89 0x05 + +static hda_nid_t nvhdmi_con_nids_7x[4] = { /*front, rear, clfe, rear_surr */ 0x6, 0x8, 0xa, 0xc, }; -static struct hda_verb nvhdmi_basic_init[] = { +static struct hda_verb nvhdmi_basic_init_7x[] = { /* set audio protect on */ { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, /* enable digital output on pin widget */ @@ -84,22 +97,60 @@ static struct hda_verb nvhdmi_basic_init[] = { */ static int nvhdmi_build_controls(struct hda_codec *codec) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int err; + int i; - err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); - if (err < 0) - return err; + if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) + || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { + for (i = 0; i < codec->num_pcms; i++) { + err = snd_hda_create_spdif_out_ctls(codec, + spec->cvt[i]); + if (err < 0) + return err; + } + } else { + err = snd_hda_create_spdif_out_ctls(codec, + spec->multiout.dig_out_nid); + if (err < 0) + return err; + } return 0; } static int nvhdmi_init(struct hda_codec *codec) { - snd_hda_sequence_write(codec, nvhdmi_basic_init); + struct hdmi_spec *spec = codec->spec; + int i; + if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) + || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { + for (i = 0; spec->pin[i]; i++) { + hdmi_enable_output(codec, spec->pin[i]); + snd_hda_codec_write(codec, spec->pin[i], 0, + AC_VERB_SET_UNSOLICITED_ENABLE, + AC_USRSP_EN | spec->pin[i]); + } + } else { + snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); + } return 0; } +static void nvhdmi_free(struct hda_codec *codec) +{ + struct hdmi_spec *spec = codec->spec; + int i; + + if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) + || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { + for (i = 0; i < spec->num_pins; i++) + snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); + } + + kfree(spec); +} + /* * Digital out */ @@ -107,25 +158,25 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; return snd_hda_multi_out_dig_open(codec, &spec->multiout); } -static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo, +static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; int i; - snd_hda_codec_write(codec, Nv_Master_Convert_nid, + snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); for (i = 0; i < 4; i++) { /* set the stream id */ - snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, + snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_CHANNEL_STREAMID, 0); /* set the stream format */ - snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0, + snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_STREAM_FORMAT, 0); } @@ -136,10 +187,25 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; return snd_hda_multi_out_dig_close(codec, &spec->multiout); } +static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + hdmi_set_channel_count(codec, hinfo->nid, + substream->runtime->channels); + + hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); + + hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); + return 0; +} + static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, @@ -181,29 +247,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) snd_hda_codec_write(codec, - Nv_Master_Convert_nid, + nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); /* set the stream id */ - snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, + snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); /* set the stream format */ - snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, + snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_STREAM_FORMAT, format); /* turn on again (if needed) */ /* enable and set the channel status audio/data flag */ if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { snd_hda_codec_write(codec, - Nv_Master_Convert_nid, + nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & 0xff); snd_hda_codec_write(codec, - Nv_Master_Convert_nid, + nvhdmi_master_con_nid_7x, 0, AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); } @@ -220,19 +286,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) snd_hda_codec_write(codec, - nvhdmi_convert_nids[i], + nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); /* set the stream id */ snd_hda_codec_write(codec, - nvhdmi_convert_nids[i], + nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | channel_id); /* set the stream format */ snd_hda_codec_write(codec, - nvhdmi_convert_nids[i], + nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_STREAM_FORMAT, format); @@ -241,12 +307,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { snd_hda_codec_write(codec, - nvhdmi_convert_nids[i], + nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_DIGI_CONVERT_1, codec->spdif_ctls & 0xff); snd_hda_codec_write(codec, - nvhdmi_convert_nids[i], + nvhdmi_con_nids_7x[i], 0, AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); } @@ -261,28 +327,47 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, return 0; } +static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + return 0; +} + static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, unsigned int format, struct snd_pcm_substream *substream) { - struct nvhdmi_spec *spec = codec->spec; + struct hdmi_spec *spec = codec->spec; return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, format, substream); } -static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = { +static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { + .substreams = 1, + .channels_min = 2, + .rates = SUPPORTED_RATES, + .maxbps = SUPPORTED_MAXBPS, + .formats = SUPPORTED_FORMATS, + .ops = { + .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, + .cleanup = nvhdmi_playback_pcm_cleanup, + }, +}; + +static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = { .substreams = 1, .channels_min = 2, .channels_max = 8, - .nid = Nv_Master_Convert_nid, + .nid = nvhdmi_master_con_nid_7x, .rates = SUPPORTED_RATES, .maxbps = SUPPORTED_MAXBPS, .formats = SUPPORTED_FORMATS, .ops = { .open = nvhdmi_dig_playback_pcm_open, - .close = nvhdmi_dig_playback_pcm_close_8ch, + .close = nvhdmi_dig_playback_pcm_close_8ch_7x, .prepare = nvhdmi_dig_playback_pcm_prepare_8ch }, }; @@ -291,7 +376,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { .substreams = 1, .channels_min = 2, .channels_max = 2, - .nid = Nv_Master_Convert_nid, + .nid = nvhdmi_master_con_nid_7x, .rates = SUPPORTED_RATES, .maxbps = SUPPORTED_MAXBPS, .formats = SUPPORTED_FORMATS, @@ -302,10 +387,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { }, }; -static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) +static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) +{ + struct hdmi_spec *spec = codec->spec; + struct hda_pcm *info = spec->pcm_rec; + int i; + + codec->num_pcms = spec->num_cvts; + codec->pcm_info = info; + + for (i = 0; i < codec->num_pcms; i++, info++) { + unsigned int chans; + + chans = get_wcaps(codec, spec->cvt[i]); + chans = get_wcaps_channels(chans); + + info->name = nvhdmi_pcm_names[i]; + info->pcm_type = HDA_PCM_TYPE_HDMI; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] + = nvhdmi_pcm_digital_playback_8ch_89; + info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; + info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; + } + + return 0; +} + +static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) { - struct nvhdmi_spec *spec = codec->spec; - struct hda_pcm *info = &spec->pcm_rec; + struct hdmi_spec *spec = codec->spec; + struct hda_pcm *info = spec->pcm_rec; codec->num_pcms = 1; codec->pcm_info = info; @@ -313,15 +424,15 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec) info->name = "NVIDIA HDMI"; info->pcm_type = HDA_PCM_TYPE_HDMI; info->stream[SNDRV_PCM_STREAM_PLAYBACK] - = nvhdmi_pcm_digital_playback_8ch; + = nvhdmi_pcm_digital_playback_8ch_7x; return 0; } static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) { - struct nvhdmi_spec *spec = codec->spec; - struct hda_pcm *info = &spec->pcm_rec; + struct hdmi_spec *spec = codec->spec; + struct hda_pcm *info = spec->pcm_rec; codec->num_pcms = 1; codec->pcm_info = info; @@ -334,14 +445,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) return 0; } -static void nvhdmi_free(struct hda_codec *codec) -{ - kfree(codec->spec); -} +static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = { + .build_controls = nvhdmi_build_controls, + .build_pcms = nvhdmi_build_pcms_8ch_89, + .init = nvhdmi_init, + .free = nvhdmi_free, + .unsol_event = hdmi_unsol_event, +}; -static struct hda_codec_ops nvhdmi_patch_ops_8ch = { +static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { .build_controls = nvhdmi_build_controls, - .build_pcms = nvhdmi_build_pcms_8ch, + .build_pcms = nvhdmi_build_pcms_8ch_7x, .init = nvhdmi_init, .free = nvhdmi_free, }; @@ -353,9 +467,36 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = { .free = nvhdmi_free, }; -static int patch_nvhdmi_8ch(struct hda_codec *codec) +static int patch_nvhdmi_8ch_89(struct hda_codec *codec) +{ + struct hdmi_spec *spec; + int i; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + spec->codec_type = HDA_CODEC_NVIDIA_MCP89; + + if (hdmi_parse_codec(codec) < 0) { + codec->spec = NULL; + kfree(spec); + return -EINVAL; + } + codec->patch_ops = nvhdmi_patch_ops_8ch_89; + + for (i = 0; i < spec->num_pins; i++) + snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); + + init_channel_allocations(); + + return 0; +} + +static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) { - struct nvhdmi_spec *spec; + struct hdmi_spec *spec; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -365,16 +506,17 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec) spec->multiout.num_dacs = 0; /* no analog */ spec->multiout.max_channels = 8; - spec->multiout.dig_out_nid = Nv_Master_Convert_nid; + spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; + spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; - codec->patch_ops = nvhdmi_patch_ops_8ch; + codec->patch_ops = nvhdmi_patch_ops_8ch_7x; return 0; } static int patch_nvhdmi_2ch(struct hda_codec *codec) { - struct nvhdmi_spec *spec; + struct hdmi_spec *spec; spec = kzalloc(sizeof(*spec), GFP_KERNEL); if (spec == NULL) @@ -384,7 +526,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) spec->multiout.num_dacs = 0; /* no analog */ spec->multiout.max_channels = 2; - spec->multiout.dig_out_nid = Nv_Master_Convert_nid; + spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; + spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; codec->patch_ops = nvhdmi_patch_ops_2ch; @@ -395,11 +538,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) * patch entries */ static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { - { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, - { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, - { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, - { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch }, - { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch }, + { .id = 0x10de0002, .name = "MCP77/78 HDMI", + .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0003, .name = "MCP77/78 HDMI", + .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0005, .name = "MCP77/78 HDMI", + .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0006, .name = "MCP77/78 HDMI", + .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de0007, .name = "MCP79/7A HDMI", + .patch = patch_nvhdmi_8ch_7x }, + { .id = 0x10de000a, .name = "GT220 HDMI", + .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de000b, .name = "GT21x HDMI", + .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de000c, .name = "MCP89 HDMI", + .patch = patch_nvhdmi_8ch_89 }, + { .id = 0x10de000d, .name = "GT240 HDMI", + .patch = patch_nvhdmi_8ch_89 }, { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, {} /* terminator */ @@ -410,11 +566,15 @@ MODULE_ALIAS("snd-hda-codec-id:10de0003"); MODULE_ALIAS("snd-hda-codec-id:10de0005"); MODULE_ALIAS("snd-hda-codec-id:10de0006"); MODULE_ALIAS("snd-hda-codec-id:10de0007"); +MODULE_ALIAS("snd-hda-codec-id:10de000a"); +MODULE_ALIAS("snd-hda-codec-id:10de000b"); +MODULE_ALIAS("snd-hda-codec-id:10de000c"); +MODULE_ALIAS("snd-hda-codec-id:10de000d"); MODULE_ALIAS("snd-hda-codec-id:10de0067"); MODULE_ALIAS("snd-hda-codec-id:10de8001"); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec"); +MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec"); static struct hda_codec_preset_list nvhdmi_list = { .preset = snd_hda_preset_nvhdmi, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e8cbe216e912..7404dba16f83 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -230,6 +230,7 @@ enum { ALC888_ACER_ASPIRE_7730G, ALC883_MEDION, ALC883_MEDION_MD2, + ALC883_MEDION_WIM2160, ALC883_LAPTOP_EAPD, ALC883_LENOVO_101E_2ch, ALC883_LENOVO_NB0763, @@ -411,6 +412,8 @@ static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id); if (mux_idx >= spec->num_mux_defs) mux_idx = 0; + if (!spec->input_mux[mux_idx].num_items && mux_idx > 0) + mux_idx = 0; return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); } @@ -439,6 +442,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; imux = &spec->input_mux[mux_idx]; + if (!imux->num_items && mux_idx > 0) + imux = &spec->input_mux[0]; type = get_wcaps_type(get_wcaps(codec, nid)); if (type == AC_WID_AUD_MIX) { @@ -1385,22 +1390,31 @@ struct alc_fixup { static void alc_pick_fixup(struct hda_codec *codec, const struct snd_pci_quirk *quirk, - const struct alc_fixup *fix) + const struct alc_fixup *fix, + int pre_init) { const struct alc_pincfg *cfg; quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); if (!quirk) return; - fix += quirk->value; cfg = fix->pins; - if (cfg) { + if (pre_init && cfg) { +#ifdef CONFIG_SND_DEBUG_VERBOSE + snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n", + codec->chip_name, quirk->name); +#endif for (; cfg->nid; cfg++) snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); } - if (fix->verbs) + if (!pre_init && fix->verbs) { +#ifdef CONFIG_SND_DEBUG_VERBOSE + snd_printdd(KERN_INFO "hda_codec: %s: Apply fix-verbs for %s\n", + codec->chip_name, quirk->name); +#endif add_verb(codec->spec, fix->verbs); + } } static int alc_read_coef_idx(struct hda_codec *codec, @@ -1617,6 +1631,11 @@ static struct hda_verb alc888_acer_aspire_4930g_verbs[] = { */ static struct hda_verb alc888_acer_aspire_6530g_verbs[] = { +/* Route to built-in subwoofer as well as speakers */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, /* Bias voltage on for external mic port */ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80}, /* Front Mic: set to PIN_IN (empty by default) */ @@ -1628,10 +1647,12 @@ static struct hda_verb alc888_acer_aspire_6530g_verbs[] = { /* Enable speaker output */ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, /* Enable headphone output */ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2}, { } }; @@ -2528,8 +2549,6 @@ static int alc_build_controls(struct hda_codec *codec) return err; } - alc_free_kctls(codec); /* no longer needed */ - /* assign Capture Source enums to NID */ kctl = snd_hda_find_mixer_ctl(codec, "Capture Source"); if (!kctl) @@ -2598,6 +2617,9 @@ static int alc_build_controls(struct hda_codec *codec) } } } + + alc_free_kctls(codec); /* no longer needed */ + return 0; } @@ -4121,7 +4143,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG), SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734), SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU), - SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL), + SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734), SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU), SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW), SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG), @@ -4796,6 +4818,25 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec) } } +static void alc880_auto_init_input_src(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int c; + + for (c = 0; c < spec->num_adc_nids; c++) { + unsigned int mux_idx; + const struct hda_input_mux *imux; + mux_idx = c >= spec->num_mux_defs ? 0 : c; + imux = &spec->input_mux[mux_idx]; + if (!imux->num_items && mux_idx > 0) + imux = &spec->input_mux[0]; + if (imux) + snd_hda_codec_write(codec, spec->adc_nids[c], 0, + AC_VERB_SET_CONNECT_SEL, + imux->items[0].index); + } +} + /* parse the BIOS configuration and set up the alc_spec */ /* return 1 if successful, 0 if the proper config is not found, * or a negative error code @@ -4874,6 +4915,7 @@ static void alc880_auto_init(struct hda_codec *codec) alc880_auto_init_multi_out(codec); alc880_auto_init_extra_out(codec); alc880_auto_init_analog_input(codec); + alc880_auto_init_input_src(codec); if (spec->unsol_event) alc_inithook(codec); } @@ -4915,7 +4957,7 @@ static void fixup_automic_adc(struct hda_codec *codec) static void fixup_single_adc(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - hda_nid_t pin; + hda_nid_t pin = 0; int i; /* search for the input pin; there must be only one */ @@ -4979,6 +5021,70 @@ static void set_capture_mixer(struct hda_codec *codec) } } +/* fill adc_nids (and capsrc_nids) containing all active input pins */ +static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, + int num_nids) +{ + struct alc_spec *spec = codec->spec; + int n; + hda_nid_t fallback_adc = 0, fallback_cap = 0; + + for (n = 0; n < num_nids; n++) { + hda_nid_t adc, cap; + hda_nid_t conn[HDA_MAX_NUM_INPUTS]; + int nconns, i, j; + + adc = nids[n]; + if (get_wcaps_type(get_wcaps(codec, adc)) != AC_WID_AUD_IN) + continue; + cap = adc; + nconns = snd_hda_get_connections(codec, cap, conn, + ARRAY_SIZE(conn)); + if (nconns == 1) { + cap = conn[0]; + nconns = snd_hda_get_connections(codec, cap, conn, + ARRAY_SIZE(conn)); + } + if (nconns <= 0) + continue; + if (!fallback_adc) { + fallback_adc = adc; + fallback_cap = cap; + } + for (i = 0; i < AUTO_PIN_LAST; i++) { + hda_nid_t nid = spec->autocfg.input_pins[i]; + if (!nid) + continue; + for (j = 0; j < nconns; j++) { + if (conn[j] == nid) + break; + } + if (j >= nconns) + break; + } + if (i >= AUTO_PIN_LAST) { + int num_adcs = spec->num_adc_nids; + spec->private_adc_nids[num_adcs] = adc; + spec->private_capsrc_nids[num_adcs] = cap; + spec->num_adc_nids++; + spec->adc_nids = spec->private_adc_nids; + if (adc != cap) + spec->capsrc_nids = spec->private_capsrc_nids; + } + } + if (!spec->num_adc_nids) { + printk(KERN_WARNING "hda_codec: %s: no valid ADC found;" + " using fallback 0x%x\n", + codec->chip_name, fallback_adc); + spec->private_adc_nids[0] = fallback_adc; + spec->adc_nids = spec->private_adc_nids; + if (fallback_adc != fallback_cap) { + spec->private_capsrc_nids[0] = fallback_cap; + spec->capsrc_nids = spec->private_adc_nids; + } + } +} + #ifdef CONFIG_SND_HDA_INPUT_BEEP #define set_beep_amp(spec, nid, idx, dir) \ ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) @@ -6321,6 +6427,8 @@ static void alc260_auto_init_analog_input(struct hda_codec *codec) } } +#define alc260_auto_init_input_src alc880_auto_init_input_src + /* * generic initialization of ADC, input mixers and output mixers */ @@ -6407,6 +6515,7 @@ static void alc260_auto_init(struct hda_codec *codec) struct alc_spec *spec = codec->spec; alc260_auto_init_multi_out(codec); alc260_auto_init_analog_input(codec); + alc260_auto_init_input_src(codec); if (spec->unsol_event) alc_inithook(codec); } @@ -6473,7 +6582,7 @@ static struct alc_config_preset alc260_presets[] = { .num_dacs = ARRAY_SIZE(alc260_dac_nids), .dac_nids = alc260_dac_nids, .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids), - .adc_nids = alc260_adc_nids, + .adc_nids = alc260_dual_adc_nids, .num_channel_mode = ARRAY_SIZE(alc260_modes), .channel_mode = alc260_modes, .input_mux = &alc260_capture_source, @@ -8379,6 +8488,42 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { { } /* end */ }; +static struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = { + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), + HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT), + { } /* end */ +}; + +static struct hda_verb alc883_medion_wim2160_verbs[] = { + /* Unmute front mixer */ + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + + /* Set speaker pin to front mixer */ + {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, + + /* Init headphone pin */ + {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, + + { } /* end */ +}; + +/* toggle speaker-output according to the hp-jack state */ +static void alc883_medion_wim2160_setup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + spec->autocfg.hp_pins[0] = 0x1a; + spec->autocfg.speaker_pins[0] = 0x15; +} + static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), @@ -8393,9 +8538,7 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("LFE Playback Switch", 0x0f, 2, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), @@ -9090,6 +9233,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g", [ALC883_MEDION] = "medion", [ALC883_MEDION_MD2] = "medion-md2", + [ALC883_MEDION_WIM2160] = "medion-wim2160", [ALC883_LAPTOP_EAPD] = "laptop-eapd", [ALC883_LENOVO_101E_2ch] = "lenovo-101e", [ALC883_LENOVO_NB0763] = "lenovo-nb0763", @@ -9191,6 +9335,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG), SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG), SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG), + SND_PCI_QUIRK(0x1462, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG), SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG), SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), @@ -9200,10 +9345,12 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG), + SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG), SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), + SND_PCI_QUIRK(0x1558, 0x0571, "Clevo laptop M570U", ALC883_3ST_6ch_DIG), SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720), SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R), @@ -9231,7 +9378,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL), SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL), SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL), - SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch), + SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG), {} }; @@ -9742,6 +9889,21 @@ static struct alc_config_preset alc882_presets[] = { .setup = alc883_medion_md2_setup, .init_hook = alc_automute_amp, }, + [ALC883_MEDION_WIM2160] = { + .mixers = { alc883_medion_wim2160_mixer }, + .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs }, + .num_dacs = ARRAY_SIZE(alc883_dac_nids), + .dac_nids = alc883_dac_nids, + .dig_out_nid = ALC883_DIGOUT_NID, + .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), + .adc_nids = alc883_adc_nids, + .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), + .channel_mode = alc883_3ST_2ch_modes, + .input_mux = &alc883_capture_source, + .unsol_event = alc_automute_amp_unsol_event, + .setup = alc883_medion_wim2160_setup, + .init_hook = alc_automute_amp, + }, [ALC883_LAPTOP_EAPD] = { .mixers = { alc883_base_mixer }, .init_verbs = { alc883_init_verbs, alc882_eapd_verbs }, @@ -10034,6 +10196,8 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, int idx; alc_set_pin_output(codec, nid, pin_type); + if (dac_idx >= spec->multiout.num_dacs) + return; if (spec->multiout.dac_nids[dac_idx] == 0x25) idx = 4; else @@ -10105,6 +10269,8 @@ static void alc882_auto_init_input_src(struct hda_codec *codec) continue; mux_idx = c >= spec->num_mux_defs ? 0 : c; imux = &spec->input_mux[mux_idx]; + if (!imux->num_items && mux_idx > 0) + imux = &spec->input_mux[0]; for (idx = 0; idx < conns; idx++) { /* if the current connection is the selected one, * unmute it as default - otherwise mute it @@ -10283,7 +10449,8 @@ static int patch_alc882(struct hda_codec *codec) board_config = ALC882_AUTO; } - alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups); + if (board_config == ALC882_AUTO) + alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1); if (board_config == ALC882_AUTO) { /* automatic parse from the BIOS config */ @@ -10356,6 +10523,9 @@ static int patch_alc882(struct hda_codec *codec) set_capture_mixer(codec); set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (board_config == ALC882_AUTO) + alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 0); + spec->vmaster_nid = 0x0c; codec->patch_ops = alc_patch_ops; @@ -12447,11 +12617,11 @@ static void alc268_aspire_one_speaker_automute(struct hda_codec *codec) unsigned char bits; present = snd_hda_jack_detect(codec, 0x15); - bits = present ? AMP_IN_MUTE(0) : 0; + bits = present ? HDA_AMP_MUTE : 0; snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); } static void alc268_acer_lc_unsol_event(struct hda_codec *codec, @@ -12736,6 +12906,7 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, dac = 0x02; break; case 0x15: + case 0x21: /* ALC269vb has this pin, too */ dac = 0x03; break; default: @@ -13201,7 +13372,7 @@ static int patch_alc268(struct hda_codec *codec) if (board_config < 0 || board_config >= ALC268_MODEL_LAST) board_config = snd_hda_check_board_codec_sid_config(codec, - ALC882_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl); + ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl); if (board_config < 0 || board_config >= ALC268_MODEL_LAST) { printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", @@ -13321,9 +13492,9 @@ static hda_nid_t alc269vb_capsrc_nids[1] = { 0x22, }; -/* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24), - * not a mux! - */ +static hda_nid_t alc269_adc_candidates[] = { + 0x08, 0x09, 0x07, +}; #define alc269_modes alc260_modes #define alc269_capture_source alc880_lg_lw_capture_source @@ -13470,11 +13641,11 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec) unsigned char bits; present = snd_hda_jack_detect(codec, 0x15); - bits = present ? AMP_IN_MUTE(0) : 0; + bits = present ? HDA_AMP_MUTE : 0; snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x0c); @@ -13499,11 +13670,11 @@ static void alc269_lifebook_speaker_automute(struct hda_codec *codec) /* Check port replicator headphone socket */ present |= snd_hda_jack_detect(codec, 0x1a); - bits = present ? AMP_IN_MUTE(0) : 0; + bits = present ? HDA_AMP_MUTE : 0; snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0x0c); @@ -13561,6 +13732,8 @@ static void alc269_lifebook_unsol_event(struct hda_codec *codec, static void alc269_quanta_fl1_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + spec->autocfg.hp_pins[0] = 0x15; + spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x19; @@ -13632,11 +13805,11 @@ static void alc269_speaker_automute(struct hda_codec *codec) unsigned char bits; present = snd_hda_jack_detect(codec, nid); - bits = present ? AMP_IN_MUTE(0) : 0; + bits = present ? HDA_AMP_MUTE : 0; snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); } /* unsolicited event for HP jack sensing */ @@ -13653,29 +13826,35 @@ static void alc269_laptop_unsol_event(struct hda_codec *codec, } } -static void alc269_laptop_dmic_setup(struct hda_codec *codec) +static void alc269_laptop_amic_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + spec->autocfg.hp_pins[0] = 0x15; + spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; - spec->int_mic.pin = 0x12; - spec->int_mic.mux_idx = 5; + spec->int_mic.pin = 0x19; + spec->int_mic.mux_idx = 1; spec->auto_mic = 1; } -static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) +static void alc269_laptop_dmic_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + spec->autocfg.hp_pins[0] = 0x15; + spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x12; - spec->int_mic.mux_idx = 6; + spec->int_mic.mux_idx = 5; spec->auto_mic = 1; } -static void alc269_laptop_amic_setup(struct hda_codec *codec) +static void alc269vb_laptop_amic_setup(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + spec->autocfg.hp_pins[0] = 0x21; + spec->autocfg.speaker_pins[0] = 0x14; spec->ext_mic.pin = 0x18; spec->ext_mic.mux_idx = 0; spec->int_mic.pin = 0x19; @@ -13683,6 +13862,18 @@ static void alc269_laptop_amic_setup(struct hda_codec *codec) spec->auto_mic = 1; } +static void alc269vb_laptop_dmic_setup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + spec->autocfg.hp_pins[0] = 0x21; + spec->autocfg.speaker_pins[0] = 0x14; + spec->ext_mic.pin = 0x18; + spec->ext_mic.mux_idx = 0; + spec->int_mic.pin = 0x12; + spec->int_mic.mux_idx = 6; + spec->auto_mic = 1; +} + static void alc269_laptop_inithook(struct hda_codec *codec) { alc269_speaker_automute(codec); @@ -13822,7 +14013,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec) struct alc_spec *spec = codec->spec; int err; static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; - hda_nid_t real_capsrc_nids; err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, alc269_ignore); @@ -13846,18 +14036,19 @@ static int alc269_parse_auto_config(struct hda_codec *codec) if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) { add_verb(spec, alc269vb_init_verbs); - real_capsrc_nids = alc269vb_capsrc_nids[0]; alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); } else { add_verb(spec, alc269_init_verbs); - real_capsrc_nids = alc269_capsrc_nids[0]; alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); } spec->num_mux_defs = 1; spec->input_mux = &spec->private_imux[0]; + fillup_priv_adc_nids(codec, alc269_adc_candidates, + sizeof(alc269_adc_candidates)); + /* set default input source */ - snd_hda_codec_write_cache(codec, real_capsrc_nids, + snd_hda_codec_write_cache(codec, spec->capsrc_nids[0], 0, AC_VERB_SET_CONNECT_SEL, spec->input_mux->items[0].index); @@ -13887,6 +14078,27 @@ static void alc269_auto_init(struct hda_codec *codec) alc_inithook(codec); } +enum { + ALC269_FIXUP_SONY_VAIO, +}; + +const static struct hda_verb alc269_sony_vaio_fixup_verbs[] = { + {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, + {} +}; + +static const struct alc_fixup alc269_fixups[] = { + [ALC269_FIXUP_SONY_VAIO] = { + .verbs = alc269_sony_vaio_fixup_verbs + }, +}; + +static struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), + {} +}; + + /* * configuration and preset */ @@ -13946,7 +14158,7 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = { ALC269_DMIC), SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC), SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC), - SND_PCI_QUIRK(0x104d, 0x9071, "SONY XTB", ALC269_DMIC), + SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO), SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC), SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), @@ -14020,7 +14232,7 @@ static struct alc_config_preset alc269_presets[] = { .num_channel_mode = ARRAY_SIZE(alc269_modes), .channel_mode = alc269_modes, .unsol_event = alc269_laptop_unsol_event, - .setup = alc269_laptop_amic_setup, + .setup = alc269vb_laptop_amic_setup, .init_hook = alc269_laptop_inithook, }, [ALC269VB_DMIC] = { @@ -14100,6 +14312,9 @@ static int patch_alc269(struct hda_codec *codec) board_config = ALC269_AUTO; } + if (board_config == ALC269_AUTO) + alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 1); + if (board_config == ALC269_AUTO) { /* automatic parse from the BIOS config */ err = alc269_parse_auto_config(codec); @@ -14136,20 +14351,25 @@ static int patch_alc269(struct hda_codec *codec) spec->stream_digital_playback = &alc269_pcm_digital_playback; spec->stream_digital_capture = &alc269_pcm_digital_capture; - if (!is_alc269vb) { - spec->adc_nids = alc269_adc_nids; - spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); - spec->capsrc_nids = alc269_capsrc_nids; - } else { - spec->adc_nids = alc269vb_adc_nids; - spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids); - spec->capsrc_nids = alc269vb_capsrc_nids; + if (!spec->adc_nids) { /* wasn't filled automatically? use default */ + if (!is_alc269vb) { + spec->adc_nids = alc269_adc_nids; + spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); + spec->capsrc_nids = alc269_capsrc_nids; + } else { + spec->adc_nids = alc269vb_adc_nids; + spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids); + spec->capsrc_nids = alc269vb_capsrc_nids; + } } if (!spec->cap_mixer) set_capture_mixer(codec); set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); + if (board_config == ALC269_AUTO) + alc_pick_fixup(codec, alc269_fixup_tbl, alc269_fixups, 0); + spec->vmaster_nid = 0x02; codec->patch_ops = alc_patch_ops; @@ -15238,7 +15458,8 @@ static int patch_alc861(struct hda_codec *codec) board_config = ALC861_AUTO; } - alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups); + if (board_config == ALC861_AUTO) + alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups, 1); if (board_config == ALC861_AUTO) { /* automatic parse from the BIOS config */ @@ -15275,6 +15496,9 @@ static int patch_alc861(struct hda_codec *codec) spec->vmaster_nid = 0x03; + if (board_config == ALC861_AUTO) + alc_pick_fixup(codec, alc861_fixup_tbl, alc861_fixups, 0); + codec->patch_ops = alc_patch_ops; if (board_config == ALC861_AUTO) { spec->init_hook = alc861_auto_init; @@ -16209,7 +16433,8 @@ static int patch_alc861vd(struct hda_codec *codec) board_config = ALC861VD_AUTO; } - alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups); + if (board_config == ALC861VD_AUTO) + alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups, 1); if (board_config == ALC861VD_AUTO) { /* automatic parse from the BIOS config */ @@ -16257,6 +16482,9 @@ static int patch_alc861vd(struct hda_codec *codec) spec->vmaster_nid = 0x02; + if (board_config == ALC861VD_AUTO) + alc_pick_fixup(codec, alc861vd_fixup_tbl, alc861vd_fixups, 0); + codec->patch_ops = alc_patch_ops; if (board_config == ALC861VD_AUTO) @@ -17095,9 +17323,9 @@ static void alc663_m51va_speaker_automute(struct hda_codec *codec) present = snd_hda_jack_detect(codec, 0x21); bits = present ? HDA_AMP_MUTE : 0; snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); } static void alc663_21jd_two_speaker_automute(struct hda_codec *codec) @@ -17108,13 +17336,13 @@ static void alc663_21jd_two_speaker_automute(struct hda_codec *codec) present = snd_hda_jack_detect(codec, 0x21); bits = present ? HDA_AMP_MUTE : 0; snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); } static void alc663_15jd_two_speaker_automute(struct hda_codec *codec) @@ -17125,13 +17353,13 @@ static void alc663_15jd_two_speaker_automute(struct hda_codec *codec) present = snd_hda_jack_detect(codec, 0x15); bits = present ? HDA_AMP_MUTE : 0; snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1, - AMP_IN_MUTE(0), bits); + HDA_AMP_MUTE, bits); } static void alc662_f5z_speaker_automute(struct hda_codec *codec) @@ -17170,14 +17398,14 @@ static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec) if (present1 || present2) { snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, - AMP_IN_MUTE(0), AMP_IN_MUTE(0)); + HDA_AMP_MUTE, HDA_AMP_MUTE); snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, - AMP_IN_MUTE(0), AMP_IN_MUTE(0)); + HDA_AMP_MUTE, HDA_AMP_MUTE); } else { snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, - AMP_IN_MUTE(0), 0); + HDA_AMP_MUTE, 0); snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, - AMP_IN_MUTE(0), 0); + HDA_AMP_MUTE, 0); } } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 8c416bb18a57..7fb7d017a347 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1607,6 +1607,10 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { "Dell Studio 1555", STAC_DELL_M6_DMIC), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd, "Dell Studio 1557", STAC_DELL_M6_DMIC), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe, + "Dell Studio XPS 1645", STAC_DELL_M6_BOTH), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413, + "Dell Studio 1558", STAC_DELL_M6_BOTH), {} /* terminator */ }; @@ -1730,6 +1734,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { "HP HDX", STAC_HP_HDX), /* HDX16 */ SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3620, "HP dv6", STAC_HP_DV5), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3061, + "HP dv6", STAC_HP_DV5), /* HP dv6-1110ax */ SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x7010, "HP", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 9ddc37300f6b..73453814e098 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -476,7 +476,7 @@ static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, knew->name = kstrdup(tmpl->name, GFP_KERNEL); if (!knew->name) return NULL; - return 0; + return knew; } static void via_free_kctls(struct hda_codec *codec) @@ -1215,14 +1215,13 @@ static struct snd_kcontrol_new via_hp_mixer[2] = { }, }; -static int via_hp_build(struct via_spec *spec) +static int via_hp_build(struct hda_codec *codec) { + struct via_spec *spec = codec->spec; struct snd_kcontrol_new *knew; hda_nid_t nid; - - knew = via_clone_control(spec, &via_hp_mixer[0]); - if (knew == NULL) - return -ENOMEM; + int nums; + hda_nid_t conn[HDA_MAX_CONNECTIONS]; switch (spec->codec_type) { case VT1718S: @@ -1239,6 +1238,14 @@ static int via_hp_build(struct via_spec *spec) break; } + nums = snd_hda_get_connections(codec, nid, conn, HDA_MAX_CONNECTIONS); + if (nums <= 1) + return 0; + + knew = via_clone_control(spec, &via_hp_mixer[0]); + if (knew == NULL) + return -ENOMEM; + knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; knew->private_value = nid; @@ -2561,7 +2568,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) spec->input_mux = &spec->private_imux[0]; if (spec->hp_mux) - via_hp_build(spec); + via_hp_build(codec); via_smart51_build(spec); return 1; @@ -3087,7 +3094,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) spec->input_mux = &spec->private_imux[0]; if (spec->hp_mux) - via_hp_build(spec); + via_hp_build(codec); via_smart51_build(spec); return 1; @@ -3654,7 +3661,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) spec->input_mux = &spec->private_imux[0]; if (spec->hp_mux) - via_hp_build(spec); + via_hp_build(codec); via_smart51_build(spec); return 1; @@ -4140,7 +4147,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) spec->input_mux = &spec->private_imux[0]; if (spec->hp_mux) - via_hp_build(spec); + via_hp_build(codec); via_smart51_build(spec); return 1; @@ -4510,7 +4517,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) spec->input_mux = &spec->private_imux[0]; if (spec->hp_mux) - via_hp_build(spec); + via_hp_build(codec); return 1; } @@ -4930,7 +4937,7 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec) spec->input_mux = &spec->private_imux[0]; if (spec->hp_mux) - via_hp_build(spec); + via_hp_build(codec); via_smart51_build(spec); @@ -5425,7 +5432,7 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec) spec->input_mux = &spec->private_imux[0]; if (spec->hp_mux) - via_hp_build(spec); + via_hp_build(codec); via_smart51_build(spec); @@ -5781,7 +5788,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec) spec->input_mux = &spec->private_imux[0]; if (spec->hp_mux) - via_hp_build(spec); + via_hp_build(codec); return 1; } @@ -6000,12 +6007,12 @@ static int vt1812_auto_create_multi_out_ctls(struct via_spec *spec, /* Line-Out: PortE */ err = via_add_control(spec, VIA_CTL_WIDGET_VOL, - "Master Front Playback Volume", + "Front Playback Volume", HDA_COMPOSE_AMP_VAL(0x8, 3, 0, HDA_OUTPUT)); if (err < 0) return err; err = via_add_control(spec, VIA_CTL_WIDGET_BIND_PIN_MUTE, - "Master Front Playback Switch", + "Front Playback Switch", HDA_COMPOSE_AMP_VAL(0x28, 3, 0, HDA_OUTPUT)); if (err < 0) return err; @@ -6130,7 +6137,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec) spec->input_mux = &spec->private_imux[0]; if (spec->hp_mux) - via_hp_build(spec); + via_hp_build(codec); return 1; } diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c index 03391da8c8c7..90d560c3df13 100644 --- a/sound/pci/ice1712/ak4xxx.c +++ b/sound/pci/ice1712/ak4xxx.c @@ -24,6 +24,7 @@ #include <asm/io.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include <linux/init.h> #include <sound/core.h> #include <sound/initval.h> diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c index 6da21a2bcade..e328cfb7620c 100644 --- a/sound/pci/ice1712/amp.c +++ b/sound/pci/ice1712/amp.c @@ -25,7 +25,6 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/init.h> -#include <linux/slab.h> #include <sound/core.h> #include "ice1712.h" diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c index 7f9674b641c0..4c551e147c08 100644 --- a/sound/pci/ice1712/vt1720_mobo.c +++ b/sound/pci/ice1712/vt1720_mobo.c @@ -25,7 +25,6 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/init.h> -#include <linux/slab.h> #include <sound/core.h> #include "ice1712.h" diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c index 5af9e84456d1..e618f789026e 100644 --- a/sound/pci/ice1712/wtm.c +++ b/sound/pci/ice1712/wtm.c @@ -29,7 +29,6 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/init.h> -#include <linux/slab.h> #include <sound/core.h> #include "ice1712.h" diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index 0cca56038cd9..ef9af3f4ace2 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c @@ -26,6 +26,7 @@ #include <linux/init.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/slab.h> #include <sound/initval.h> #include <sound/control.h> diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index b64e78139d63..b56e33676780 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c @@ -849,6 +849,7 @@ struct snd_m3 { struct snd_kcontrol *master_switch; struct snd_kcontrol *master_volume; struct tasklet_struct hwvol_tq; + unsigned int in_suspend; #ifdef CONFIG_PM u16 *suspend_mem; @@ -884,6 +885,7 @@ static DEFINE_PCI_DEVICE_TABLE(snd_m3_ids) = { MODULE_DEVICE_TABLE(pci, snd_m3_ids); static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = { + SND_PCI_QUIRK(0x0E11, 0x0094, "Compaq Evo N600c", 0x0c), SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d), SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d), SND_PCI_QUIRK(0x1033, 0x80f1, "NEC LM800J/7", 0x03), @@ -1613,6 +1615,11 @@ static void snd_m3_update_hw_volume(unsigned long private_data) outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER); outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER); + /* Ignore spurious HV interrupts during suspend / resume, this avoids + mistaking them for a mute button press. */ + if (chip->in_suspend) + return; + if (!chip->master_switch || !chip->master_volume) return; @@ -2424,6 +2431,7 @@ static int m3_suspend(struct pci_dev *pci, pm_message_t state) if (chip->suspend_mem == NULL) return 0; + chip->in_suspend = 1; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); @@ -2497,6 +2505,7 @@ static int m3_resume(struct pci_dev *pci) snd_m3_hv_init(chip); snd_power_change_state(card, SNDRV_CTL_POWER_D0); + chip->in_suspend = 0; return 0; } #endif /* CONFIG_PM */ diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 7e8e7da592a9..3be8f97c8bc0 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -27,6 +27,7 @@ #include <linux/dma-mapping.h> #include <linux/moduleparam.h> #include <linux/mutex.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/initval.h> @@ -1161,13 +1162,15 @@ static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private unsigned long count, unsigned long pos) { struct mixart_mgr *mgr = entry->private_data; + unsigned long maxsize; - count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ - if(count <= 0) + if (pos >= MIXART_BA0_SIZE) return 0; - if(pos + count > MIXART_BA0_SIZE) - count = (long)(MIXART_BA0_SIZE - pos); - if(copy_to_user_fromio(buf, MIXART_MEM( mgr, pos ), count)) + maxsize = MIXART_BA0_SIZE - pos; + if (count > maxsize) + count = maxsize; + count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ + if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count)) return -EFAULT; return count; } @@ -1180,13 +1183,15 @@ static long snd_mixart_BA1_read(struct snd_info_entry *entry, void *file_private unsigned long count, unsigned long pos) { struct mixart_mgr *mgr = entry->private_data; + unsigned long maxsize; - count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ - if(count <= 0) + if (pos > MIXART_BA1_SIZE) return 0; - if(pos + count > MIXART_BA1_SIZE) - count = (long)(MIXART_BA1_SIZE - pos); - if(copy_to_user_fromio(buf, MIXART_REG( mgr, pos ), count)) + maxsize = MIXART_BA1_SIZE - pos; + if (count > maxsize) + count = maxsize; + count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ + if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count)) return -EFAULT; return count; } diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index 4cf4cd8c939c..bf2696aa5d49 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c @@ -24,6 +24,7 @@ #include <linux/pci.h> #include <linux/firmware.h> #include <linux/vmalloc.h> +#include <linux/slab.h> #include <asm/io.h> #include <sound/core.h> #include "mixart.h" diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index 9c5e6450eebb..fad03d64e3ad 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c @@ -21,6 +21,7 @@ #include <linux/interrupt.h> #include <linux/mutex.h> #include <linux/pci.h> +#include <linux/slab.h> #include <sound/ac97_codec.h> #include <sound/asoundef.h> #include <sound/core.h> diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index 7754db166d9e..dbc4b89d74e4 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c @@ -68,7 +68,7 @@ static void wm8776_write(struct oxygen *chip, OXYGEN_SPI_CEN_LATCH_CLOCK_LO, (reg << 9) | value); if (reg < ARRAY_SIZE(data->wm8776_regs)) { - if (reg >= WM8776_HPLVOL || reg <= WM8776_DACMASTER) + if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER) value &= ~WM8776_UPDATE; data->wm8776_regs[reg] = value; } diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 960a227eb653..ad4462677615 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c @@ -1974,9 +1974,9 @@ snd_riptide_proc_read(struct snd_info_entry *entry, } snd_iprintf(buffer, "Paths:\n"); i = getpaths(cif, p); - while (i--) { - snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]); - i--; + while (i >= 2) { + i -= 2; + snd_iprintf(buffer, "%x->%x ", p[i], p[i + 1]); } snd_iprintf(buffer, "\n"); } diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index d5e1c6eb7b7b..3c04524de37c 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -70,10 +70,10 @@ #include <linux/delay.h> +#include <linux/gfp.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <sound/core.h> diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 9d5252bc870c..d19dc052c391 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -27,7 +27,6 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <sound/core.h> diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 52c6eb57cc3f..b92adef8e81e 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -24,7 +24,6 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/interrupt.h> -#include <linux/slab.h> #include <linux/pci.h> #include <linux/firmware.h> #include <linux/moduleparam.h> diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 3d72c1effeef..547b713d7204 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -2479,7 +2479,7 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol, on MADICARD - playback mixer matrix: [channelout+64] [output] [value] - input(thru) mixer matrix: [channelin] [output] [value] - (better do 2 kontrols for seperation ?) + (better do 2 kontrols for separation ?) */ #define HDSPM_MIXER(xname, xindex) \ diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 44a3e2d8c556..c492af5b25f3 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -24,7 +24,6 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/pci.h> -#include <linux/slab.h> #include <linux/moduleparam.h> #include <sound/core.h> diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 7e3e8fbc90fe..9cc1b5aa0148 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -24,6 +24,7 @@ #include <linux/init.h> #include <linux/pci.h> #include <linux/time.h> +#include <linux/slab.h> #include <linux/moduleparam.h> #include <linux/interrupt.h> #include <linux/delay.h> diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index 5d2afa0b0ce4..9dce0bde5c05 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c @@ -19,6 +19,7 @@ */ #include <linux/delay.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/info.h> #include "pdaudiocf.h" diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 0d668f471620..43f995a3f960 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -20,7 +20,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/slab.h> #include <linux/delay.h> #include <sound/core.h> #include <sound/asoundef.h> diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 7be3b3357045..cfd1438bcc64 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -21,6 +21,7 @@ #include <linux/init.h> #include <linux/moduleparam.h> +#include <linux/slab.h> #include <sound/core.h> #include "vxpocket.h" #include <pcmcia/ciscode.h> diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c index 1f72e1c786bf..00e2d5166d0a 100644 --- a/sound/ppc/burgundy.c +++ b/sound/ppc/burgundy.c @@ -21,7 +21,6 @@ #include <asm/io.h> #include <linux/init.h> -#include <linux/slab.h> #include <linux/delay.h> #include <sound/core.h> #include "pmac.h" diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index d06f780bd7e8..8f064c7ce745 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -22,7 +22,6 @@ #include <linux/init.h> #include <linux/i2c.h> #include <linux/delay.h> -#include <linux/slab.h> #include <sound/core.h> #include "pmac.h" diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 53c81a547613..2f12da4da561 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -20,10 +20,10 @@ #include <linux/dma-mapping.h> #include <linux/dmapool.h> +#include <linux/gfp.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> -#include <linux/slab.h> #include <sound/asound.h> #include <sound/control.h> diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index 76d9ad27d91c..68e0dee4ff05 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c @@ -26,6 +26,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/initval.h> #include <sound/pcm.h> diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c index 9ef6b96373f5..3e6628c8e665 100644 --- a/sound/soc/atmel/atmel-pcm.c +++ b/sound/soc/atmel/atmel-pcm.c @@ -180,7 +180,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream, snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = params_buffer_bytes(params); - prtd->params = rtd->dai->cpu_dai->dma_data; + prtd->params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); prtd->params->dma_intr_handler = atmel_pcm_dma_irq; prtd->dma_buffer = runtime->dma_addr; diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c index e588e63f18d2..0b59806905d1 100644 --- a/sound/soc/atmel/atmel_ssc_dai.c +++ b/sound/soc/atmel/atmel_ssc_dai.c @@ -363,12 +363,12 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, ssc_p->dma_params[dir] = dma_params; /* - * The cpu_dai->dma_data field is only used to communicate the - * appropriate DMA parameters to the pcm driver hw_params() + * The snd_soc_pcm_stream->dma_data field is only used to communicate + * the appropriate DMA parameters to the pcm driver hw_params() * function. It should not be used for other purposes * as it is common to all substreams. */ - rtd->dai->cpu_dai->dma_data = dma_params; + snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_params); channels = params_channels(params); diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 340311d7fed5..a61ccd2d505f 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c @@ -17,6 +17,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/device.h> #include <linux/delay.h> #include <linux/mutex.h> diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 0cf2ca61c776..495be6e71931 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c @@ -18,6 +18,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/suspend.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 67cbfe7283da..5e7aacf3bb5a 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c @@ -29,8 +29,8 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/slab.h> #include <linux/dma-mapping.h> +#include <linux/gfp.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index e69322978739..523b7fc33f4e 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c @@ -16,6 +16,7 @@ #include <linux/interrupt.h> #include <linux/wait.h> #include <linux/delay.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index c6c6a4a7d948..1d2a1adf2575 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c @@ -29,8 +29,8 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/slab.h> #include <linux/dma-mapping.h> +#include <linux/gfp.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c index 5e03bb2f3cd7..6bac1ac1a315 100644 --- a/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c @@ -29,8 +29,8 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/slab.h> #include <linux/dma-mapping.h> +#include <linux/gfp.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index a1bbe16b7f96..1f5e57a4bb7a 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c @@ -13,6 +13,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/kernel.h> #include <linux/device.h> #include <sound/core.h> @@ -80,9 +81,11 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, static int ac97_soc_probe(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_card *card = socdev->card; struct snd_soc_codec *codec; struct snd_ac97_bus *ac97_bus; struct snd_ac97_template ac97_template; + int i; int ret = 0; printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION); @@ -102,12 +105,6 @@ static int ac97_soc_probe(struct platform_device *pdev) INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); - if (ret < 0) { - printk(KERN_ERR "ASoC: failed to init gen ac97 glue\n"); - goto err; - } - /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) @@ -123,6 +120,13 @@ static int ac97_soc_probe(struct platform_device *pdev) if (ret < 0) goto bus_err; + for (i = 0; i < card->num_links; i++) { + if (card->dai_link[i].codec_dai->ac97_control) { + snd_ac97_dev_add_pdata(codec->ac97, + card->dai_link[i].cpu_dai->ac97_pdata); + } + } + return 0; bus_err: diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 3c80137d5938..11b62dee842c 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -17,6 +17,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c index c233810d463d..240cd155b313 100644 --- a/sound/soc/codecs/ad1938.c +++ b/sound/soc/codecs/ad1938.c @@ -27,6 +27,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 39c0f7584e65..042072738cdc 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -12,6 +12,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index d2fcc601722c..475807bea2c2 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c @@ -11,6 +11,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c index cc96411ca3e6..f8e75edb27b7 100644 --- a/sound/soc/codecs/ads117x.c +++ b/sound/soc/codecs/ads117x.c @@ -11,6 +11,7 @@ */ #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/init.h> #include <linux/device.h> #include <sound/core.h> diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index b9ef7e45891d..bdeb10dfd887 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c @@ -10,6 +10,7 @@ */ #include <linux/module.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/soc.h> #include <sound/initval.h> @@ -90,12 +91,10 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg, if (reg >= codec->reg_cache_size) return -EINVAL; - reg &= AK4104_REG_MASK; - reg |= AK4104_WRITE; - /* only write to the hardware if value has changed */ if (cache[reg] != value) { - u8 tmp[2] = { reg, value }; + u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value }; + if (spi_write(spi, tmp, sizeof(tmp))) { dev_err(&spi->dev, "SPI write failed\n"); return -EIO; diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index ff966567e2ba..352d1d08dbd9 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -19,6 +19,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index 3ef16bbc8c83..729859cf6ca8 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -29,6 +29,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 82fca284d007..926797a014c7 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/i2c.h> #include <linux/delay.h> +#include <linux/slab.h> #include <sound/soc.h> #include <sound/soc-dapm.h> #include <sound/initval.h> diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index dfbeb2db61b3..81a62d198b70 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -23,6 +23,7 @@ #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/soc.h> #include <sound/initval.h> diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c index e000cdfec1ec..9f169c477108 100644 --- a/sound/soc/codecs/cx20442.c +++ b/sound/soc/codecs/cx20442.c @@ -14,6 +14,7 @@ */ #include <linux/tty.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/initval.h> diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index cf2975a7294a..366daf1d044e 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -23,6 +23,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c index 2afcd0a8669d..5a5f187a2657 100644 --- a/sound/soc/codecs/pcm3008.c +++ b/sound/soc/codecs/pcm3008.c @@ -19,6 +19,7 @@ #include <linux/kernel.h> #include <linux/device.h> #include <linux/gpio.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/initval.h> diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index d2ff1cde6883..29d0906a924a 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c @@ -33,6 +33,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 81b8c9dfe7fc..3293629dcb3b 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -15,6 +15,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/device.h> #include <sound/core.h> diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index da589d8664d0..776b79cde904 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -25,6 +25,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 357b609196e3..b5b7d6a03844 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c @@ -13,6 +13,7 @@ #include <linux/device.h> #include <linux/sysfs.h> #include <linux/spi/spi.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index e4b946a19ea3..4a6d56c3fed9 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -39,6 +39,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index f9f367d29a90..d1e0e81ef30c 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -31,6 +31,7 @@ #include <linux/interrupt.h> #include <linux/gpio.h> #include <linux/regulator/consumer.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -778,7 +779,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) if (dac33->fifo_mode) { /* Generic for all FIFO modes */ /* 50-51 : ASRC Control registers */ - dac33_write(codec, DAC33_ASRC_CTRL_A, (1 << 4)); /* div=2 */ + dac33_write(codec, DAC33_ASRC_CTRL_A, DAC33_SRCLKDIV(1)); dac33_write(codec, DAC33_ASRC_CTRL_B, 1); /* ??? */ /* Write registers 0x34 and 0x35 (MSB, LSB) */ @@ -1038,11 +1039,7 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, case SND_SOC_DAIFMT_DSP_A: aictrl_a |= DAC33_AFMT_DSP; aictrl_b &= ~DAC33_DATA_DELAY_MASK; - aictrl_b |= DAC33_DATA_DELAY(1); /* 1 bit delay */ - break; - case SND_SOC_DAIFMT_DSP_B: - aictrl_a |= DAC33_AFMT_DSP; - aictrl_b &= ~DAC33_DATA_DELAY_MASK; /* No delay */ + aictrl_b |= DAC33_DATA_DELAY(0); break; case SND_SOC_DAIFMT_RIGHT_J: aictrl_a |= DAC33_AFMT_RIGHT_J; @@ -1066,7 +1063,7 @@ static void dac33_init_chip(struct snd_soc_codec *codec) { /* 44-46: DAC Control Registers */ /* A : DAC sample rate Fsref/1.5 */ - dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(1)); + dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0)); /* B : DAC src=normal, not muted */ dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT | DAC33_DACSRCL_LEFT); diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 958d49c969ac..569ad8758a84 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -26,6 +26,7 @@ #include <linux/i2c.h> #include <linux/gpio.h> #include <linux/regulator/consumer.h> +#include <linux/slab.h> #include <sound/tpa6130a2-plat.h> #include <sound/soc.h> #include <sound/soc-dapm.h> diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 6f5d4af20052..520ffd6536c3 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -27,6 +27,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/i2c/twl.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c index 3e99fe5131dd..a8dcd5a5bbcb 100644 --- a/sound/soc/codecs/uda134x.c +++ b/sound/soc/codecs/uda134x.c @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/delay.h> +#include <linux/slab.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index a2763c2e7348..9cd0a66b7663 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -137,7 +137,7 @@ static void uda1380_flush_work(struct work_struct *work) { int bit, reg; - for_each_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { + for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { reg = 0x10 + bit; pr_debug("uda1380: flush reg %x val %x:\n", reg, uda1380_read_reg_cache(uda1380_codec, reg)); diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 217b02680597..002e289d1255 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -23,7 +23,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/version.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/firmware.h> @@ -32,6 +31,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/debugfs.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 718ef912e758..2e0772f9c456 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -13,6 +13,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/delay.h> #include <linux/pm.h> #include <linux/platform_device.h> @@ -1349,7 +1350,7 @@ static irqreturn_t wm8350_hp_jack_handler(int irq, void *data) int mask; struct wm8350_jack_data *jack = NULL; - switch (irq) { + switch (irq - wm8350->irq_base) { case WM8350_IRQ_CODEC_JCK_DET_L: jack = &priv->hpl; mask = WM8350_JACK_L_LVL; @@ -1424,7 +1425,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(irq, priv); + wm8350_hp_jack_handler(irq + wm8350->irq_base, priv); return 0; } @@ -1521,8 +1522,8 @@ 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_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); - wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); + wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv); + wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv); priv->hpl.jack = NULL; priv->hpr.jack = NULL; diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index b432f4d4a324..6acc885cf9b7 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/pm.h> diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index af8cb6995a1f..9000b1d19afb 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -19,6 +19,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index d3a61d7ea0c5..19cd47293424 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -19,6 +19,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index d077df6f5e75..8cc9042965eb 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c @@ -25,6 +25,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 24a35603bcf7..8ca3812f2f2f 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -20,6 +20,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c index 63a254e293ca..1072621e93fd 100644 --- a/sound/soc/codecs/wm8727.c +++ b/sound/soc/codecs/wm8727.c @@ -13,6 +13,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 3fb653ba363a..07adc375a706 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -18,6 +18,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 5a2619dbf283..e7c6bf163185 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -18,6 +18,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> +#include <linux/slab.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/spi/spi.h> diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 475c67ac7818..2916ed4d3844 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -20,6 +20,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index c2444e7c8480..613199a0f799 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -40,6 +40,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 44e7d9d82f87..60b1b3e1094b 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -20,6 +20,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index dbc368c08263..b7fd96adac64 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -24,6 +24,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 3595bd57c4eb..fa5f99fde68b 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -23,6 +23,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 593e47d0e0eb..c6f0abcc5711 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -19,6 +19,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 31e39ffd1d8e..0c04b476487f 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -30,6 +30,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 615dab2b62ef..c8d7a809af4d 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -18,6 +18,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index d07bcc1e1c60..f1e63e01b04d 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -15,6 +15,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index d2342c5e0425..50634ab76a5c 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -18,6 +18,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index d9540d55fc89..a65b781af512 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -20,6 +20,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index ee637af4737a..69708c4cc004 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -18,6 +18,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 28bb59ea6ea1..526f56b09066 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -19,6 +19,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 2862e4dced27..bb18c3ecfeb9 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -19,6 +19,7 @@ #include <linux/i2c.h> #include <linux/spi/spi.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index a54dc77b7f34..831f4730bfd5 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -18,6 +18,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -990,7 +991,7 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, reg = snd_soc_read(codec, WM8990_CLOCKING_2); snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC); - /* set up N , fractional mode and pre-divisor if neccessary */ + /* set up N , fractional mode and pre-divisor if necessary */ snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM | (pll_div.div2?WM8990_PRESCALE:0)); snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8)); diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index bf022f68b84f..03e8b1a6a56c 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -18,6 +18,7 @@ #include <linux/i2c.h> #include <linux/regulator/consumer.h> #include <linux/spi/spi.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 29f3771c33a4..9da0724cd47a 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -19,6 +19,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -3007,34 +3008,39 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: - /* Switch over to startup biases */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - WM8994_VMID_RAMP_MASK, - WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - (1 << WM8994_VMID_RAMP_SHIFT)); - - /* Disable main biases */ - snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, - WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0); + if (codec->bias_level == SND_SOC_BIAS_STANDBY) { + /* Switch over to startup biases */ + snd_soc_update_bits(codec, WM8994_ANTIPOP_2, + WM8994_BIAS_SRC | + WM8994_STARTUP_BIAS_ENA | + WM8994_VMID_BUF_ENA | + WM8994_VMID_RAMP_MASK, + WM8994_BIAS_SRC | + WM8994_STARTUP_BIAS_ENA | + WM8994_VMID_BUF_ENA | + (1 << WM8994_VMID_RAMP_SHIFT)); - /* Discharge line */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_1, - WM8994_LINEOUT1_DISCH | - WM8994_LINEOUT2_DISCH, - WM8994_LINEOUT1_DISCH | - WM8994_LINEOUT2_DISCH); + /* Disable main biases */ + snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, + WM8994_BIAS_ENA | + WM8994_VMID_SEL_MASK, 0); - msleep(5); + /* Discharge line */ + snd_soc_update_bits(codec, WM8994_ANTIPOP_1, + WM8994_LINEOUT1_DISCH | + WM8994_LINEOUT2_DISCH, + WM8994_LINEOUT1_DISCH | + WM8994_LINEOUT2_DISCH); - /* Switch off startup biases */ - snd_soc_update_bits(codec, WM8994_ANTIPOP_2, - WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | - WM8994_VMID_BUF_ENA | - WM8994_VMID_RAMP_MASK, 0); + msleep(5); + /* Switch off startup biases */ + snd_soc_update_bits(codec, WM8994_ANTIPOP_2, + WM8994_BIAS_SRC | + WM8994_STARTUP_BIAS_ENA | + WM8994_VMID_BUF_ENA | + WM8994_VMID_RAMP_MASK, 0); + } break; } codec->bias_level = level; @@ -3401,7 +3407,7 @@ struct snd_soc_dai wm8994_dai[] = { .rates = WM8994_RATES, .formats = WM8994_FORMATS, }, - .playback = { + .capture = { .stream_name = "AIF3 Capture", .channels_min = 2, .channels_max = 2, @@ -3730,11 +3736,12 @@ static int wm8994_codec_probe(struct platform_device *pdev) case 3: wm8994->hubs.dcs_codes = -5; wm8994->hubs.hp_startup_mode = 1; + wm8994->hubs.dcs_readback_mode = 1; break; default: + wm8994->hubs.dcs_readback_mode = 1; break; } - /* Remember if AIFnLRCLK is configured as a GPIO. This should be * configured on init - if a system wants to do this dynamically diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index c468497314ba..3a184fcb702b 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -18,6 +18,7 @@ #include <linux/pm.h> #include <linux/i2c.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index ec54c6da9856..8793341849d1 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c @@ -10,6 +10,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index e237bf615129..2f48a8aae22c 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -11,6 +11,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index ceb86b4ddb25..2fca514fde58 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -16,6 +16,7 @@ */ #include <linux/init.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/device.h> #include <sound/core.h> diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 0ad9f5d536c6..e1f225a3ac46 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -62,21 +62,27 @@ static const char *speaker_mode_text[] = { static const struct soc_enum speaker_mode = SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); -static void wait_for_dc_servo(struct snd_soc_codec *codec) +static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) { unsigned int reg; int count = 0; + unsigned int val; + + val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; + + /* Trigger the command */ + snd_soc_write(codec, WM8993_DC_SERVO_0, val); dev_dbg(codec->dev, "Waiting for DC servo...\n"); do { count++; msleep(1); - reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0); + reg = snd_soc_read(codec, WM8993_DC_SERVO_0); dev_dbg(codec->dev, "DC servo: %x\n", reg); - } while (reg & WM8993_DCS_DATAPATH_BUSY); + } while (reg & op && count < 400); - if (reg & WM8993_DCS_DATAPATH_BUSY) + if (reg & op) dev_err(codec->dev, "Timed out waiting for DC Servo\n"); } @@ -86,51 +92,58 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec) static void calibrate_dc_servo(struct snd_soc_codec *codec) { struct wm_hubs_data *hubs = codec->private_data; - u16 reg, dcs_cfg; + u16 reg, reg_l, reg_r, dcs_cfg; /* Set for 32 series updates */ snd_soc_update_bits(codec, WM8993_DC_SERVO_1, WM8993_DCS_SERIES_NO_01_MASK, 32 << WM8993_DCS_SERIES_NO_01_SHIFT); - - /* Enable the DC servo. Write all bits to avoid triggering startup - * or write calibration. - */ - snd_soc_update_bits(codec, WM8993_DC_SERVO_0, - 0xFFFF, - WM8993_DCS_ENA_CHAN_0 | - WM8993_DCS_ENA_CHAN_1 | - WM8993_DCS_TRIG_SERIES_1 | - WM8993_DCS_TRIG_SERIES_0); - - wait_for_dc_servo(codec); + wait_for_dc_servo(codec, + WM8993_DCS_TRIG_SERIES_0 | WM8993_DCS_TRIG_SERIES_1); /* Apply correction to DC servo result */ if (hubs->dcs_codes) { dev_dbg(codec->dev, "Applying %d code DC servo correction\n", hubs->dcs_codes); + /* Different chips in the family support different + * readback methods. + */ + switch (hubs->dcs_readback_mode) { + case 0: + reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) + & WM8993_DCS_INTEG_CHAN_0_MASK;; + reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) + & WM8993_DCS_INTEG_CHAN_1_MASK; + break; + case 1: + reg = snd_soc_read(codec, WM8993_DC_SERVO_3); + reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) + >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; + reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; + break; + default: + WARN(1, "Unknown DCS readback method"); + break; + } + /* HPOUT1L */ - reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) & - WM8993_DCS_INTEG_CHAN_0_MASK;; - reg += hubs->dcs_codes; - dcs_cfg = reg << WM8993_DCS_DAC_WR_VAL_1_SHIFT; + if (reg_l + hubs->dcs_codes > 0 && + reg_l + hubs->dcs_codes < 0xff) + reg_l += hubs->dcs_codes; + dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT; /* HPOUT1R */ - reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) & - WM8993_DCS_INTEG_CHAN_1_MASK; - reg += hubs->dcs_codes; - dcs_cfg |= reg; + if (reg_r + hubs->dcs_codes > 0 && + reg_r + hubs->dcs_codes < 0xff) + reg_r += hubs->dcs_codes; + dcs_cfg |= reg_r; /* Do it */ snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); - snd_soc_update_bits(codec, WM8993_DC_SERVO_0, - WM8993_DCS_TRIG_DAC_WR_0 | - WM8993_DCS_TRIG_DAC_WR_1, - WM8993_DCS_TRIG_DAC_WR_0 | - WM8993_DCS_TRIG_DAC_WR_1); - - wait_for_dc_servo(codec); + wait_for_dc_servo(codec, + WM8993_DCS_TRIG_DAC_WR_0 | + WM8993_DCS_TRIG_DAC_WR_1); } } @@ -141,10 +154,16 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct wm_hubs_data *hubs = codec->private_data; int ret; ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); + /* If we're applying an offset correction then updating the + * callibration would be likely to introduce further offsets. */ + if (hubs->dcs_codes) + return ret; + /* Only need to do this if the outputs are active */ if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index 420104fe9c90..e51c16683589 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h @@ -21,6 +21,7 @@ extern const unsigned int wm_hubs_spkmix_tlv[]; /* This *must* be the first element of the codec->private_data struct */ struct wm_hubs_data { int dcs_codes; + int dcs_readback_mode; int hp_startup_mode; }; diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 6362ca05506e..adadcd3aa1b1 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c @@ -12,6 +12,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/slab.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/clk.h> @@ -585,7 +586,8 @@ static int davinci_i2s_probe(struct platform_device *pdev) dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; davinci_i2s_dai.private_data = dev; - davinci_i2s_dai.dma_data = dev->dma_params; + davinci_i2s_dai.capture.dma_data = dev->dma_params; + davinci_i2s_dai.playback.dma_data = dev->dma_params; ret = snd_soc_register_dai(&davinci_i2s_dai); if (ret != 0) goto err_free_mem; diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index ab6518d86f18..79f0f4ad242c 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -18,6 +18,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/slab.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/clk.h> @@ -917,7 +918,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev) dma_data->channel = res->start; davinci_mcasp_dai[pdata->op_mode].private_data = dev; - davinci_mcasp_dai[pdata->op_mode].dma_data = dev->dma_params; + davinci_mcasp_dai[pdata->op_mode].capture.dma_data = dev->dma_params; + davinci_mcasp_dai[pdata->op_mode].playback.dma_data = dev->dma_params; davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev; ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]); diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 80c7fdf2f521..2dc406f42fe7 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c @@ -649,8 +649,10 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream) struct snd_pcm_hardware *ppcm; int ret = 0; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->dma_data; + struct davinci_pcm_dma_params *pa; struct davinci_pcm_dma_params *params; + + pa = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); if (!pa) return -ENODEV; params = &pa[substream->stream]; diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index b1a3a278819f..410c7496a18d 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -19,6 +19,7 @@ #include <linux/dma-mapping.h> #include <linux/interrupt.h> #include <linux/delay.h> +#include <linux/gfp.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 93f0f38a32c9..762c1b8e8e4e 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -14,6 +14,7 @@ #include <linux/interrupt.h> #include <linux/device.h> #include <linux/delay.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 30ed568afb2e..d639e55c5124 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -8,6 +8,7 @@ #include <linux/module.h> #include <linux/of_device.h> +#include <linux/slab.h> #include <sound/soc.h> diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index ef67d1cdffe7..83de1c81c8c4 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -9,6 +9,7 @@ * express or implied. */ +#include <linux/slab.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/of_device.h> diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c index 8bc5cd9e972f..3bc13fd89096 100644 --- a/sound/soc/fsl/soc-of-simple.c +++ b/sound/soc/fsl/soc-of-simple.c @@ -12,6 +12,7 @@ #include <linux/bitops.h> #include <linux/platform_device.h> #include <linux/of.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index c7d0fd9b7de8..7174b4c710de 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig @@ -1,6 +1,6 @@ config SND_IMX_SOC tristate "SoC Audio for Freescale i.MX CPUs" - depends on ARCH_MXC && BROKEN + depends on ARCH_MXC select SND_PCM select FIQ select SND_SOC_AC97_BUS diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index 19452e44afdc..2b31ac673ea4 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -19,6 +19,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/initval.h> @@ -70,7 +71,12 @@ static void imx_ssi_dma_callback(int channel, void *data) static void snd_imx_dma_err_callback(int channel, void *data, int err) { - pr_err("DMA error callback called\n"); + struct snd_pcm_substream *substream = data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; + struct snd_pcm_runtime *runtime = substream->runtime; + struct imx_pcm_runtime_data *iprtd = runtime->private_data; + int ret; pr_err("DMA timeout on channel %d -%s%s%s%s\n", channel, @@ -78,16 +84,26 @@ static void snd_imx_dma_err_callback(int channel, void *data, int err) err & IMX_DMA_ERR_REQUEST ? " request" : "", err & IMX_DMA_ERR_TRANSFER ? " transfer" : "", err & IMX_DMA_ERR_BUFFER ? " buffer" : ""); + + imx_dma_disable(iprtd->dma); + ret = imx_dma_setup_sg(iprtd->dma, iprtd->sg_list, iprtd->sg_count, + IMX_DMA_LENGTH_LOOP, dma_params->dma_addr, + substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? + DMA_MODE_WRITE : DMA_MODE_READ); + if (!ret) + imx_dma_enable(iprtd->dma); } static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; + struct imx_pcm_dma_params *dma_params; struct snd_pcm_runtime *runtime = substream->runtime; struct imx_pcm_runtime_data *iprtd = runtime->private_data; int ret; + dma_params = snd_soc_get_dma_data(rtd->dai->cpu_dai, substream); + iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH); if (iprtd->dma < 0) { pr_err("Failed to claim the audio DMA\n"); @@ -192,10 +208,12 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct imx_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; + struct imx_pcm_dma_params *dma_params; struct imx_pcm_runtime_data *iprtd = runtime->private_data; int err; + dma_params = snd_soc_get_dma_data(rtd->dai->cpu_dai, substream); + iprtd->substream = substream; iprtd->buf = (unsigned int *)substream->dma_buffer.area; iprtd->period_cnt = 0; diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c index d9cb9849b033..6b518e07eea9 100644 --- a/sound/soc/imx/imx-pcm-fiq.c +++ b/sound/soc/imx/imx-pcm-fiq.c @@ -19,6 +19,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/initval.h> @@ -38,23 +39,24 @@ struct imx_pcm_runtime_data { unsigned long offset; unsigned long last_offset; unsigned long size; - struct timer_list timer; - int poll_time; + struct hrtimer hrt; + int poll_time_ns; + struct snd_pcm_substream *substream; + atomic_t running; }; -static inline void imx_ssi_set_next_poll(struct imx_pcm_runtime_data *iprtd) +static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) { - iprtd->timer.expires = jiffies + iprtd->poll_time; -} - -static void imx_ssi_timer_callback(unsigned long data) -{ - struct snd_pcm_substream *substream = (void *)data; + struct imx_pcm_runtime_data *iprtd = + container_of(hrt, struct imx_pcm_runtime_data, hrt); + struct snd_pcm_substream *substream = iprtd->substream; struct snd_pcm_runtime *runtime = substream->runtime; - struct imx_pcm_runtime_data *iprtd = runtime->private_data; struct pt_regs regs; unsigned long delta; + if (!atomic_read(&iprtd->running)) + return HRTIMER_NORESTART; + get_fiq_regs(®s); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -71,16 +73,14 @@ static void imx_ssi_timer_callback(unsigned long data) /* If we've transferred at least a period then report it and * reset our poll time */ - if (delta >= runtime->period_size) { + if (delta >= iprtd->period) { snd_pcm_period_elapsed(substream); iprtd->last_offset = iprtd->offset; - - imx_ssi_set_next_poll(iprtd); } - /* Restart the timer; if we didn't report we'll run on the next tick */ - add_timer(&iprtd->timer); + hrtimer_forward_now(hrt, ns_to_ktime(iprtd->poll_time_ns)); + return HRTIMER_RESTART; } static struct fiq_handler fh = { @@ -98,8 +98,8 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, iprtd->period = params_period_bytes(params) ; iprtd->offset = 0; iprtd->last_offset = 0; - iprtd->poll_time = HZ / (params_rate(params) / params_period_size(params)); - + iprtd->poll_time_ns = 1000000000 / params_rate(params) * + params_period_size(params); snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); return 0; @@ -134,8 +134,9 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - imx_ssi_set_next_poll(iprtd); - add_timer(&iprtd->timer); + atomic_set(&iprtd->running, 1); + hrtimer_start(&iprtd->hrt, ns_to_ktime(iprtd->poll_time_ns), + HRTIMER_MODE_REL); if (++fiq_enable == 1) enable_fiq(imx_pcm_fiq); @@ -144,11 +145,11 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - del_timer(&iprtd->timer); + atomic_set(&iprtd->running, 0); + if (--fiq_enable == 0) disable_fiq(imx_pcm_fiq); - break; default: return -EINVAL; @@ -179,7 +180,7 @@ static struct snd_pcm_hardware snd_imx_hardware = { .buffer_bytes_max = IMX_SSI_DMABUF_SIZE, .period_bytes_min = 128, .period_bytes_max = 16 * 1024, - .periods_min = 2, + .periods_min = 4, .periods_max = 255, .fifo_size = 0, }; @@ -193,9 +194,11 @@ static int snd_imx_open(struct snd_pcm_substream *substream) iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); runtime->private_data = iprtd; - init_timer(&iprtd->timer); - iprtd->timer.data = (unsigned long)substream; - iprtd->timer.function = imx_ssi_timer_callback; + iprtd->substream = substream; + + atomic_set(&iprtd->running, 0); + hrtimer_init(&iprtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + iprtd->hrt.function = snd_hrtimer_callback; ret = snd_pcm_hw_constraint_integer(substream->runtime, SNDRV_PCM_HW_PARAM_PERIODS); @@ -211,7 +214,8 @@ static int snd_imx_close(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct imx_pcm_runtime_data *iprtd = runtime->private_data; - del_timer_sync(&iprtd->timer); + hrtimer_cancel(&iprtd->hrt); + kfree(iprtd); return 0; diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 56f46a75d297..80b4fee2442b 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c @@ -39,6 +39,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/initval.h> @@ -234,17 +235,20 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct imx_ssi *ssi = cpu_dai->private_data; + struct imx_pcm_dma_params *dma_data; u32 reg, sccr; /* Tx/Rx config */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { reg = SSI_STCCR; - cpu_dai->dma_data = &ssi->dma_params_tx; + dma_data = &ssi->dma_params_tx; } else { reg = SSI_SRCCR; - cpu_dai->dma_data = &ssi->dma_params_rx; + dma_data = &ssi->dma_params_rx; } + snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); + sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK; /* DAI data (word) size */ @@ -652,7 +656,8 @@ static int imx_ssi_probe(struct platform_device *pdev) dai->private_data = ssi; if ((cpu_is_mx27() || cpu_is_mx21()) && - !(ssi->flags & IMX_SSI_USE_AC97)) { + !(ssi->flags & IMX_SSI_USE_AC97) && + (ssi->flags & IMX_SSI_DMA)) { ssi->flags |= IMX_SSI_DMA; platform = imx_ssi_dma_mx2_init(pdev, ssi); } else diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c index ad8df6cfae88..1dab4c14874d 100644 --- a/sound/soc/omap/mcpdm.c +++ b/sound/soc/omap/mcpdm.c @@ -25,6 +25,7 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/wait.h> +#include <linux/slab.h> #include <linux/interrupt.h> #include <linux/err.h> #include <linux/clk.h> diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index d29725664185..8ad9dc901007 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -39,6 +39,14 @@ #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) +#define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \ + xhandler_get, xhandler_put) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = omap_mcbsp_st_info_volsw, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = (unsigned long) &(struct soc_mixer_control) \ + {.min = xmin, .max = xmax} } + struct omap_mcbsp_data { unsigned int bus_id; struct omap_mcbsp_reg_cfg regs; @@ -82,11 +90,11 @@ static const int omap1_dma_reqs[][2] = {}; static const unsigned long omap1_mcbsp_port[][2] = {}; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) static const int omap24xx_dma_reqs[][2] = { { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX }, { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX }, -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) { OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX }, { OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX }, { OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX }, @@ -124,7 +132,7 @@ static const unsigned long omap2430_mcbsp_port[][2] = { static const unsigned long omap2430_mcbsp_port[][2] = {}; #endif -#if defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP3) static const unsigned long omap34xx_mcbsp_port[][2] = { { OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR, OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR }, @@ -289,7 +297,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; omap_mcbsp_dai_dma_params[id][substream->stream].data_type = OMAP_DMA_DATA_TYPE_S16; - cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; + + snd_soc_dai_set_dma_data(cpu_dai, substream, + &omap_mcbsp_dai_dma_params[id][substream->stream]); if (mcbsp_data->configured) { /* McBSP already configured by another stream */ @@ -639,6 +649,136 @@ struct snd_soc_dai omap_mcbsp_dai[] = { EXPORT_SYMBOL_GPL(omap_mcbsp_dai); +int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + int max = mc->max; + int min = mc->min; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = min; + uinfo->value.integer.max = max; + return 0; +} + +#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel) \ +static int \ +omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ + struct snd_ctl_elem_value *uc) \ +{ \ + struct soc_mixer_control *mc = \ + (struct soc_mixer_control *)kc->private_value; \ + int max = mc->max; \ + int min = mc->min; \ + int val = uc->value.integer.value[0]; \ + \ + if (val < min || val > max) \ + return -EINVAL; \ + \ + /* OMAP McBSP implementation uses index values 0..4 */ \ + return omap_st_set_chgain((id)-1, channel, val); \ +} + +#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel) \ +static int \ +omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ + struct snd_ctl_elem_value *uc) \ +{ \ + s16 chgain; \ + \ + if (omap_st_get_chgain((id)-1, channel, &chgain)) \ + return -EAGAIN; \ + \ + uc->value.integer.value[0] = chgain; \ + return 0; \ +} + +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0) +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1) +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0) +OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0) +OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1) + +static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + u8 value = ucontrol->value.integer.value[0]; + + if (value == omap_st_is_enabled(mc->reg)) + return 0; + + if (value) + omap_st_enable(mc->reg); + else + omap_st_disable(mc->reg); + + return 1; +} + +static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + + ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg); + return 0; +} + +static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { + SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, + omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", + -32768, 32767, + omap_mcbsp2_get_st_ch0_volume, + omap_mcbsp2_set_st_ch0_volume), + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", + -32768, 32767, + omap_mcbsp2_get_st_ch1_volume, + omap_mcbsp2_set_st_ch1_volume), +}; + +static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { + SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, + omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", + -32768, 32767, + omap_mcbsp3_get_st_ch0_volume, + omap_mcbsp3_set_st_ch0_volume), + OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", + -32768, 32767, + omap_mcbsp3_get_st_ch1_volume, + omap_mcbsp3_set_st_ch1_volume), +}; + +int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id) +{ + if (!cpu_is_omap34xx()) + return -ENODEV; + + switch (mcbsp_id) { + case 1: /* McBSP 2 */ + return snd_soc_add_controls(codec, omap_mcbsp2_st_controls, + ARRAY_SIZE(omap_mcbsp2_st_controls)); + case 2: /* McBSP 3 */ + return snd_soc_add_controls(codec, omap_mcbsp3_st_controls, + ARRAY_SIZE(omap_mcbsp3_st_controls)); + default: + break; + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); + static int __init snd_omap_mcbsp_init(void) { return snd_soc_register_dais(omap_mcbsp_dai, diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index 647d2f981ab0..6c363e5f4387 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h @@ -50,11 +50,13 @@ enum omap_mcbsp_div { #undef NUM_LINKS #define NUM_LINKS 3 #endif -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) #undef NUM_LINKS #define NUM_LINKS 5 #endif extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS]; +int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id); + #endif diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 25f19e4728bf..b7f4f7e015f3 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -150,7 +150,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, int stream = substream->stream; int channels, err, link_mask = 0; - cpu_dai->dma_data = &omap_mcpdm_dai_dma_params[stream]; + snd_soc_dai_set_dma_data(cpu_dai, substream, + &omap_mcpdm_dai_dma_params[stream]); channels = params_channels(params); switch (channels) { diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 825db385f01f..1e521904ea64 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -23,6 +23,7 @@ */ #include <linux/dma-mapping.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -60,12 +61,11 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data) struct omap_runtime_data *prtd = runtime->private_data; unsigned long flags; - if ((cpu_is_omap1510()) && - (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) { + if ((cpu_is_omap1510())) { /* * OMAP1510 doesn't fully support DMA progress counter * and there is no software emulation implemented yet, - * so have to maintain our own playback progress counter + * so have to maintain our own progress counters * that can be used by omap_pcm_pointer() instead. */ spin_lock_irqsave(&prtd->lock, flags); @@ -100,9 +100,11 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct omap_runtime_data *prtd = runtime->private_data; - struct omap_pcm_dma_data *dma_data = rtd->dai->cpu_dai->dma_data; + struct omap_pcm_dma_data *dma_data; int err = 0; + dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + /* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ if (!dma_data) @@ -189,8 +191,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) dma_params.frame_count = runtime->periods; omap_set_dma_params(prtd->dma_ch, &dma_params); - if ((cpu_is_omap1510()) && - (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) + if ((cpu_is_omap1510())) omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); else @@ -248,14 +249,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) dma_addr_t ptr; snd_pcm_uframes_t offset; - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + if (cpu_is_omap1510()) { + offset = prtd->period_index * runtime->period_size; + } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { ptr = omap_get_dma_dst_pos(prtd->dma_ch); offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); - } else if (!(cpu_is_omap1510())) { + } else { ptr = omap_get_dma_src_pos(prtd->dma_ch); offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); - } else - offset = prtd->period_index * runtime->period_size; + } if (offset >= runtime->buffer_size) offset = 0; diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index e69397f40f72..544fd9566f4d 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/io.h> @@ -42,11 +43,14 @@ * SSP audio private data */ struct ssp_priv { - struct ssp_dev dev; + struct ssp_device *ssp; unsigned int sysclk; int dai_fmt; #ifdef CONFIG_PM - struct ssp_state state; + uint32_t cr0; + uint32_t cr1; + uint32_t to; + uint32_t psp; #endif }; @@ -61,6 +65,22 @@ static void dump_registers(struct ssp_device *ssp) ssp_read_reg(ssp, SSACD)); } +static void ssp_enable(struct ssp_device *ssp) +{ + uint32_t sscr0; + + sscr0 = __raw_readl(ssp->mmio_base + SSCR0) | SSCR0_SSE; + __raw_writel(sscr0, ssp->mmio_base + SSCR0); +} + +static void ssp_disable(struct ssp_device *ssp) +{ + uint32_t sscr0; + + sscr0 = __raw_readl(ssp->mmio_base + SSCR0) & ~SSCR0_SSE; + __raw_writel(sscr0, ssp->mmio_base + SSCR0); +} + struct pxa2xx_pcm_dma_data { struct pxa2xx_pcm_dma_params params; char name[20]; @@ -94,19 +114,17 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_device *ssp = priv->ssp; int ret = 0; if (!cpu_dai->active) { - priv->dev.port = cpu_dai->id + 1; - priv->dev.irq = NO_IRQ; - clk_enable(priv->dev.ssp->clk); - ssp_disable(&priv->dev); + clk_enable(ssp->clk); + ssp_disable(ssp); } - if (cpu_dai->dma_data) { - kfree(cpu_dai->dma_data); - cpu_dai->dma_data = NULL; - } + kfree(snd_soc_dai_get_dma_data(cpu_dai, substream)); + snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); + return ret; } @@ -116,16 +134,15 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_device *ssp = priv->ssp; if (!cpu_dai->active) { - ssp_disable(&priv->dev); - clk_disable(priv->dev.ssp->clk); + ssp_disable(ssp); + clk_disable(ssp->clk); } - if (cpu_dai->dma_data) { - kfree(cpu_dai->dma_data); - cpu_dai->dma_data = NULL; - } + kfree(snd_soc_dai_get_dma_data(cpu_dai, substream)); + snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); } #ifdef CONFIG_PM @@ -133,27 +150,39 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) { struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_device *ssp = priv->ssp; if (!cpu_dai->active) - clk_enable(priv->dev.ssp->clk); + clk_enable(ssp->clk); - ssp_save_state(&priv->dev, &priv->state); - clk_disable(priv->dev.ssp->clk); + priv->cr0 = __raw_readl(ssp->mmio_base + SSCR0); + priv->cr1 = __raw_readl(ssp->mmio_base + SSCR1); + priv->to = __raw_readl(ssp->mmio_base + SSTO); + priv->psp = __raw_readl(ssp->mmio_base + SSPSP); + ssp_disable(ssp); + clk_disable(ssp->clk); return 0; } static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) { struct ssp_priv *priv = cpu_dai->private_data; + struct ssp_device *ssp = priv->ssp; + uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE; - clk_enable(priv->dev.ssp->clk); - ssp_restore_state(&priv->dev, &priv->state); + clk_enable(ssp->clk); + + __raw_writel(sssr, ssp->mmio_base + SSSR); + __raw_writel(priv->cr0 & ~SSCR0_SSE, ssp->mmio_base + SSCR0); + __raw_writel(priv->cr1, ssp->mmio_base + SSCR1); + __raw_writel(priv->to, ssp->mmio_base + SSTO); + __raw_writel(priv->psp, ssp->mmio_base + SSPSP); if (cpu_dai->active) - ssp_enable(&priv->dev); + ssp_enable(ssp); else - clk_disable(priv->dev.ssp->clk); + clk_disable(ssp->clk); return 0; } @@ -203,7 +232,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct ssp_priv *priv = cpu_dai->private_data; - struct ssp_device *ssp = priv->dev.ssp; + struct ssp_device *ssp = priv->ssp; int val; u32 sscr0 = ssp_read_reg(ssp, SSCR0) & @@ -244,11 +273,11 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, /* The SSP clock must be disabled when changing SSP clock mode * on PXA2xx. On PXA3xx it must be enabled when doing so. */ if (!cpu_is_pxa3xx()) - clk_disable(priv->dev.ssp->clk); + clk_disable(ssp->clk); val = ssp_read_reg(ssp, SSCR0) | sscr0; ssp_write_reg(ssp, SSCR0, val); if (!cpu_is_pxa3xx()) - clk_enable(priv->dev.ssp->clk); + clk_enable(ssp->clk); return 0; } @@ -260,7 +289,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) { struct ssp_priv *priv = cpu_dai->private_data; - struct ssp_device *ssp = priv->dev.ssp; + struct ssp_device *ssp = priv->ssp; int val; switch (div_id) { @@ -311,7 +340,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { struct ssp_priv *priv = cpu_dai->private_data; - struct ssp_device *ssp = priv->dev.ssp; + struct ssp_device *ssp = priv->ssp; u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70; #if defined(CONFIG_PXA3xx) @@ -380,7 +409,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) { struct ssp_priv *priv = cpu_dai->private_data; - struct ssp_device *ssp = priv->dev.ssp; + struct ssp_device *ssp = priv->ssp; u32 sscr0; sscr0 = ssp_read_reg(ssp, SSCR0); @@ -415,7 +444,7 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, int tristate) { struct ssp_priv *priv = cpu_dai->private_data; - struct ssp_device *ssp = priv->dev.ssp; + struct ssp_device *ssp = priv->ssp; u32 sscr1; sscr1 = ssp_read_reg(ssp, SSCR1); @@ -437,7 +466,7 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { struct ssp_priv *priv = cpu_dai->private_data; - struct ssp_device *ssp = priv->dev.ssp; + struct ssp_device *ssp = priv->ssp; u32 sscr0; u32 sscr1; u32 sspsp; @@ -532,25 +561,29 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct ssp_priv *priv = cpu_dai->private_data; - struct ssp_device *ssp = priv->dev.ssp; + struct ssp_device *ssp = priv->ssp; int chn = params_channels(params); u32 sscr0; u32 sspsp; int width = snd_pcm_format_physical_width(params_format(params)); int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf; + struct pxa2xx_pcm_dma_params *dma_data; + + dma_data = snd_soc_dai_get_dma_data(dai, substream); /* generate correct DMA params */ - if (cpu_dai->dma_data) - kfree(cpu_dai->dma_data); + kfree(dma_data); /* Network mode with one active slot (ttsa == 1) can be used * to force 16-bit frame width on the wire (for S16_LE), even * with two channels. Use 16-bit DMA transfers for this case. */ - cpu_dai->dma_data = ssp_get_dma_params(ssp, + dma_data = ssp_get_dma_params(ssp, ((chn == 2) && (ttsa != 1)) || (width == 32), substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + snd_soc_dai_set_dma_data(dai, substream, dma_data); + /* we can only change the settings if the port is not in use */ if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) return 0; @@ -642,12 +675,12 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; int ret = 0; struct ssp_priv *priv = cpu_dai->private_data; - struct ssp_device *ssp = priv->dev.ssp; + struct ssp_device *ssp = priv->ssp; int val; switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: - ssp_enable(&priv->dev); + ssp_enable(ssp); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: val = ssp_read_reg(ssp, SSCR1); @@ -666,7 +699,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, else val |= SSCR1_RSRE; ssp_write_reg(ssp, SSCR1, val); - ssp_enable(&priv->dev); + ssp_enable(ssp); break; case SNDRV_PCM_TRIGGER_STOP: val = ssp_read_reg(ssp, SSCR1); @@ -677,7 +710,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, ssp_write_reg(ssp, SSCR1, val); break; case SNDRV_PCM_TRIGGER_SUSPEND: - ssp_disable(&priv->dev); + ssp_disable(ssp); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: val = ssp_read_reg(ssp, SSCR1); @@ -707,8 +740,8 @@ static int pxa_ssp_probe(struct platform_device *pdev, if (!priv) return -ENOMEM; - priv->dev.ssp = ssp_request(dai->id + 1, "SoC audio"); - if (priv->dev.ssp == NULL) { + priv->ssp = ssp_request(dai->id + 1, "SoC audio"); + if (priv->ssp == NULL) { ret = -ENODEV; goto err_priv; } @@ -727,7 +760,7 @@ static void pxa_ssp_remove(struct platform_device *pdev, struct snd_soc_dai *dai) { struct ssp_priv *priv = dai->private_data; - ssp_free(priv->dev.ssp); + ssp_free(priv->ssp); } #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index e9ae7b3a7e00..d314115e3dd7 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -122,11 +122,14 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct pxa2xx_pcm_dma_params *dma_data; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out; + dma_data = &pxa2xx_ac97_pcm_stereo_out; else - cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in; + dma_data = &pxa2xx_ac97_pcm_stereo_in; + + snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); return 0; } @@ -137,11 +140,14 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct pxa2xx_pcm_dma_params *dma_data; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out; + dma_data = &pxa2xx_ac97_pcm_aux_mono_out; else - cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in; + dma_data = &pxa2xx_ac97_pcm_aux_mono_in; + + snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); return 0; } @@ -156,7 +162,8 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) return -ENODEV; else - cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in; + snd_soc_dai_set_dma_data(cpu_dai, substream, + &pxa2xx_ac97_pcm_mic_mono_in); return 0; } diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 6b8f655d1ad8..c1a5275721e4 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -164,6 +164,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct pxa2xx_pcm_dma_params *dma_data; BUG_ON(IS_ERR(clk_i2s)); clk_enable(clk_i2s); @@ -171,9 +172,11 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, pxa_i2s_wait(); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out; + dma_data = &pxa2xx_i2s_pcm_stereo_out; else - cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in; + dma_data = &pxa2xx_i2s_pcm_stereo_in; + + snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); /* is port used by another stream */ if (!(SACR0 & SACR0_ENB)) { diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index d38e39575f51..adc7e6f15f93 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -25,9 +25,11 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct pxa2xx_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; + struct pxa2xx_pcm_dma_params *dma; int ret; + dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); + /* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ if (!dma) diff --git a/sound/soc/s3c24xx/s3c-ac97.c b/sound/soc/s3c24xx/s3c-ac97.c index ee8ed9d7e703..ecf4fd04ae96 100644 --- a/sound/soc/s3c24xx/s3c-ac97.c +++ b/sound/soc/s3c24xx/s3c-ac97.c @@ -224,11 +224,14 @@ static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct s3c_dma_params *dma_data; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - cpu_dai->dma_data = &s3c_ac97_pcm_out; + dma_data = &s3c_ac97_pcm_out; else - cpu_dai->dma_data = &s3c_ac97_pcm_in; + dma_data = &s3c_ac97_pcm_in; + + snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); return 0; } @@ -238,8 +241,8 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, { u32 ac_glbctrl; struct snd_soc_pcm_runtime *rtd = substream->private_data; - int channel = ((struct s3c_dma_params *) - rtd->dai->cpu_dai->dma_data)->channel; + struct s3c_dma_params *dma_data = + snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) @@ -265,7 +268,7 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd, writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); + s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); return 0; } @@ -280,7 +283,7 @@ static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) return -ENODEV; else - cpu_dai->dma_data = &s3c_ac97_mic_in; + snd_soc_dai_set_dma_data(cpu_dai, substream, &s3c_ac97_mic_in); return 0; } @@ -290,8 +293,8 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, { u32 ac_glbctrl; struct snd_soc_pcm_runtime *rtd = substream->private_data; - int channel = ((struct s3c_dma_params *) - rtd->dai->cpu_dai->dma_data)->channel; + struct s3c_dma_params *dma_data = + snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; @@ -311,7 +314,7 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream, writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); - s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); + s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); return 0; } diff --git a/sound/soc/s3c24xx/s3c-dma.c b/sound/soc/s3c24xx/s3c-dma.c index 7725e26d6c91..1b61c23ff300 100644 --- a/sound/soc/s3c24xx/s3c-dma.c +++ b/sound/soc/s3c24xx/s3c-dma.c @@ -145,10 +145,12 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; struct s3c24xx_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct s3c_dma_params *dma = rtd->dai->cpu_dai->dma_data; unsigned long totbytes = params_buffer_bytes(params); + struct s3c_dma_params *dma = + snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); int ret = 0; + pr_debug("Entered %s\n", __func__); /* return if this is a bufferless transfer e.g. diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c index e994d8374fe6..88515946b6c0 100644 --- a/sound/soc/s3c24xx/s3c-i2s-v2.c +++ b/sound/soc/s3c24xx/s3c-i2s-v2.c @@ -339,14 +339,17 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai_link *dai = rtd->dai; struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai); + struct s3c_dma_params *dma_data; u32 iismod; pr_debug("Entered %s\n", __func__); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dai->cpu_dai->dma_data = i2s->dma_playback; + dma_data = i2s->dma_playback; else - dai->cpu_dai->dma_data = i2s->dma_capture; + dma_data = i2s->dma_capture; + + snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); /* Working copies of register */ iismod = readl(i2s->regs + S3C2412_IISMOD); @@ -394,8 +397,8 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); unsigned long irqs; int ret = 0; - int channel = ((struct s3c_dma_params *) - rtd->dai->cpu_dai->dma_data)->channel; + struct s3c_dma_params *dma_data = + snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); pr_debug("Entered %s\n", __func__); @@ -431,7 +434,7 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, * of the auto reload mechanism of S3C24XX. * This call won't bother S3C64XX. */ - s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); + s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); break; diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c index a98f40c3cd29..326f0a9e7e30 100644 --- a/sound/soc/s3c24xx/s3c-pcm.c +++ b/sound/soc/s3c24xx/s3c-pcm.c @@ -178,6 +178,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai_link *dai = rtd->dai; struct s3c_pcm_info *pcm = to_info(dai->cpu_dai); + struct s3c_dma_params *dma_data; void __iomem *regs = pcm->regs; struct clk *clk; int sclk_div, sync_div; @@ -187,9 +188,11 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream, dev_dbg(pcm->dev, "Entered %s\n", __func__); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dai->cpu_dai->dma_data = pcm->dma_playback; + dma_data = pcm->dma_playback; else - dai->cpu_dai->dma_data = pcm->dma_capture; + dma_data = pcm->dma_capture; + + snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); /* Strictly check for sample size */ switch (params_format(params)) { diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index 0bc5950b9f02..c3ac890a3986 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c @@ -242,14 +242,17 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct s3c_dma_params *dma_data; u32 iismod; pr_debug("Entered %s\n", __func__); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out; + dma_data = &s3c24xx_i2s_pcm_stereo_out; else - rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_in; + dma_data = &s3c24xx_i2s_pcm_stereo_in; + + snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_data); /* Working copies of register */ iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); @@ -258,13 +261,11 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: iismod &= ~S3C2410_IISMOD_16BIT; - ((struct s3c_dma_params *) - rtd->dai->cpu_dai->dma_data)->dma_size = 1; + dma_data->dma_size = 1; break; case SNDRV_PCM_FORMAT_S16_LE: iismod |= S3C2410_IISMOD_16BIT; - ((struct s3c_dma_params *) - rtd->dai->cpu_dai->dma_data)->dma_size = 2; + dma_data->dma_size = 2; break; default: return -EINVAL; @@ -280,8 +281,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, { int ret = 0; struct snd_soc_pcm_runtime *rtd = substream->private_data; - int channel = ((struct s3c_dma_params *) - rtd->dai->cpu_dai->dma_data)->channel; + struct s3c_dma_params *dma_data = + snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); pr_debug("Entered %s\n", __func__); @@ -300,7 +301,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, else s3c24xx_snd_txctrl(1); - s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); + s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index 93ed3aad1631..a72c251401ac 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c @@ -22,8 +22,8 @@ #include <sound/soc.h> #include <plat/regs-s3c2412-iis.h> -#include <plat/gpio-bank-d.h> -#include <plat/gpio-bank-e.h> +#include <mach/gpio-bank-d.h> +#include <mach/gpio-bank-e.h> #include <plat/gpio-cfg.h> #include <mach/map.h> diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c index c5cda187ecab..5b9ac1759bd2 100644 --- a/sound/soc/s6000/s6000-i2s.c +++ b/sound/soc/s6000/s6000-i2s.c @@ -16,6 +16,7 @@ #include <linux/clk.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> @@ -518,7 +519,8 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev) s6000_i2s_dai.dev = &pdev->dev; s6000_i2s_dai.private_data = dev; - s6000_i2s_dai.dma_data = &dev->dma_params; + s6000_i2s_dai.capture.dma_data = &dev->dma_params; + s6000_i2s_dai.playback.dma_data = &dev->dma_params; dev->sifbase = sifmem->start; dev->scbbase = mmio; diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c index 1d61109e09fa..9c7f7f00cebb 100644 --- a/sound/soc/s6000/s6000-pcm.c +++ b/sound/soc/s6000/s6000-pcm.c @@ -58,13 +58,15 @@ static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct s6000_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *par; int channel; unsigned int period_size; unsigned int dma_offset; dma_addr_t dma_pos; dma_addr_t src, dst; + par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + period_size = snd_pcm_lib_period_bytes(substream); dma_offset = prtd->period * period_size; dma_pos = runtime->dma_addr + dma_offset; @@ -101,7 +103,8 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data) { struct snd_pcm *pcm = data; struct snd_soc_pcm_runtime *runtime = pcm->private_data; - struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *params = + snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); struct s6000_runtime_data *prtd; unsigned int has_xrun; int i, ret = IRQ_NONE; @@ -172,11 +175,13 @@ static int s6000_pcm_start(struct snd_pcm_substream *substream) { struct s6000_runtime_data *prtd = substream->runtime->private_data; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *par; unsigned long flags; int srcinc; u32 dma; + par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + spin_lock_irqsave(&prtd->lock, flags); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -212,10 +217,12 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream) { struct s6000_runtime_data *prtd = substream->runtime->private_data; struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *par; unsigned long flags; u32 channel; + par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) channel = par->dma_out; else @@ -236,9 +243,11 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream) static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *par; int ret; + par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + ret = par->trigger(substream, cmd, 0); if (ret < 0) return ret; @@ -275,13 +284,15 @@ static int s6000_pcm_prepare(struct snd_pcm_substream *substream) static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *par; struct snd_pcm_runtime *runtime = substream->runtime; struct s6000_runtime_data *prtd = runtime->private_data; unsigned long flags; unsigned int offset; dma_addr_t count; + par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + spin_lock_irqsave(&prtd->lock, flags); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -305,11 +316,12 @@ static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream) static int s6000_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *par; struct snd_pcm_runtime *runtime = substream->runtime; struct s6000_runtime_data *prtd; int ret; + par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware); ret = snd_pcm_hw_constraint_step(runtime, 0, @@ -364,7 +376,7 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *par; int ret; ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); @@ -373,6 +385,8 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream, return ret; } + par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + if (par->same_rate) { spin_lock(&par->lock); if (par->rate == -1 || @@ -392,7 +406,8 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream, static int s6000_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; - struct s6000_pcm_dma_params *par = soc_runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *par = + snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); spin_lock(&par->lock); par->in_use &= ~(1 << substream->stream); @@ -417,7 +432,8 @@ static struct snd_pcm_ops s6000_pcm_ops = { static void s6000_pcm_free(struct snd_pcm *pcm) { struct snd_soc_pcm_runtime *runtime = pcm->private_data; - struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *params = + snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); free_irq(params->irq, pcm); snd_pcm_lib_preallocate_free_for_all(pcm); @@ -429,9 +445,11 @@ static int s6000_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { struct snd_soc_pcm_runtime *runtime = pcm->private_data; - struct s6000_pcm_dma_params *params = runtime->dai->cpu_dai->dma_data; + struct s6000_pcm_dma_params *params; int res; + params = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); + if (!card->dev->dma_mask) card->dev->dma_mask = &s6000_pcm_dmamask; if (!card->dev->coherent_dma_mask) diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 106674979b53..f07f6d8b93e1 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -32,6 +32,7 @@ config SND_SOC_SH4_SIU select DMA_ENGINE select DMADEVICES select SH_DMAE + select FW_LOADER ## ## Boards diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index baddb1242c71..0d8bdf07729c 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c @@ -13,6 +13,7 @@ */ #include <linux/module.h> +#include <linux/gfp.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 993abb730dfa..8dc966f45c36 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -19,6 +19,7 @@ #include <linux/list.h> #include <linux/pm_runtime.h> #include <linux/io.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/initval.h> diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h index 9cc04ab2bce7..c0bfab8fed3d 100644 --- a/sound/soc/sh/siu.h +++ b/sound/soc/sh/siu.h @@ -72,7 +72,7 @@ struct siu_firmware { #include <linux/interrupt.h> #include <linux/io.h> -#include <asm/dma-sh.h> +#include <asm/dmaengine.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c index 5452d19607e1..d86ee1bfc03a 100644 --- a/sound/soc/sh/siu_dai.c +++ b/sound/soc/sh/siu_dai.c @@ -22,6 +22,7 @@ #include <linux/delay.h> #include <linux/firmware.h> #include <linux/pm_runtime.h> +#include <linux/slab.h> #include <asm/clock.h> #include <asm/siu.h> diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index c5efc30f0136..8f85719212f9 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -24,7 +24,6 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/slab.h> #include <sound/control.h> #include <sound/core.h> @@ -32,7 +31,7 @@ #include <sound/pcm_params.h> #include <sound/soc-dai.h> -#include <asm/dma-sh.h> +#include <asm/dmaengine.h> #include <asm/siu.h> #include "siu.h" diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a03bac943aaf..ad7f9528d751 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -28,6 +28,7 @@ #include <linux/bitops.h> #include <linux/debugfs.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <sound/ac97_codec.h> #include <sound/core.h> #include <sound/pcm.h> @@ -427,24 +428,24 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (!runtime->hw.rates) { printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", codec_dai->name, cpu_dai->name); - goto machine_err; + goto config_err; } if (!runtime->hw.formats) { printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", codec_dai->name, cpu_dai->name); - goto machine_err; + goto config_err; } if (!runtime->hw.channels_min || !runtime->hw.channels_max) { printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", codec_dai->name, cpu_dai->name); - goto machine_err; + goto config_err; } /* Symmetry only applies if we've already got an active stream. */ if (cpu_dai->active || codec_dai->active) { ret = soc_pcm_apply_symmetry(substream); if (ret != 0) - goto machine_err; + goto config_err; } pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); @@ -464,10 +465,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) mutex_unlock(&pcm_mutex); return 0; -machine_err: +config_err: if (machine->ops && machine->ops->shutdown) machine->ops->shutdown(substream); +machine_err: + if (codec_dai->ops->shutdown) + codec_dai->ops->shutdown(substream, codec_dai); + codec_dai_err: if (platform->pcm_ops->close) platform->pcm_ops->close(substream); @@ -1544,7 +1549,8 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) mutex_unlock(&codec->mutex); return ret; } - if (card->dai_link[i].codec_dai->ac97_control) { + /* Check for codec->ac97 to handle the ac97.c fun */ + if (card->dai_link[i].codec_dai->ac97_control && codec->ac97) { snd_ac97_dev_add_pdata(codec->ac97, card->dai_link[i].cpu_dai->ac97_pdata); } diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6c3351095786..7c28f401f436 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -38,6 +38,7 @@ #include <linux/platform_device.h> #include <linux/jiffies.h> #include <linux/debugfs.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index 0f83bdb9b16f..612e18b4bf4e 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c @@ -16,6 +16,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/gfp.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index efed64b8b026..49cc7ea9a518 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c @@ -15,6 +15,7 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/scatterlist.h> +#include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c index 96deaefaa897..340a0bc5303e 100644 --- a/sound/sound_firmware.c +++ b/sound/sound_firmware.c @@ -2,7 +2,6 @@ #include <linux/module.h> #include <linux/fs.h> #include <linux/mm.h> -#include <linux/slab.h> #include <linux/sched.h> #include <asm/uaccess.h> #include "oss/sound_firmware.h" diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 8d13d933087d..7dcc06512e86 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -10,7 +10,6 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/slab.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/interrupt.h> diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 1d2e51b3f918..2eab6ce48852 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -58,6 +58,7 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/dma-mapping.h> +#include <linux/gfp.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c index 687e6a13689e..58a32a10d115 100644 --- a/sound/synth/emux/emux_proc.c +++ b/sound/synth/emux/emux_proc.c @@ -19,7 +19,6 @@ */ #include <linux/wait.h> -#include <linux/slab.h> #include <sound/core.h> #include <sound/emux_synth.h> #include <sound/info.h> diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 8c2925814ce4..c570ae3e6d55 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -22,13 +22,13 @@ config SND_USB_AUDIO will be called snd-usb-audio. config SND_USB_UA101 - tristate "Edirol UA-101 driver (EXPERIMENTAL)" + tristate "Edirol UA-101/UA-1000 driver (EXPERIMENTAL)" depends on EXPERIMENTAL select SND_PCM select SND_RAWMIDI help - Say Y here to include support for the Edirol UA-101 audio/MIDI - interface. + Say Y here to include support for the Edirol UA-101 and UA-1000 + audio/MIDI interfaces. To compile this driver as a module, choose M here: the module will be called snd-ua101. diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 86b2c3b92df5..4328cad6c3a2 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c @@ -17,6 +17,7 @@ */ #include <linux/spinlock.h> +#include <linux/slab.h> #include <linux/init.h> #include <linux/usb.h> #include <sound/core.h> diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index a3f02dd97440..afc5aeb68005 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/gfp.h> #include <linux/usb.h> #include <sound/initval.h> #include <sound/core.h> diff --git a/sound/usb/caiaq/midi.c b/sound/usb/caiaq/midi.c index 538e8c00d31a..2f218c77fff2 100644 --- a/sound/usb/caiaq/midi.c +++ b/sound/usb/caiaq/midi.c @@ -17,6 +17,7 @@ */ #include <linux/usb.h> +#include <linux/gfp.h> #include <sound/rawmidi.h> #include <sound/core.h> #include <sound/pcm.h> diff --git a/sound/usb/caiaq/midi.h b/sound/usb/caiaq/midi.h index 9d16db027fc3..380f984babc9 100644 --- a/sound/usb/caiaq/midi.h +++ b/sound/usb/caiaq/midi.h @@ -3,6 +3,6 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev); void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len); -void snd_usb_caiaq_midi_output_done(struct urb* urb); +void snd_usb_caiaq_midi_output_done(struct urb *urb); #endif /* CAIAQ_MIDI_H */ diff --git a/sound/usb/ua101.c b/sound/usb/ua101.c index 4f4ccdf70dd0..3d458d3b9962 100644 --- a/sound/usb/ua101.c +++ b/sound/usb/ua101.c @@ -1,5 +1,5 @@ /* - * Edirol UA-101 driver + * Edirol UA-101/UA-1000 driver * Copyright (c) Clemens Ladisch <clemens@ladisch.de> * * This driver is free software: you can redistribute it and/or modify @@ -25,13 +25,10 @@ #include <sound/pcm_params.h> #include "usbaudio.h" -MODULE_DESCRIPTION("Edirol UA-101 driver"); +MODULE_DESCRIPTION("Edirol UA-101/1000 driver"); MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101}}"); - -/* I use my UA-1A for testing because I don't have a UA-101 ... */ -#define UA1A_HACK +MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}"); /* * Should not be lower than the minimum scheduling delay of the host @@ -132,9 +129,6 @@ struct ua101 { dma_addr_t dma; } buffers[MAX_MEMORY_BUFFERS]; } capture, playback; - - unsigned int fps[10]; - unsigned int frame_counter; }; static DEFINE_MUTEX(devices_mutex); @@ -424,16 +418,6 @@ static void capture_urb_complete(struct urb *urb) if (do_period_elapsed) snd_pcm_period_elapsed(stream->substream); - /* for debugging: measure the sample rate relative to the USB clock */ - ua->fps[ua->frame_counter++ / ua->packets_per_second] += frames; - if (ua->frame_counter >= ARRAY_SIZE(ua->fps) * ua->packets_per_second) { - printk(KERN_DEBUG "capture rate:"); - for (frames = 0; frames < ARRAY_SIZE(ua->fps); ++frames) - printk(KERN_CONT " %u", ua->fps[frames]); - printk(KERN_CONT "\n"); - memset(ua->fps, 0, sizeof(ua->fps)); - ua->frame_counter = 0; - } return; stream_stopped: @@ -1200,13 +1184,30 @@ static int ua101_probe(struct usb_interface *interface, .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &midi_ep }; + static const int intf_numbers[2][3] = { + { /* UA-101 */ + [INTF_PLAYBACK] = 0, + [INTF_CAPTURE] = 1, + [INTF_MIDI] = 2, + }, + { /* UA-1000 */ + [INTF_CAPTURE] = 1, + [INTF_PLAYBACK] = 2, + [INTF_MIDI] = 3, + }, + }; struct snd_card *card; struct ua101 *ua; unsigned int card_index, i; + int is_ua1000; + const char *name; char usb_path[32]; int err; - if (interface->altsetting->desc.bInterfaceNumber != 0) + is_ua1000 = usb_id->idProduct == 0x0044; + + if (interface->altsetting->desc.bInterfaceNumber != + intf_numbers[is_ua1000][0]) return -ENODEV; mutex_lock(&devices_mutex); @@ -1239,20 +1240,13 @@ static int ua101_probe(struct usb_interface *interface, init_waitqueue_head(&ua->rate_feedback_wait); init_waitqueue_head(&ua->alsa_playback_wait); -#ifdef UA1A_HACK - if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) { - ua->intf[2] = interface; - ua->intf[0] = usb_ifnum_to_if(ua->dev, 1); - ua->intf[1] = usb_ifnum_to_if(ua->dev, 2); - usb_driver_claim_interface(&ua101_driver, ua->intf[0], ua); - usb_driver_claim_interface(&ua101_driver, ua->intf[1], ua); - } else { -#endif ua->intf[0] = interface; for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) { - ua->intf[i] = usb_ifnum_to_if(ua->dev, i); + ua->intf[i] = usb_ifnum_to_if(ua->dev, + intf_numbers[is_ua1000][i]); if (!ua->intf[i]) { - dev_err(&ua->dev->dev, "interface %u not found\n", i); + dev_err(&ua->dev->dev, "interface %u not found\n", + intf_numbers[is_ua1000][i]); err = -ENXIO; goto probe_error; } @@ -1264,39 +1258,19 @@ static int ua101_probe(struct usb_interface *interface, goto probe_error; } } -#ifdef UA1A_HACK - } -#endif snd_card_set_dev(card, &interface->dev); -#ifdef UA1A_HACK - if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) { - ua->format_bit = SNDRV_PCM_FMTBIT_S16_LE; - ua->rate = 44100; - ua->packets_per_second = 1000; - ua->capture.channels = 2; - ua->playback.channels = 2; - ua->capture.frame_bytes = 4; - ua->playback.frame_bytes = 4; - ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, 2); - ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, 1); - ua->capture.max_packet_bytes = 192; - ua->playback.max_packet_bytes = 192; - } else { -#endif err = detect_usb_format(ua); if (err < 0) goto probe_error; -#ifdef UA1A_HACK - } -#endif + name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101"; strcpy(card->driver, "UA-101"); - strcpy(card->shortname, "UA-101"); + strcpy(card->shortname, name); usb_make_path(ua->dev, usb_path, sizeof(usb_path)); snprintf(ua->card->longname, sizeof(ua->card->longname), - "EDIROL UA-101 (serial %s), %u Hz at %s, %s speed", + "EDIROL %s (serial %s), %u Hz at %s, %s speed", name, ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path, ua->dev->speed == USB_SPEED_HIGH ? "high" : "full"); @@ -1314,24 +1288,18 @@ static int ua101_probe(struct usb_interface *interface, if (err < 0) goto probe_error; - err = snd_pcm_new(card, "UA-101", 0, 1, 1, &ua->pcm); + err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm); if (err < 0) goto probe_error; ua->pcm->private_data = ua; - strcpy(ua->pcm->name, "UA-101"); + strcpy(ua->pcm->name, name); snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops); snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops); -#ifdef UA1A_HACK - if (ua->dev->descriptor.idProduct != cpu_to_le16(0x0018)) { -#endif err = snd_usbmidi_create(card, ua->intf[INTF_MIDI], &ua->midi_list, &midi_quirk); if (err < 0) goto probe_error; -#ifdef UA1A_HACK - } -#endif err = snd_card_register(card); if (err < 0) @@ -1386,11 +1354,9 @@ static void ua101_disconnect(struct usb_interface *interface) } static struct usb_device_id ua101_ids[] = { -#ifdef UA1A_HACK - { USB_DEVICE(0x0582, 0x0018) }, -#endif - { USB_DEVICE(0x0582, 0x007d) }, - { USB_DEVICE(0x0582, 0x008d) }, + { USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */ + { USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */ + { USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */ { } }; MODULE_DEVICE_TABLE(usb, ua101_ids); diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c539f7fe292f..11b0826b8fe6 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c @@ -2483,7 +2483,6 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, sample_width, sample_bytes); } /* check the format byte size */ - printk(" XXXXX SAMPLE BYTES %d\n", sample_bytes); switch (sample_bytes) { case 1: pcm_format = SNDRV_PCM_FORMAT_S8; @@ -2581,6 +2580,9 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof chip->usb_id == USB_ID(0x0d8c, 0x0102)) && fp->altsetting == 5 && fp->maxpacksize == 392) rate = 96000; + /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */ + if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068)) + rate = 8000; fp->rate_table[fp->nr_rates] = rate; if (!fp->rate_min || rate < fp->rate_min) fp->rate_min = rate; @@ -3386,58 +3388,6 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, return 0; } -/* - * Create a stream for an Edirol UA-1000 interface. - */ -static int create_ua1000_quirk(struct snd_usb_audio *chip, - struct usb_interface *iface, - const struct snd_usb_audio_quirk *quirk) -{ - static const struct audioformat ua1000_format = { - .format = SNDRV_PCM_FORMAT_S32_LE, - .fmt_type = UAC_FORMAT_TYPE_I, - .altsetting = 1, - .altset_idx = 1, - .attributes = 0, - .rates = SNDRV_PCM_RATE_CONTINUOUS, - }; - struct usb_host_interface *alts; - struct usb_interface_descriptor *altsd; - struct audioformat *fp; - int stream, err; - - if (iface->num_altsetting != 2) - return -ENXIO; - alts = &iface->altsetting[1]; - altsd = get_iface_desc(alts); - if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE || - altsd->bNumEndpoints != 1) - return -ENXIO; - - fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL); - if (!fp) - return -ENOMEM; - - fp->channels = alts->extra[4]; - fp->iface = altsd->bInterfaceNumber; - fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; - fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; - fp->datainterval = parse_datainterval(chip, alts); - fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); - fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]); - - stream = (fp->endpoint & USB_DIR_IN) - ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; - err = add_audio_endpoint(chip, stream, fp); - if (err < 0) { - kfree(fp); - return err; - } - /* FIXME: playback must be synchronized to capture */ - usb_set_interface(chip->dev, fp->iface, 0); - return 0; -} - static int snd_usb_create_quirk(struct snd_usb_audio *chip, struct usb_interface *iface, const struct snd_usb_audio_quirk *quirk); @@ -3686,7 +3636,6 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_MIDI_CME] = create_any_midi_quirk, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, - [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk }; diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 6b016d4aac6b..42c299cbf63a 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -75,7 +75,6 @@ enum quirk_type { QUIRK_MIDI_US122L, QUIRK_AUDIO_STANDARD_INTERFACE, QUIRK_AUDIO_FIXED_ENDPOINT, - QUIRK_AUDIO_EDIROL_UA1000, QUIRK_AUDIO_EDIROL_UAXX, QUIRK_AUDIO_ALIGN_TRANSFER, @@ -112,7 +111,7 @@ struct snd_usb_midi_endpoint_info { /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */ -/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */ +/* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */ /* for QUIRK_IGNORE_INTERFACE, data is NULL */ diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 2c59afd99611..9e28b20cb2ce 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c @@ -986,6 +986,8 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream) DEFINE_WAIT(wait); long timeout = msecs_to_jiffies(50); + if (ep->umidi->disconnected) + return; /* * The substream buffer is empty, but some data might still be in the * currently active URBs, so we have to wait for those to complete. @@ -1123,14 +1125,21 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi, * Frees an output endpoint. * May be called when ep hasn't been initialized completely. */ -static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint* ep) +static void snd_usbmidi_out_endpoint_clear(struct snd_usb_midi_out_endpoint *ep) { unsigned int i; for (i = 0; i < OUTPUT_URBS; ++i) - if (ep->urbs[i].urb) + if (ep->urbs[i].urb) { free_urb_and_buffer(ep->umidi, ep->urbs[i].urb, ep->max_transfer); + ep->urbs[i].urb = NULL; + } +} + +static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep) +{ + snd_usbmidi_out_endpoint_clear(ep); kfree(ep); } @@ -1262,15 +1271,18 @@ void snd_usbmidi_disconnect(struct list_head* p) usb_kill_urb(ep->out->urbs[j].urb); if (umidi->usb_protocol_ops->finish_out_endpoint) umidi->usb_protocol_ops->finish_out_endpoint(ep->out); + ep->out->active_urbs = 0; + if (ep->out->drain_urbs) { + ep->out->drain_urbs = 0; + wake_up(&ep->out->drain_wait); + } } if (ep->in) for (j = 0; j < INPUT_URBS; ++j) usb_kill_urb(ep->in->urbs[j]); /* free endpoints here; later call can result in Oops */ - if (ep->out) { - snd_usbmidi_out_endpoint_delete(ep->out); - ep->out = NULL; - } + if (ep->out) + snd_usbmidi_out_endpoint_clear(ep->out); if (ep->in) { snd_usbmidi_in_endpoint_delete(ep->in); ep->in = NULL; diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index f06faf7917b9..2b426c1fd0e8 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h @@ -1016,36 +1016,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - USB_DEVICE(0x0582, 0x0044), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "UA-1000", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UA1000 - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UA1000 - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } - }, - { - .ifnum = -1 - } - } - } -}, -{ /* has ID 0x0049 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0047), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 44deb21b1777..9ca9a13a78da 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -16,6 +16,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/slab.h> #include <linux/usb.h> #include <linux/usb/audio.h> #include <sound/core.h> diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index 1879b72c40f8..04aafb43a13c 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -21,6 +21,7 @@ */ #include <linux/interrupt.h> +#include <linux/slab.h> #include <linux/usb.h> #include <sound/core.h> #include <sound/memalloc.h> diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index 12ae0340adc0..c400ade3ff08 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -17,6 +17,7 @@ */ #include <linux/usb.h> +#include <linux/gfp.h> #include "usb_stream.h" diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index c42350eed2eb..cbd37f2c76d0 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -133,6 +133,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/slab.h> #include <linux/interrupt.h> #include <linux/usb.h> #include <sound/core.h> diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 74a67a85aa81..5d37d1ccf813 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -32,6 +32,7 @@ #include <linux/interrupt.h> +#include <linux/slab.h> #include <linux/usb.h> #include <sound/core.h> #include <sound/info.h> diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 9ed6c3956ca7..2a528e56afd5 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -51,6 +51,7 @@ */ #include <linux/delay.h> +#include <linux/gfp.h> #include "usbusx2yaudio.c" #if defined(USX2Y_NRPACKS_VARIABLE) || (!defined(USX2Y_NRPACKS_VARIABLE) && USX2Y_NRPACKS == 1) |