diff options
Diffstat (limited to 'sound')
60 files changed, 855 insertions, 546 deletions
diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h index 622cd37a011..a0f223c13f6 100644 --- a/sound/aoa/soundbus/soundbus.h +++ b/sound/aoa/soundbus/soundbus.h @@ -8,7 +8,7 @@ #ifndef __SOUNDBUS_H #define __SOUNDBUS_H -#include <asm/of_device.h> +#include <linux/of_device.h> #include <sound/pcm.h> #include <linux/list.h> diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index cba71d86754..c2635beb4c8 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -44,7 +44,7 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = { .name = "AC97 PCM out", .dev_addr = __PREG(PCDR), - .drcmr = &DRCMRTXPCDR, + .drcmr = &DRCMR(12), .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST32 | DCMD_WIDTH4, }; @@ -52,7 +52,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = { static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_in = { .name = "AC97 PCM in", .dev_addr = __PREG(PCDR), - .drcmr = &DRCMRRXPCDR, + .drcmr = &DRCMR(11), .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST32 | DCMD_WIDTH4, }; diff --git a/sound/core/control.c b/sound/core/control.c index b0bf4269104..636b3b52ef8 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -113,7 +113,6 @@ static int snd_ctl_release(struct inode *inode, struct file *file) unsigned int idx; ctl = file->private_data; - fasync_helper(-1, file, 0, &ctl->fasync); file->private_data = NULL; card = ctl->card; write_lock_irqsave(&card->ctl_files_rwlock, flags); diff --git a/sound/core/init.c b/sound/core/init.c index 8af467df924..b47ff8b44be 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -264,8 +264,11 @@ static int snd_disconnect_release(struct inode *inode, struct file *file) } spin_unlock(&shutdown_lock); - if (likely(df)) + if (likely(df)) { + if ((file->f_flags & FASYNC) && df->disconnected_f_op->fasync) + df->disconnected_f_op->fasync(-1, file, 0); return df->disconnected_f_op->release(inode, file); + } panic("%s(%p, %p) failed!", __func__, inode, file); } @@ -549,9 +552,9 @@ int snd_card_register(struct snd_card *card) return -EINVAL; #ifndef CONFIG_SYSFS_DEPRECATED if (!card->card_dev) { - card->card_dev = device_create_drvdata(sound_class, card->dev, - MKDEV(0, 0), NULL, - "card%i", card->number); + card->card_dev = device_create(sound_class, card->dev, + MKDEV(0, 0), NULL, + "card%i", card->number); if (IS_ERR(card->card_dev)) card->card_dev = NULL; } diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index a7b46ec72f3..1b3534d6768 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -33,9 +33,6 @@ #include <linux/moduleparam.h> #include <linux/mutex.h> #include <sound/memalloc.h> -#ifdef CONFIG_SBUS -#include <asm/sbus.h> -#endif MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>"); @@ -162,39 +159,6 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, } #endif /* CONFIG_HAS_DMA */ -#ifdef CONFIG_SBUS - -static void *snd_malloc_sbus_pages(struct device *dev, size_t size, - dma_addr_t *dma_addr) -{ - struct sbus_dev *sdev = (struct sbus_dev *)dev; - int pg; - void *res; - - if (WARN_ON(!dma_addr)) - return NULL; - pg = get_order(size); - res = sbus_alloc_consistent(sdev, PAGE_SIZE * (1 << pg), dma_addr); - if (res != NULL) - inc_snd_pages(pg); - return res; -} - -static void snd_free_sbus_pages(struct device *dev, size_t size, - void *ptr, dma_addr_t dma_addr) -{ - struct sbus_dev *sdev = (struct sbus_dev *)dev; - int pg; - - if (ptr == NULL) - return; - pg = get_order(size); - dec_snd_pages(pg); - sbus_free_consistent(sdev, PAGE_SIZE * (1 << pg), ptr, dma_addr); -} - -#endif /* CONFIG_SBUS */ - /* * * ALSA generic memory management @@ -231,11 +195,6 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, dmab->area = snd_malloc_pages(size, (unsigned long)device); dmab->addr = 0; break; -#ifdef CONFIG_SBUS - case SNDRV_DMA_TYPE_SBUS: - dmab->area = snd_malloc_sbus_pages(device, size, &dmab->addr); - break; -#endif #ifdef CONFIG_HAS_DMA case SNDRV_DMA_TYPE_DEV: dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); @@ -306,11 +265,6 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) case SNDRV_DMA_TYPE_CONTINUOUS: snd_free_pages(dmab->area, dmab->bytes); break; -#ifdef CONFIG_SBUS - case SNDRV_DMA_TYPE_SBUS: - snd_free_sbus_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); - break; -#endif #ifdef CONFIG_HAS_DMA case SNDRV_DMA_TYPE_DEV: snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); @@ -419,7 +373,7 @@ static int snd_mem_proc_read(struct seq_file *seq, void *offset) long pages = snd_allocated_pages >> (PAGE_SHIFT-12); struct snd_mem_list *mem; int devno; - static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" }; + static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG" }; mutex_lock(&list_mutex); seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n", diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 1af62b8b86c..e17836680f4 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2283,7 +2283,7 @@ static int snd_pcm_oss_open_file(struct file *file, int idx, err; struct snd_pcm_oss_file *pcm_oss_file; struct snd_pcm_substream *substream; - unsigned int f_mode = file->f_mode; + fmode_t f_mode = file->f_mode; if (rpcm_oss_file) *rpcm_oss_file = NULL; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index aef18682c03..a789efc9df3 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2169,7 +2169,6 @@ static int snd_pcm_release(struct inode *inode, struct file *file) if (snd_BUG_ON(!substream)) return -ENXIO; pcm = substream->pcm; - fasync_helper(-1, file, 0, &substream->runtime->fasync); mutex_lock(&pcm->open_mutex); snd_pcm_release_substream(substream); kfree(pcm_file); diff --git a/sound/core/sound.c b/sound/core/sound.c index c0685e2f0af..44a69bb8d4f 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -274,9 +274,8 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, return minor; } snd_minors[minor] = preg; - preg->dev = device_create_drvdata(sound_class, device, - MKDEV(major, minor), - private_data, "%s", name); + preg->dev = device_create(sound_class, device, MKDEV(major, minor), + private_data, "%s", name); if (IS_ERR(preg->dev)) { snd_minors[minor] = NULL; mutex_unlock(&sound_mutex); diff --git a/sound/core/timer.c b/sound/core/timer.c index e582face89d..c584408c9f1 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1263,7 +1263,6 @@ static int snd_timer_user_release(struct inode *inode, struct file *file) if (file->private_data) { tu = file->private_data; file->private_data = NULL; - fasync_helper(-1, file, 0, &tu->fasync); if (tu->timeri) snd_timer_close(tu->timeri); kfree(tu->queue); diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h index 70533a333b5..cdef2664218 100644 --- a/sound/drivers/pcsp/pcsp.h +++ b/sound/drivers/pcsp/pcsp.h @@ -62,6 +62,8 @@ struct snd_pcsp { unsigned short port, irq, dma; spinlock_t substream_lock; struct snd_pcm_substream *playback_substream; + unsigned int fmt_size; + unsigned int is_signed; size_t playback_ptr; size_t period_ptr; atomic_t timer_active; diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index 40f95f549d2..84cc2658c05 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -36,12 +36,13 @@ static void pcsp_call_pcm_elapsed(unsigned long priv) static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0); -enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) +/* write the port and returns the next expire time in ns; + * called at the trigger-start and in hrtimer callback + */ +static unsigned long pcsp_timer_update(struct hrtimer *handle) { unsigned char timer_cnt, val; - int fmt_size, periods_elapsed; u64 ns; - size_t period_bytes, buffer_bytes; struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); @@ -51,28 +52,25 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) outb(chip->val61, 0x61); chip->thalf = 0; if (!atomic_read(&chip->timer_active)) - goto stop; - hrtimer_forward(&chip->timer, chip->timer.expires, - ktime_set(0, chip->ns_rem)); - return HRTIMER_RESTART; + return 0; + return chip->ns_rem; } if (!atomic_read(&chip->timer_active)) - goto stop; + return 0; substream = chip->playback_substream; if (!substream) - goto stop; + return 0; runtime = substream->runtime; - fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3; /* assume it is mono! */ - val = runtime->dma_area[chip->playback_ptr + fmt_size - 1]; - if (snd_pcm_format_signed(runtime->format)) + val = runtime->dma_area[chip->playback_ptr + chip->fmt_size - 1]; + if (chip->is_signed) val ^= 0x80; timer_cnt = val * CUR_DIV() / 256; if (timer_cnt && chip->enable) { - spin_lock(&i8253_lock); + spin_lock_irqsave(&i8253_lock, flags); if (!nforce_wa) { outb_p(chip->val61, 0x61); outb_p(timer_cnt, 0x42); @@ -81,14 +79,39 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) outb(chip->val61 ^ 2, 0x61); chip->thalf = 1; } - spin_unlock(&i8253_lock); + spin_unlock_irqrestore(&i8253_lock, flags); } + chip->ns_rem = PCSP_PERIOD_NS(); + ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); + chip->ns_rem -= ns; + return ns; +} + +enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) +{ + struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); + struct snd_pcm_substream *substream; + int periods_elapsed, pointer_update; + size_t period_bytes, buffer_bytes; + unsigned long ns; + unsigned long flags; + + pointer_update = !chip->thalf; + ns = pcsp_timer_update(handle); + if (!ns) + return HRTIMER_NORESTART; + + /* update the playback position */ + substream = chip->playback_substream; + if (!substream) + return HRTIMER_NORESTART; + period_bytes = snd_pcm_lib_period_bytes(substream); buffer_bytes = snd_pcm_lib_buffer_bytes(substream); spin_lock_irqsave(&chip->substream_lock, flags); - chip->playback_ptr += PCSP_INDEX_INC() * fmt_size; + chip->playback_ptr += PCSP_INDEX_INC() * chip->fmt_size; periods_elapsed = chip->playback_ptr - chip->period_ptr; if (periods_elapsed < 0) { #if PCSP_DEBUG @@ -106,31 +129,27 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) if (periods_elapsed) { chip->period_ptr += periods_elapsed * period_bytes; chip->period_ptr %= buffer_bytes; - tasklet_schedule(&pcsp_pcm_tasklet); } spin_unlock_irqrestore(&chip->substream_lock, flags); - if (!atomic_read(&chip->timer_active)) - goto stop; + if (periods_elapsed) + tasklet_schedule(&pcsp_pcm_tasklet); - chip->ns_rem = PCSP_PERIOD_NS(); - ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); - chip->ns_rem -= ns; - hrtimer_forward(&chip->timer, chip->timer.expires, ktime_set(0, ns)); - return HRTIMER_RESTART; + hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns)); - stop: - return HRTIMER_NORESTART; + return HRTIMER_RESTART; } -static void pcsp_start_playing(struct snd_pcsp *chip) +static int pcsp_start_playing(struct snd_pcsp *chip) { + unsigned long ns; + #if PCSP_DEBUG printk(KERN_INFO "PCSP: start_playing called\n"); #endif if (atomic_read(&chip->timer_active)) { printk(KERN_ERR "PCSP: Timer already active\n"); - return; + return -EIO; } spin_lock(&i8253_lock); @@ -140,7 +159,12 @@ static void pcsp_start_playing(struct snd_pcsp *chip) atomic_set(&chip->timer_active, 1); chip->thalf = 0; - hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); + ns = pcsp_timer_update(&pcsp_chip.timer); + if (!ns) + return -EIO; + + hrtimer_start(&pcsp_chip.timer, ktime_set(0, ns), HRTIMER_MODE_REL); + return 0; } static void pcsp_stop_playing(struct snd_pcsp *chip) @@ -220,6 +244,9 @@ static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream) pcsp_sync_stop(chip); chip->playback_ptr = 0; chip->period_ptr = 0; + chip->fmt_size = + snd_pcm_format_physical_width(substream->runtime->format) >> 3; + chip->is_signed = snd_pcm_format_signed(substream->runtime->format); return 0; } @@ -232,8 +259,7 @@ static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: - pcsp_start_playing(chip); - break; + return pcsp_start_playing(chip); case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: pcsp_stop_playing(chip); diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c index 83e90057270..c13a178383b 100644 --- a/sound/i2c/other/tea575x-tuner.c +++ b/sound/i2c/other/tea575x-tuner.c @@ -87,8 +87,7 @@ static void snd_tea575x_set_freq(struct snd_tea575x *tea) static int snd_tea575x_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) { - struct video_device *dev = video_devdata(file); - struct snd_tea575x *tea = video_get_drvdata(dev); + struct snd_tea575x *tea = video_drvdata(file); void __user *arg = (void __user *)data; switch(cmd) { @@ -175,6 +174,21 @@ static void snd_tea575x_release(struct video_device *vfd) { } +static int snd_tea575x_exclusive_open(struct inode *inode, struct file *file) +{ + struct snd_tea575x *tea = video_drvdata(file); + + return test_and_set_bit(0, &tea->in_use) ? -EBUSY : 0; +} + +static int snd_tea575x_exclusive_release(struct inode *inode, struct file *file) +{ + struct snd_tea575x *tea = video_drvdata(file); + + clear_bit(0, &tea->in_use); + return 0; +} + /* * initialize all the tea575x chips */ @@ -193,9 +207,10 @@ void snd_tea575x_init(struct snd_tea575x *tea) tea->vd.release = snd_tea575x_release; video_set_drvdata(&tea->vd, tea); tea->vd.fops = &tea->fops; + tea->in_use = 0; tea->fops.owner = tea->card->module; - tea->fops.open = video_exclusive_open; - tea->fops.release = video_exclusive_release; + tea->fops.open = snd_tea575x_exclusive_open; + tea->fops.release = snd_tea575x_exclusive_release; tea->fops.ioctl = snd_tea575x_ioctl; if (video_register_device(&tea->vd, VFL_TYPE_RADIO, tea->dev_nr - 1) < 0) { snd_printk(KERN_ERR "unable to register tea575x tuner\n"); diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 660beb41f76..ce0aa044e27 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -211,7 +211,7 @@ config SND_GUSCLASSIC config SND_GUSEXTREME tristate "Gravis UltraSound Extreme" - select SND_HWDEP + select SND_OPL3_LIB select SND_MPU401_UART select SND_PCM help diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index 23018a7c063..81e1f443d09 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c @@ -93,7 +93,7 @@ static struct au1550_state { spinlock_t lock; struct mutex open_mutex; struct mutex sem; - mode_t open_mode; + fmode_t open_mode; wait_queue_head_t open_wait; struct dmabuf { diff --git a/sound/oss/dmasound/dmasound.h b/sound/oss/dmasound/dmasound.h index d978b009656..1308d8d3418 100644 --- a/sound/oss/dmasound/dmasound.h +++ b/sound/oss/dmasound/dmasound.h @@ -129,7 +129,7 @@ typedef struct { int (*mixer_ioctl)(u_int, u_long); /* optional */ int (*write_sq_setup)(void); /* optional */ int (*read_sq_setup)(void); /* optional */ - int (*sq_open)(mode_t); /* optional */ + int (*sq_open)(fmode_t); /* optional */ int (*state_info)(char *, size_t); /* optional */ void (*abort_read)(void); /* optional */ int min_dsp_speed; @@ -235,7 +235,7 @@ struct sound_queue { */ int active; wait_queue_head_t action_queue, open_queue, sync_queue; - int open_mode; + int non_blocking; int busy, syncing, xruns, died; }; diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c index 285239d64b8..4d45bd63718 100644 --- a/sound/oss/dmasound/dmasound_atari.c +++ b/sound/oss/dmasound/dmasound_atari.c @@ -143,7 +143,7 @@ static int AtaMixerIoctl(u_int cmd, u_long arg); static int TTMixerIoctl(u_int cmd, u_long arg); static int FalconMixerIoctl(u_int cmd, u_long arg); static int AtaWriteSqSetup(void); -static int AtaSqOpen(mode_t mode); +static int AtaSqOpen(fmode_t mode); static int TTStateInfo(char *buffer, size_t space); static int FalconStateInfo(char *buffer, size_t space); @@ -1461,7 +1461,7 @@ static int AtaWriteSqSetup(void) return 0 ; } -static int AtaSqOpen(mode_t mode) +static int AtaSqOpen(fmode_t mode) { write_sq_ignore_int = 1; return 0 ; diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c index 95fc5c68175..793b7f47843 100644 --- a/sound/oss/dmasound/dmasound_core.c +++ b/sound/oss/dmasound/dmasound_core.c @@ -212,7 +212,7 @@ static int irq_installed; #endif /* MODULE */ /* control over who can modify resources shared between play/record */ -static mode_t shared_resource_owner; +static fmode_t shared_resource_owner; static int shared_resources_initialised; /* @@ -603,7 +603,7 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft, while (uLeft) { while (write_sq.count >= write_sq.max_active) { sq_play(); - if (write_sq.open_mode & O_NONBLOCK) + if (write_sq.non_blocking) return uWritten > 0 ? uWritten : -EAGAIN; SLEEP(write_sq.action_queue); if (signal_pending(current)) @@ -668,7 +668,7 @@ static inline void sq_init_waitqueue(struct sound_queue *sq) #if 0 /* blocking open() */ static inline void sq_wake_up(struct sound_queue *sq, struct file *file, - mode_t mode) + fmode_t mode) { if (file->f_mode & mode) { sq->busy = 0; /* CHECK: IS THIS OK??? */ @@ -677,7 +677,7 @@ static inline void sq_wake_up(struct sound_queue *sq, struct file *file, } #endif -static int sq_open2(struct sound_queue *sq, struct file *file, mode_t mode, +static int sq_open2(struct sound_queue *sq, struct file *file, fmode_t mode, int numbufs, int bufsize) { int rc = 0; @@ -718,7 +718,7 @@ static int sq_open2(struct sound_queue *sq, struct file *file, mode_t mode, return rc; } - sq->open_mode = file->f_mode; + sq->non_blocking = file->f_flags & O_NONBLOCK; } return rc; } @@ -891,10 +891,10 @@ static int sq_release(struct inode *inode, struct file *file) is the owner - if we have problems. */ -static int shared_resources_are_mine(mode_t md) +static int shared_resources_are_mine(fmode_t md) { if (shared_resource_owner) - return (shared_resource_owner & md ) ; + return (shared_resource_owner & md) != 0; else { shared_resource_owner = md ; return 1 ; diff --git a/sound/oss/msnd.h b/sound/oss/msnd.h index 61b3955481c..c8be47ec2b7 100644 --- a/sound/oss/msnd.h +++ b/sound/oss/msnd.h @@ -211,7 +211,7 @@ typedef struct multisound_dev { /* State variables */ enum { msndClassic, msndPinnacle } type; - mode_t mode; + fmode_t mode; unsigned long flags; #define F_RESETTING 0 #define F_HAVEDIGITAL 1 diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c index b493660deb3..e5d42399491 100644 --- a/sound/oss/sh_dac_audio.c +++ b/sound/oss/sh_dac_audio.c @@ -26,7 +26,7 @@ #include <asm/cpu/dac.h> #include <asm/cpu/timer.h> #include <asm/machvec.h> -#include <asm/hp6xx.h> +#include <mach/hp6xx.h> #include <asm/hd64461.h> #define MODNAME "sh_dac_audio" diff --git a/sound/oss/sound_config.h b/sound/oss/sound_config.h index 1a00a321061..55271fbe7f4 100644 --- a/sound/oss/sound_config.h +++ b/sound/oss/sound_config.h @@ -110,24 +110,16 @@ struct channel_info { #define OPEN_WRITE PCM_ENABLE_OUTPUT #define OPEN_READWRITE (OPEN_READ|OPEN_WRITE) -#if OPEN_READ == FMODE_READ && OPEN_WRITE == FMODE_WRITE - -static inline int translate_mode(struct file *file) -{ - return file->f_mode; -} - -#else - static inline int translate_mode(struct file *file) { - return ((file->f_mode & FMODE_READ) ? OPEN_READ : 0) | - ((file->f_mode & FMODE_WRITE) ? OPEN_WRITE : 0); + if (OPEN_READ == (__force int)FMODE_READ && + OPEN_WRITE == (__force int)FMODE_WRITE) + return (__force int)(file->f_mode & (FMODE_READ | FMODE_WRITE)); + else + return ((file->f_mode & FMODE_READ) ? OPEN_READ : 0) | + ((file->f_mode & FMODE_WRITE) ? OPEN_WRITE : 0); } -#endif - - #include "sound_calls.h" #include "dev_table.h" diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 7d89c081a08..61aaedae6b7 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c @@ -560,19 +560,18 @@ static int __init oss_init(void) sound_dmap_flag = (dmabuf > 0 ? 1 : 0); for (i = 0; i < ARRAY_SIZE(dev_list); i++) { - device_create_drvdata(sound_class, NULL, - MKDEV(SOUND_MAJOR, dev_list[i].minor), - NULL, "%s", dev_list[i].name); + device_create(sound_class, NULL, + MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL, + "%s", dev_list[i].name); if (!dev_list[i].num) continue; for (j = 1; j < *dev_list[i].num; j++) - device_create_drvdata(sound_class, NULL, - MKDEV(SOUND_MAJOR, - dev_list[i].minor + (j*0x10)), - NULL, - "%s%d", dev_list[i].name, j); + device_create(sound_class, NULL, + MKDEV(SOUND_MAJOR, + dev_list[i].minor + (j*0x10)), + NULL, "%s%d", dev_list[i].name, j); } if (sound_nblocks >= 1024) diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index 044453a4ee5..41562ecde5b 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c @@ -295,7 +295,7 @@ struct cs4297a_state { struct mutex open_mutex; struct mutex open_sem_adc; struct mutex open_sem_dac; - mode_t open_mode; + fmode_t open_mode; wait_queue_head_t open_wait; wait_queue_head_t open_wait_adc; wait_queue_head_t open_wait_dac; diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c index dcbb3f739e6..78b8acc7c3b 100644 --- a/sound/oss/vwsnd.c +++ b/sound/oss/vwsnd.c @@ -1509,7 +1509,7 @@ typedef struct vwsnd_dev { struct mutex open_mutex; struct mutex io_mutex; struct mutex mix_mutex; - mode_t open_mode; + fmode_t open_mode; wait_queue_head_t open_wait; lithium_t lith; diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 92f3a976ef2..a7f38e63303 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c @@ -932,7 +932,7 @@ snd_ad1889_create(struct snd_card *card, goto free_and_ret; chip->bar = pci_resource_start(pci, 0); - chip->iobase = ioremap_nocache(chip->bar, pci_resource_len(pci, 0)); + chip->iobase = pci_ioremap_bar(pci, 0); if (chip->iobase == NULL) { printk(KERN_ERR PFX "unable to reserve region.\n"); err = -EBUSY; diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 085a52b8c80..226fe8237d3 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c @@ -1609,7 +1609,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card, return err; } chip->addr = pci_resource_start(pci, 0); - chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 0)); + chip->remap_addr = pci_ioremap_bar(pci, 0); if (chip->remap_addr == NULL) { snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); snd_atiixp_free(chip); diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 2f106306c7f..0e6e5cc1c50 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -1252,7 +1252,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card, return err; } chip->addr = pci_resource_start(pci, 0); - chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 0)); + chip->remap_addr = pci_ioremap_bar(pci, 0); if (chip->remap_addr == NULL) { snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); snd_atiixp_free(chip); diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 68368e49007..a36d4d1fd41 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c @@ -180,8 +180,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) if ((err = pci_request_regions(pci, CARD_NAME_SHORT)) != 0) goto regions_out; - chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), - pci_resource_len(pci, 0)); + chip->mmio = pci_ioremap_bar(pci, 0); if (!chip->mmio) { printk(KERN_ERR "MMIO area remap failed.\n"); err = -ENOMEM; diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 3aa8d973540..1aa1c040254 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -749,8 +749,7 @@ static int __devinit snd_bt87x_create(struct snd_card *card, pci_disable_device(pci); return err; } - chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), - pci_resource_len(pci, 0)); + chip->mmio = pci_ioremap_bar(pci, 0); if (!chip->mmio) { snd_printk(KERN_ERR "cannot remap io memory\n"); err = -ENOMEM; diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index ef9308f7c45..192e7842e18 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1382,8 +1382,8 @@ static int __devinit snd_cs4281_create(struct snd_card *card, chip->ba0_addr = pci_resource_start(pci, 0); chip->ba1_addr = pci_resource_start(pci, 1); - chip->ba0 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0)); - chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1)); + chip->ba0 = pci_ioremap_bar(pci, 0); + chip->ba1 = pci_ioremap_bar(pci, 1); if (!chip->ba0 || !chip->ba1) { snd_cs4281_free(chip); return -ENOMEM; diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index 4ba2db2f425..6dea5b5cc77 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c @@ -132,7 +132,7 @@ static int __devinit snd_cs5530_create(struct snd_card *card, } chip->pci_base = pci_resource_start(pci, 0); - mem = ioremap_nocache(chip->pci_base, pci_resource_len(pci, 0)); + mem = pci_ioremap_bar(pci, 0); if (mem == NULL) { kfree(chip); pci_disable_device(pci); diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 9b77b3e0fa9..3ecd7e797de 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -37,6 +37,9 @@ static void snd_hda_generate_beep(struct work_struct *work) container_of(work, struct hda_beep, beep_work); struct hda_codec *codec = beep->codec; + if (!beep->enabled) + return; + /* generate tone */ snd_hda_codec_write_cache(codec, beep->nid, 0, AC_VERB_SET_BEEP_CONTROL, beep->tone); @@ -85,6 +88,10 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) snprintf(beep->phys, sizeof(beep->phys), "card%d/codec#%d/beep0", codec->bus->card->number, codec->addr); input_dev = input_allocate_device(); + if (!input_dev) { + kfree(beep); + return -ENOMEM; + } /* setup digital beep device */ input_dev->name = "HDA Digital PCBeep"; @@ -115,6 +122,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) beep->nid = nid; beep->dev = input_dev; beep->codec = codec; + beep->enabled = 1; codec->beep = beep; INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index de4036e6e71..b9679f081ca 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -31,6 +31,7 @@ struct hda_beep { char phys[32]; int tone; int nid; + int enabled; struct work_struct beep_work; /* scheduled task for beep event */ }; diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 6447754ae56..ba1ab737b55 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -64,6 +64,7 @@ static struct hda_vendor_id hda_vendor_ids[] = { { 0x14f1, "Conexant" }, { 0x17e8, "Chrontel" }, { 0x1854, "LG" }, + { 0x1aec, "Wolfson Microelectronics" }, { 0x434d, "C-Media" }, { 0x8384, "SigmaTel" }, {} /* terminator */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 9f316c1b279..35722ec920c 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -45,6 +45,7 @@ #include <linux/slab.h> #include <linux/pci.h> #include <linux/mutex.h> +#include <linux/reboot.h> #include <sound/core.h> #include <sound/initval.h> #include "hda_codec.h" @@ -397,6 +398,9 @@ struct azx { /* for pending irqs */ struct work_struct irq_pending_work; + + /* reboot notifier (for mysterious hangup problem at power-down) */ + struct notifier_block reboot_notifier; }; /* driver types */ @@ -1979,12 +1983,36 @@ static int azx_resume(struct pci_dev *pci) /* + * reboot notifier for hang-up problem at power-down + */ +static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) +{ + struct azx *chip = container_of(nb, struct azx, reboot_notifier); + azx_stop_chip(chip); + return NOTIFY_OK; +} + +static void azx_notifier_register(struct azx *chip) +{ + chip->reboot_notifier.notifier_call = azx_halt; + register_reboot_notifier(&chip->reboot_notifier); +} + +static void azx_notifier_unregister(struct azx *chip) +{ + if (chip->reboot_notifier.notifier_call) + unregister_reboot_notifier(&chip->reboot_notifier); +} + +/* * destructor */ static int azx_free(struct azx *chip) { int i; + azx_notifier_unregister(chip); + if (chip->initialized) { azx_clear_irq_pending(chip); for (i = 0; i < chip->num_streams; i++) @@ -2158,7 +2186,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } chip->addr = pci_resource_start(pci, 0); - chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0)); + chip->remap_addr = pci_ioremap_bar(pci, 0); if (chip->remap_addr == NULL) { snd_printk(KERN_ERR SFX "ioremap error\n"); err = -ENXIO; @@ -2348,6 +2376,7 @@ static int __devinit azx_probe(struct pci_dev *pci, pci_set_drvdata(pci, card); chip->running = 1; power_down_all_codecs(chip); + azx_notifier_register(chip); dev++; return err; diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 743d77922bc..c39af986bff 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -483,6 +483,8 @@ static void print_gpio(struct snd_info_buffer *buffer, (gpio & AC_GPIO_UNSOLICITED) ? 1 : 0, (gpio & AC_GPIO_WAKE) ? 1 : 0); max = gpio & AC_GPIO_IO_COUNT; + if (!max || max > 8) + return; enable = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_GPIO_MASK, 0); direction = snd_hda_codec_read(codec, nid, 0, diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2b00c4afdf9..686c77491de 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3860,6 +3860,9 @@ static const char *ad1884a_models[AD1884A_MODELS] = { static struct snd_pci_quirk ad1884a_cfg_tbl[] = { SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), + SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), + SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP), + SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP), SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), {} }; diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c index 1a65775d28e..2eed2c8b98d 100644 --- a/sound/pci/hda/patch_nvhdmi.c +++ b/sound/pci/hda/patch_nvhdmi.c @@ -116,6 +116,7 @@ static int nvhdmi_build_pcms(struct hda_codec *codec) codec->pcm_info = info; info->name = "NVIDIA HDMI"; + info->pcm_type = HDA_PCM_TYPE_HDMI; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = nvhdmi_pcm_digital_playback; return 0; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e72707cb60a..a378c014512 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -307,6 +307,13 @@ struct alc_spec { /* for PLL fix */ hda_nid_t pll_nid; unsigned int pll_coef_idx, pll_coef_bit; + +#ifdef SND_HDA_NEEDS_RESUME +#define ALC_MAX_PINS 16 + unsigned int num_pins; + hda_nid_t pin_nids[ALC_MAX_PINS]; + unsigned int pin_cfgs[ALC_MAX_PINS]; +#endif }; /* @@ -822,6 +829,7 @@ static void alc_sku_automute(struct hda_codec *codec) spec->jack_present ? 0 : PIN_OUT); } +#if 0 /* it's broken in some acses -- temporarily disabled */ static void alc_mic_automute(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -842,6 +850,9 @@ static void alc_mic_automute(struct hda_codec *codec) snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, capsrc_idx_fmic, HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); } +#else +#define alc_mic_automute(codec) /* NOP */ +#endif /* disabled */ /* unsolicited event for HP jack sensing */ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) @@ -1051,12 +1062,14 @@ do_sku: AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT); +#if 0 /* it's broken in some acses -- temporarily disabled */ if (spec->autocfg.input_pins[AUTO_PIN_MIC] && spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]) snd_hda_codec_write(codec, spec->autocfg.input_pins[AUTO_PIN_MIC], 0, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT); +#endif /* disabled */ spec->unsol_event = alc_sku_unsol_event; } @@ -2778,6 +2791,64 @@ static void alc_free(struct hda_codec *codec) codec->spec = NULL; /* to be sure */ } +#ifdef SND_HDA_NEEDS_RESUME +static void store_pin_configs(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t nid, end_nid; + + end_nid = codec->start_nid + codec->num_nodes; + for (nid = codec->start_nid; nid < end_nid; nid++) { + unsigned int wid_caps = get_wcaps(codec, nid); + unsigned int wid_type = + (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + if (wid_type != AC_WID_PIN) + continue; + if (spec->num_pins >= ARRAY_SIZE(spec->pin_nids)) + break; + spec->pin_nids[spec->num_pins] = nid; + spec->pin_cfgs[spec->num_pins] = + snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_CONFIG_DEFAULT, 0); + spec->num_pins++; + } +} + +static void resume_pin_configs(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + int i; + + for (i = 0; i < spec->num_pins; i++) { + hda_nid_t pin_nid = spec->pin_nids[i]; + unsigned int pin_config = spec->pin_cfgs[i]; + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, + pin_config & 0x000000ff); + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, + (pin_config & 0x0000ff00) >> 8); + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, + (pin_config & 0x00ff0000) >> 16); + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, + pin_config >> 24); + } +} + +static int alc_resume(struct hda_codec *codec) +{ + resume_pin_configs(codec); + codec->patch_ops.init(codec); + snd_hda_codec_resume_amp(codec); + snd_hda_codec_resume_cache(codec); + return 0; +} +#else +#define store_pin_configs(codec) +#endif + /* */ static struct hda_codec_ops alc_patch_ops = { @@ -2786,6 +2857,9 @@ static struct hda_codec_ops alc_patch_ops = { .init = alc_init, .free = alc_free, .unsol_event = alc_unsol_event, +#ifdef SND_HDA_NEEDS_RESUME + .resume = alc_resume, +#endif #ifdef CONFIG_SND_HDA_POWER_SAVE .check_power_status = alc_check_power_status, #endif @@ -3832,6 +3906,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) spec->num_mux_defs = 1; spec->input_mux = &spec->private_imux; + store_pin_configs(codec); return 1; } @@ -4996,7 +5071,7 @@ static struct hda_verb alc260_test_init_verbs[] = { */ static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid, - const char *pfx) + const char *pfx, int *vol_bits) { hda_nid_t nid_vol; unsigned long vol_val, sw_val; @@ -5018,10 +5093,14 @@ static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid, } else return 0; /* N/A */ - snprintf(name, sizeof(name), "%s Playback Volume", pfx); - err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val); - if (err < 0) - return err; + if (!(*vol_bits & (1 << nid_vol))) { + /* first control for the volume widget */ + snprintf(name, sizeof(name), "%s Playback Volume", pfx); + err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val); + if (err < 0) + return err; + *vol_bits |= (1 << nid_vol); + } snprintf(name, sizeof(name), "%s Playback Switch", pfx); err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val); if (err < 0) @@ -5035,6 +5114,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, { hda_nid_t nid; int err; + int vols = 0; spec->multiout.num_dacs = 1; spec->multiout.dac_nids = spec->private_dac_nids; @@ -5042,21 +5122,22 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, nid = cfg->line_out_pins[0]; if (nid) { - err = alc260_add_playback_controls(spec, nid, "Front"); + err = alc260_add_playback_controls(spec, nid, "Front", &vols); if (err < 0) return err; } nid = cfg->speaker_pins[0]; if (nid) { - err = alc260_add_playback_controls(spec, nid, "Speaker"); + err = alc260_add_playback_controls(spec, nid, "Speaker", &vols); if (err < 0) return err; } nid = cfg->hp_pins[0]; if (nid) { - err = alc260_add_playback_controls(spec, nid, "Headphone"); + err = alc260_add_playback_controls(spec, nid, "Headphone", + &vols); if (err < 0) return err; } @@ -5244,6 +5325,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) } spec->num_mixers++; + store_pin_configs(codec); return 1; } @@ -8332,6 +8414,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE), + SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE), SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE), @@ -8386,6 +8469,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763), SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY), SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), + SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG), SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66), SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL), @@ -10307,6 +10391,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) if (err < 0) return err; + store_pin_configs(codec); return 1; } @@ -11441,6 +11526,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) if (err < 0) return err; + store_pin_configs(codec); return 1; } @@ -12160,8 +12246,26 @@ static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec, return 0; } -#define alc269_auto_create_analog_input_ctls \ - alc880_auto_create_analog_input_ctls +static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec, + const struct auto_pin_cfg *cfg) +{ + int err; + + err = alc880_auto_create_analog_input_ctls(spec, cfg); + if (err < 0) + return err; + /* digital-mic input pin is excluded in alc880_auto_create..() + * because it's under 0x18 + */ + if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 || + cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) { + struct hda_input_mux *imux = &spec->private_imux; + imux->items[imux->num_items].label = "Int Mic"; + imux->items[imux->num_items].index = 0x05; + imux->num_items++; + } + return 0; +} #ifdef CONFIG_SND_HDA_POWER_SAVE #define alc269_loopbacks alc880_loopbacks @@ -12224,6 +12328,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) spec->mixers[spec->num_mixers] = alc269_capture_mixer; spec->num_mixers++; + store_pin_configs(codec); return 1; } @@ -13310,6 +13415,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) spec->mixers[spec->num_mixers] = alc861_capture_mixer; spec->num_mixers++; + store_pin_configs(codec); return 1; } @@ -14421,6 +14527,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) if (err < 0) return err; + store_pin_configs(codec); return 1; } @@ -16252,6 +16359,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec) spec->mixers[spec->num_mixers] = alc662_capture_mixer; spec->num_mixers++; + + store_pin_configs(codec); return 1; } diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index a2ac7205d45..9563b5bbb27 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -36,9 +36,11 @@ #include "hda_beep.h" #define NUM_CONTROL_ALLOC 32 + +#define STAC_VREF_EVENT 0x00 +#define STAC_INSERT_EVENT 0x10 #define STAC_PWR_EVENT 0x20 #define STAC_HP_EVENT 0x30 -#define STAC_VREF_EVENT 0x40 enum { STAC_REF, @@ -69,6 +71,7 @@ enum { enum { STAC_92HD73XX_REF, STAC_DELL_M6, + STAC_DELL_EQ, STAC_92HD73XX_MODELS }; @@ -211,7 +214,7 @@ struct sigmatel_spec { /* i/o switches */ unsigned int io_switch[2]; unsigned int clfe_swap; - unsigned int hp_switch; + unsigned int hp_switch; /* NID of HP as line-out */ unsigned int aloopback; struct hda_pcm pcm_rec[2]; /* PCM information */ @@ -566,10 +569,8 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, nid = codec->slave_dig_outs[smux_idx - 1]; if (spec->cur_smux[smux_idx] == smux->num_items - 1) val = AMP_OUT_MUTE; - if (smux_idx == 0) - nid = spec->multiout.dig_out_nid; else - nid = codec->slave_dig_outs[smux_idx - 1]; + val = AMP_OUT_UNMUTE; /* un/mute SPDIF out */ snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val); @@ -775,9 +776,7 @@ static struct hda_verb dell_eq_core_init[] = { }; static struct hda_verb dell_m6_core_init[] = { - /* set master volume to max value without distortion - * and direct control */ - { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, + { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, /* setup audio connections */ { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, @@ -1282,7 +1281,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) return err; spec->multiout.share_spdif = 1; } - if (spec->dig_in_nid && (!spec->gpio_dir & 0x01)) { + if (spec->dig_in_nid && !(spec->gpio_dir & 0x01)) { err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); if (err < 0) return err; @@ -1602,11 +1601,13 @@ static unsigned int dell_m6_pin_configs[13] = { static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, [STAC_DELL_M6] = dell_m6_pin_configs, + [STAC_DELL_EQ] = dell_m6_pin_configs, }; static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { [STAC_92HD73XX_REF] = "ref", [STAC_DELL_M6] = "dell-m6", + [STAC_DELL_EQ] = "dell-eq", }; static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { @@ -1687,6 +1688,10 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { /* SigmaTel reference board */ SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_92HD71BXX_REF), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f2, + "HP dv5", STAC_HP_M4), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4, + "HP dv7", STAC_HP_M4), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, "unknown HP", STAC_HP_M4), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, @@ -2444,7 +2449,7 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol, struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct sigmatel_spec *spec = codec->spec; - ucontrol->value.integer.value[0] = spec->hp_switch; + ucontrol->value.integer.value[0] = !!spec->hp_switch; return 0; } @@ -2453,8 +2458,9 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct sigmatel_spec *spec = codec->spec; - - spec->hp_switch = ucontrol->value.integer.value[0]; + int nid = kcontrol->private_value; + + spec->hp_switch = ucontrol->value.integer.value[0] ? nid : 0; /* check to be sure that the ports are upto date with * switch changes @@ -2587,8 +2593,10 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = { }; /* add dynamic controls */ -static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type, - int idx, const char *name, unsigned long val) +static int stac92xx_add_control_temp(struct sigmatel_spec *spec, + struct snd_kcontrol_new *ktemp, + int idx, const char *name, + unsigned long val) { struct snd_kcontrol_new *knew; @@ -2607,20 +2615,29 @@ static int stac92xx_add_control_idx(struct sigmatel_spec *spec, int type, } knew = &spec->kctl_alloc[spec->num_kctl_used]; - *knew = stac92xx_control_templates[type]; + *knew = *ktemp; knew->index = idx; knew->name = kstrdup(name, GFP_KERNEL); - if (! knew->name) + if (!knew->name) return -ENOMEM; knew->private_value = val; spec->num_kctl_used++; return 0; } +static inline int stac92xx_add_control_idx(struct sigmatel_spec *spec, + int type, int idx, const char *name, + unsigned long val) +{ + return stac92xx_add_control_temp(spec, + &stac92xx_control_templates[type], + idx, name, val); +} + /* add dynamic controls */ -static int stac92xx_add_control(struct sigmatel_spec *spec, int type, - const char *name, unsigned long val) +static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type, + const char *name, unsigned long val) { return stac92xx_add_control_idx(spec, type, 0, name, val); } @@ -2863,7 +2880,8 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, if (cfg->hp_outs > 1) { err = stac92xx_add_control(spec, STAC_CTL_WIDGET_HP_SWITCH, - "Headphone as Line Out Switch", 0); + "Headphone as Line Out Switch", + cfg->hp_pins[cfg->hp_outs - 1]); if (err < 0) return err; } @@ -3061,6 +3079,43 @@ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec, return 0; } +#ifdef CONFIG_SND_HDA_INPUT_BEEP +#define stac92xx_dig_beep_switch_info snd_ctl_boolean_mono_info + +static int stac92xx_dig_beep_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = codec->beep->enabled; + return 0; +} + +static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + int enabled = !!ucontrol->value.integer.value[0]; + if (codec->beep->enabled != enabled) { + codec->beep->enabled = enabled; + return 1; + } + return 0; +} + +static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = stac92xx_dig_beep_switch_info, + .get = stac92xx_dig_beep_switch_get, + .put = stac92xx_dig_beep_switch_put, +}; + +static int stac92xx_beep_switch_ctl(struct hda_codec *codec) +{ + return stac92xx_add_control_temp(codec->spec, &stac92xx_dig_beep_ctrl, + 0, "PC Beep Playback Switch", 0); +} +#endif + static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; @@ -3367,6 +3422,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out #ifdef CONFIG_SND_HDA_INPUT_BEEP if (spec->digbeep_nid > 0) { hda_nid_t nid = spec->digbeep_nid; + unsigned int caps; err = stac92xx_auto_create_beep_ctls(codec, nid); if (err < 0) @@ -3374,6 +3430,14 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out err = snd_hda_attach_beep_device(codec, nid); if (err < 0) return err; + /* if no beep switch is available, make its own one */ + caps = query_amp_caps(codec, nid, HDA_OUTPUT); + if (codec->beep && + !((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT)) { + err = stac92xx_beep_switch_ctl(codec); + if (err < 0) + return err; + } } #endif @@ -3531,6 +3595,12 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) return err; + if (spec->num_muxes > 0) { + err = stac92xx_auto_create_mux_input_ctls(codec); + if (err < 0) + return err; + } + if (spec->autocfg.dig_out_pin) spec->multiout.dig_out_nid = 0x05; if (spec->autocfg.dig_in_pin) @@ -3648,14 +3718,18 @@ static int stac92xx_init(struct hda_codec *codec) for (i = 0; i < AUTO_PIN_LAST; i++) { hda_nid_t nid = cfg->input_pins[i]; if (nid) { - unsigned int pinctl = snd_hda_codec_read(codec, nid, - 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - /* if PINCTL already set then skip */ - if (pinctl & AC_PINCAP_IN) - continue; - pinctl = AC_PINCTL_IN_EN; - if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) - pinctl |= stac92xx_get_vref(codec, nid); + unsigned int pinctl; + if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { + /* for mic pins, force to initialize */ + pinctl = stac92xx_get_vref(codec, nid); + } else { + pinctl = snd_hda_codec_read(codec, nid, 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + /* if PINCTL already set then skip */ + if (pinctl & AC_PINCTL_IN_EN) + continue; + } + pinctl |= AC_PINCTL_IN_EN; stac92xx_auto_set_pinctl(codec, nid, pinctl); } } @@ -3777,11 +3851,30 @@ static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid) return 0; } +/* return non-zero if the hp-pin of the given array index isn't + * a jack-detection target + */ +static int no_hp_sensing(struct sigmatel_spec *spec, int i) +{ + struct auto_pin_cfg *cfg = &spec->autocfg; + + /* ignore sensing of shared line and mic jacks */ + if (spec->line_switch && + cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_LINE]) + return 1; + if (spec->mic_switch && + cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_MIC]) + return 1; + /* ignore if the pin is set as line-out */ + if (cfg->hp_pins[i] == spec->hp_switch) + return 1; + return 0; +} + static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) { struct sigmatel_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; - int nid = cfg->hp_pins[cfg->hp_outs - 1]; int i, presence; presence = 0; @@ -3792,15 +3885,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) for (i = 0; i < cfg->hp_outs; i++) { if (presence) break; - if (spec->hp_switch && cfg->hp_pins[i] == nid) - break; + if (no_hp_sensing(spec, i)) + continue; presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); } if (presence) { - /* disable lineouts, enable hp */ + /* disable lineouts */ if (spec->hp_switch) - stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN); + stac92xx_reset_pinctl(codec, spec->hp_switch, + AC_PINCTL_OUT_EN); for (i = 0; i < cfg->line_outs; i++) stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], AC_PINCTL_OUT_EN); @@ -3812,9 +3906,10 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) spec->gpio_dir, spec->gpio_data & ~spec->eapd_mask); } else { - /* enable lineouts, disable hp */ + /* enable lineouts */ if (spec->hp_switch) - stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); + stac92xx_set_pinctl(codec, spec->hp_switch, + AC_PINCTL_OUT_EN); for (i = 0; i < cfg->line_outs; i++) stac92xx_set_pinctl(codec, cfg->line_out_pins[i], AC_PINCTL_OUT_EN); @@ -3826,8 +3921,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) spec->gpio_dir, spec->gpio_data | spec->eapd_mask); } - if (!spec->hp_switch && cfg->hp_outs > 1 && presence) - stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); + /* toggle hp outs */ + for (i = 0; i < cfg->hp_outs; i++) { + unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN; + if (no_hp_sensing(spec, i)) + continue; + if (presence) + stac92xx_set_pinctl(codec, cfg->hp_pins[i], val); + else + stac92xx_reset_pinctl(codec, cfg->hp_pins[i], val); + } } static void stac92xx_pin_sense(struct hda_codec *codec, int idx) @@ -4133,12 +4236,17 @@ again: sizeof(stac92hd73xx_dmux)); switch (spec->board_config) { - case STAC_DELL_M6: + case STAC_DELL_EQ: spec->init = dell_eq_core_init; + /* fallthru */ + case STAC_DELL_M6: spec->num_smuxes = 0; spec->mixer = &stac92hd73xx_6ch_mixer[DELL_M6_MIXER]; spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; spec->num_amps = 1; + + if (!spec->init) + spec->init = dell_m6_core_init; switch (codec->subsystem_id) { case 0x1028025e: /* Analog Mics */ case 0x1028025f: @@ -4148,8 +4256,6 @@ again: break; case 0x10280271: /* Digital Mics */ case 0x10280272: - spec->init = dell_m6_core_init; - /* fall-through */ case 0x10280254: case 0x10280255: stac92xx_set_config_reg(codec, 0x13, 0x90A60160); @@ -4376,6 +4482,13 @@ again: stac92xx_set_config_regs(codec); } + if (spec->board_config > STAC_92HD71BXX_REF) { + /* GPIO0 = EAPD */ + spec->gpio_mask = 0x01; + spec->gpio_dir = 0x01; + spec->gpio_data = 0x01; + } + switch (codec->vendor_id) { case 0x111d76b6: /* 4 Port without Analog Mixer */ case 0x111d76b7: @@ -4386,10 +4499,10 @@ again: codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; break; case 0x111d7608: /* 5 Port with Analog Mixer */ - switch (codec->subsystem_id) { - case 0x103c361a: + switch (spec->board_config) { + case STAC_HP_M4: /* Enable VREF power saving on GPIO1 detect */ - snd_hda_codec_write(codec, codec->afg, 0, + snd_hda_codec_write_cache(codec, codec->afg, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); snd_hda_codec_write_cache(codec, codec->afg, 0, AC_VERB_SET_UNSOLICITED_ENABLE, @@ -4435,13 +4548,6 @@ again: spec->aloopback_mask = 0x50; spec->aloopback_shift = 0; - if (spec->board_config > STAC_92HD71BXX_REF) { - /* GPIO0 = EAPD */ - spec->gpio_mask = 0x01; - spec->gpio_dir = 0x01; - spec->gpio_data = 0x01; - } - spec->powerdown_adcs = 1; spec->digbeep_nid = 0x26; spec->mux_nids = stac92hd71bxx_mux_nids; @@ -4789,7 +4895,7 @@ static int patch_stac9205(struct hda_codec *codec) stac92xx_set_config_reg(codec, 0x20, 0x1c410030); /* Enable unsol response for GPIO4/Dock HP connection */ - snd_hda_codec_write(codec, codec->afg, 0, + snd_hda_codec_write_cache(codec, codec->afg, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); snd_hda_codec_write_cache(codec, codec->afg, 0, AC_VERB_SET_UNSOLICITED_ENABLE, diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index fd9a117f37a..f23a73577c2 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1315,8 +1315,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, } for (i = 0; i < 2; i++) { mgr->mem[i].phys = pci_resource_start(pci, i); - mgr->mem[i].virt = ioremap_nocache(mgr->mem[i].phys, - pci_resource_len(pci, i)); + mgr->mem[i].virt = pci_ioremap_bar(pci, i); if (!mgr->mem[i].virt) { printk(KERN_ERR "unable to remap resource 0x%lx\n", mgr->mem[i].phys); diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 58621206a2b..7d2b136295d 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c @@ -1230,8 +1230,11 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id return -ENOMEM; } - if (snd_BUG_ON(pci_id->driver_data >= PCI_ID_LAST)) + if (snd_BUG_ON(pci_id->driver_data >= PCI_ID_LAST)) { + kfree(mgr); + pci_disable_device(pci); return -ENODEV; + } card_name = pcxhr_board_params[pci_id->driver_data].board_name; mgr->playback_chips = pcxhr_board_params[pci_id->driver_data].playback_chips; mgr->capture_chips = pcxhr_board_params[pci_id->driver_data].capture_chips; diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index d723543bead..736246f98ac 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -4548,11 +4548,20 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne { struct hdsp *hdsp = (struct hdsp *)hw->private_data; void __user *argp = (void __user *)arg; + int err; switch (cmd) { case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: { struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg; + err = hdsp_check_for_iobox(hdsp); + if (err < 0) + return err; + + err = hdsp_check_for_firmware(hdsp, 1); + if (err < 0) + return err; + if (!(hdsp->state & HDSP_FirmwareLoaded)) { snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n"); return -EINVAL; @@ -4572,10 +4581,14 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne unsigned long flags; int i; - if (!(hdsp->state & HDSP_FirmwareLoaded)) { - snd_printk(KERN_ERR "Hammerfall-DSP: Firmware needs to be uploaded to the card.\n"); - return -EINVAL; - } + err = hdsp_check_for_iobox(hdsp); + if (err < 0) + return err; + + err = hdsp_check_for_firmware(hdsp, 1); + if (err < 0) + return err; + spin_lock_irqsave(&hdsp->lock, flags); info.pref_sync_ref = (unsigned char)hdsp_pref_sync_ref(hdsp); info.wordclock_sync_check = (unsigned char)hdsp_wc_sync_check(hdsp); @@ -5045,6 +5058,10 @@ static int __devinit snd_hdsp_create(struct snd_card *card, /* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */ ssleep(2); + err = hdsp_check_for_iobox(hdsp); + if (err < 0) + return err; + if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { #ifdef HDSP_FW_LOADER if ((err = hdsp_request_fw_loader(hdsp)) < 0) @@ -5057,7 +5074,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, /* init is complete, we return */ return 0; #endif - /* no iobox connected, we defer initialization */ + /* we defer initialization */ snd_printk(KERN_INFO "Hammerfall-DSP: card initialization pending : waiting for firmware\n"); if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) return err; diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 20d0e328288..8f9e3859c37 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -666,6 +666,7 @@ static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card) card->avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16; card->avs.avs_audio_format = PS3AV_CMD_AUDIO_FORMAT_PCM; card->avs.avs_audio_source = PS3AV_CMD_AUDIO_SOURCE_SERIAL; + memcpy(card->avs.avs_cs_info, ps3av_mode_cs_info, 8); ret = snd_ps3_change_avsetting(card); @@ -685,6 +686,7 @@ static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream) { struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); struct snd_ps3_avsetting_info avs; + int ret; avs = card->avs; @@ -729,19 +731,92 @@ static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream) return 1; } - if ((card->avs.avs_audio_width != avs.avs_audio_width) || - (card->avs.avs_audio_rate != avs.avs_audio_rate)) { - card->avs = avs; - snd_ps3_change_avsetting(card); + memcpy(avs.avs_cs_info, ps3av_mode_cs_info, 8); + if (memcmp(&card->avs, &avs, sizeof(avs))) { pr_debug("%s: after freq=%d width=%d\n", __func__, card->avs.avs_audio_rate, card->avs.avs_audio_width); - return 0; + card->avs = avs; + snd_ps3_change_avsetting(card); + ret = 0; } else + ret = 1; + + /* check CS non-audio bit and mute accordingly */ + if (avs.avs_cs_info[0] & 0x02) + ps3av_audio_mute_analog(1); /* mute if non-audio */ + else + ps3av_audio_mute_analog(0); + + return ret; +} + +/* + * SPDIF status bits controls + */ +static int snd_ps3_spdif_mask_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; + uinfo->count = 1; + return 0; +} + +/* FIXME: ps3av_set_audio_mode() assumes only consumer mode */ +static int snd_ps3_spdif_cmask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + memset(ucontrol->value.iec958.status, 0xff, 8); + return 0; +} + +static int snd_ps3_spdif_pmask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int snd_ps3_spdif_default_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + memcpy(ucontrol->value.iec958.status, ps3av_mode_cs_info, 8); + return 0; +} + +static int snd_ps3_spdif_default_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + if (memcmp(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8)) { + memcpy(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8); return 1; + } + return 0; } +static struct snd_kcontrol_new spdif_ctls[] = { + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), + .info = snd_ps3_spdif_mask_info, + .get = snd_ps3_spdif_cmask_get, + }, + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK), + .info = snd_ps3_spdif_mask_info, + .get = snd_ps3_spdif_pmask_get, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), + .info = snd_ps3_spdif_mask_info, + .get = snd_ps3_spdif_default_get, + .put = snd_ps3_spdif_default_put, + }, +}; static int snd_ps3_map_mmio(void) @@ -842,7 +917,7 @@ static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start) static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev) { - int ret; + int i, ret; u64 lpar_addr, lpar_size; BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1)); @@ -903,6 +978,15 @@ static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev) strcpy(the_card.card->driver, "PS3"); strcpy(the_card.card->shortname, "PS3"); strcpy(the_card.card->longname, "PS3 sound"); + + /* create control elements */ + for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) { + ret = snd_ctl_add(the_card.card, + snd_ctl_new1(&spdif_ctls[i], &the_card)); + if (ret < 0) + goto clean_card; + } + /* create PCM devices instance */ /* NOTE:this driver works assuming pcm:substream = 1:1 */ ret = snd_pcm_new(the_card.card, diff --git a/sound/ppc/snd_ps3.h b/sound/ppc/snd_ps3.h index 4b7e6fbbe50..326fb29e82d 100644 --- a/sound/ppc/snd_ps3.h +++ b/sound/ppc/snd_ps3.h @@ -51,6 +51,7 @@ struct snd_ps3_avsetting_info { uint32_t avs_audio_width; uint32_t avs_audio_format; /* fixed */ uint32_t avs_audio_source; /* fixed */ + unsigned char avs_cs_info[8]; }; /* * PS3 audio 'card' instance diff --git a/sound/soc/at32/playpaq_wm8510.c b/sound/soc/at32/playpaq_wm8510.c index 98a2d5826a8..b1966e4dfcd 100644 --- a/sound/soc/at32/playpaq_wm8510.c +++ b/sound/soc/at32/playpaq_wm8510.c @@ -304,7 +304,7 @@ static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = { -static const char *intercon[][3] = { +static const struct snd_soc_dapm_route intercon[] = { /* speaker connected to SPKOUT */ {"Ext Spk", NULL, "SPKOUTP"}, {"Ext Spk", NULL, "SPKOUTN"}, @@ -312,9 +312,6 @@ static const char *intercon[][3] = { {"Mic Bias", NULL, "Int Mic"}, {"MICN", NULL, "Mic Bias"}, {"MICP", NULL, "Mic Bias"}, - - /* Terminator */ - {NULL, NULL, NULL}, }; @@ -334,11 +331,8 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec) /* * Setup audio path interconnects */ - for (i = 0; intercon[i][0] != NULL; i++) { - snd_soc_dapm_connect_input(codec, - intercon[i][0], - intercon[i][1], intercon[i][2]); - } + snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); + /* always connected pins */ diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index 827587f0818..e020c160ee4 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c @@ -70,12 +70,24 @@ static struct sport_param sport_params[2] = { } }; -static u16 sport_req[][7] = { - { P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, - P_SPORT0_DRPRI, P_SPORT0_RSCLK, 0}, - { P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, - P_SPORT1_DRPRI, P_SPORT1_RSCLK, 0}, -}; +/* + * Setting the TFS pin selector for SPORT 0 based on whether the selected + * port id F or G. If the port is F then no conflict should exist for the + * TFS. When Port G is selected and EMAC then there is a conflict between + * the PHY interrupt line and TFS. Current settings prevent the conflict + * by ignoring the TFS pin when Port G is selected. This allows both + * ssm2602 using Port G and EMAC concurrently. + */ +#ifdef CONFIG_BF527_SPORT0_PORTF +#define LOCAL_SPORT0_TFS (P_SPORT0_TFS) +#else +#define LOCAL_SPORT0_TFS (0) +#endif + +static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, + P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0}, + {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI, + P_SPORT1_RSCLK, P_SPORT1_TFS, 0} }; static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) @@ -98,23 +110,21 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, ret = -EINVAL; break; default: + printk(KERN_ERR "%s: Unknown DAI format type\n", __func__); ret = -EINVAL; break; } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - ret = -EINVAL; - break; - case SND_SOC_DAIFMT_CBM_CFS: - ret = -EINVAL; - break; case SND_SOC_DAIFMT_CBM_CFM: break; + case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBM_CFS: case SND_SOC_DAIFMT_CBS_CFM: ret = -EINVAL; break; default: + printk(KERN_ERR "%s: Unknown DAI master type\n", __func__); ret = -EINVAL; break; } diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 05336ed7e49..cff276ee261 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -863,17 +863,21 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: + /* + * match both interface format and signal polarities since they + * are fixed + */ + switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK | + SND_SOC_DAIFMT_INV_MASK)) { + case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): break; - case SND_SOC_DAIFMT_DSP_A: + case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF): iface_breg |= (0x01 << 6); break; - case SND_SOC_DAIFMT_RIGHT_J: + case (SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_NB_NF): iface_breg |= (0x02 << 6); break; - case SND_SOC_DAIFMT_LEFT_J: + case (SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF): iface_breg |= (0x03 << 6); break; default: diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index aba402b3c99..945b32ed988 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -140,7 +140,7 @@ SOC_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0), SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0), SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0), -SOC_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0), +SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0), SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0), SOC_ENUM("ALC Function", wm9713_enum[6]), SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0), diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 86923299bc1..94a02eaa482 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -277,7 +277,7 @@ static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd) struct mpc52xx_psc __iomem *regs = psc_i2s->psc_regs; u16 imr; u8 psc_cmd; - long flags; + unsigned long flags; if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) s = &psc_i2s->capture; @@ -699,9 +699,11 @@ static ssize_t psc_i2s_stat_store(struct device *dev, return count; } -DEVICE_ATTR(status, 0644, psc_i2s_status_show, NULL); -DEVICE_ATTR(playback_underrun, 0644, psc_i2s_stat_show, psc_i2s_stat_store); -DEVICE_ATTR(capture_overrun, 0644, psc_i2s_stat_show, psc_i2s_stat_store); +static DEVICE_ATTR(status, 0644, psc_i2s_status_show, NULL); +static DEVICE_ATTR(playback_underrun, 0644, psc_i2s_stat_show, + psc_i2s_stat_store); +static DEVICE_ATTR(capture_overrun, 0644, psc_i2s_stat_show, + psc_i2s_stat_store); /* --------------------------------------------------------------------- * OF platform bus binding code: @@ -819,8 +821,8 @@ static int __devinit psc_i2s_of_probe(struct of_device *op, /* Register the SYSFS files */ rc = device_create_file(psc_i2s->dev, &dev_attr_status); - rc = device_create_file(psc_i2s->dev, &dev_attr_capture_overrun); - rc = device_create_file(psc_i2s->dev, &dev_attr_playback_underrun); + rc |= device_create_file(psc_i2s->dev, &dev_attr_capture_overrun); + rc |= device_create_file(psc_i2s->dev, &dev_attr_playback_underrun); if (rc) dev_info(psc_i2s->dev, "error creating sysfs files\n"); diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 0a063a98a66..8485a8a9d0f 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -43,6 +43,7 @@ struct omap_mcbsp_data { unsigned int bus_id; struct omap_mcbsp_reg_cfg regs; + unsigned int fmt; /* * Flags indicating is the bus already activated and configured by * another substream @@ -200,6 +201,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; + int wlen; unsigned long port; if (cpu_class_is_omap1()) { @@ -244,19 +246,29 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: /* Set word lengths */ + wlen = 16; regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16); - /* Set FS period and length in terms of bit clock periods */ - regs->srgr2 |= FPER(16 * 2 - 1); - regs->srgr1 |= FWID(16 - 1); break; default: /* Unsupported PCM format */ return -EINVAL; } + /* Set FS period and length in terms of bit clock periods */ + switch (mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + regs->srgr2 |= FPER(wlen * 2 - 1); + regs->srgr1 |= FWID(wlen - 1); + break; + case SND_SOC_DAIFMT_DSP_A: + regs->srgr2 |= FPER(wlen * 2 - 1); + regs->srgr1 |= FWID(wlen * 2 - 2); + break; + } + omap_mcbsp_config(bus_id, &mcbsp_data->regs); mcbsp_data->configured = 1; @@ -276,6 +288,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, if (mcbsp_data->configured) return 0; + mcbsp_data->fmt = fmt; memset(regs, 0, sizeof(*regs)); /* Generic McBSP register settings */ regs->spcr2 |= XINTM(3) | FREE; diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index dd7fa0b329c..2718eaf7895 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -18,13 +18,13 @@ #include <linux/timer.h> #include <linux/interrupt.h> #include <linux/platform_device.h> +#include <linux/gpio.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> #include <sound/soc-dapm.h> #include <asm/mach-types.h> -#include <asm/hardware/scoop.h> #include <mach/pxa-regs.h> #include <mach/hardware.h> #include <mach/corgi.h> @@ -54,8 +54,8 @@ static void corgi_ext_control(struct snd_soc_codec *codec) switch (corgi_jack_func) { case CORGI_HP: /* set = unmute headphone */ - set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); - set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); + gpio_set_value(CORGI_GPIO_MUTE_L, 1); + gpio_set_value(CORGI_GPIO_MUTE_R, 1); snd_soc_dapm_disable_pin(codec, "Mic Jack"); snd_soc_dapm_disable_pin(codec, "Line Jack"); snd_soc_dapm_enable_pin(codec, "Headphone Jack"); @@ -63,24 +63,24 @@ static void corgi_ext_control(struct snd_soc_codec *codec) break; case CORGI_MIC: /* reset = mute headphone */ - reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); - reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); + gpio_set_value(CORGI_GPIO_MUTE_L, 0); + gpio_set_value(CORGI_GPIO_MUTE_R, 0); snd_soc_dapm_enable_pin(codec, "Mic Jack"); snd_soc_dapm_disable_pin(codec, "Line Jack"); snd_soc_dapm_disable_pin(codec, "Headphone Jack"); snd_soc_dapm_disable_pin(codec, "Headset Jack"); break; case CORGI_LINE: - reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); - reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); + gpio_set_value(CORGI_GPIO_MUTE_L, 0); + gpio_set_value(CORGI_GPIO_MUTE_R, 0); snd_soc_dapm_disable_pin(codec, "Mic Jack"); snd_soc_dapm_enable_pin(codec, "Line Jack"); snd_soc_dapm_disable_pin(codec, "Headphone Jack"); snd_soc_dapm_disable_pin(codec, "Headset Jack"); break; case CORGI_HEADSET: - reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); - set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); + gpio_set_value(CORGI_GPIO_MUTE_L, 0); + gpio_set_value(CORGI_GPIO_MUTE_R, 1); snd_soc_dapm_enable_pin(codec, "Mic Jack"); snd_soc_dapm_disable_pin(codec, "Line Jack"); snd_soc_dapm_disable_pin(codec, "Headphone Jack"); @@ -114,8 +114,8 @@ static int corgi_shutdown(struct snd_pcm_substream *substream) struct snd_soc_codec *codec = rtd->socdev->codec; /* set = unmute headphone */ - set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L); - set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R); + gpio_set_value(CORGI_GPIO_MUTE_L, 1); + gpio_set_value(CORGI_GPIO_MUTE_R, 1); return 0; } @@ -218,22 +218,14 @@ static int corgi_set_spk(struct snd_kcontrol *kcontrol, static int corgi_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - if (SND_SOC_DAPM_EVENT_ON(event)) - set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON); - else - reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON); - + gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event)); return 0; } static int corgi_mic_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - if (SND_SOC_DAPM_EVENT_ON(event)) - set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); - else - reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS); - + gpio_set_value(CORGI_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event)); return 0; } diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index a80ae074b09..a7a3a9c5c6f 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -49,7 +49,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = { static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { .name = "AC97 PCM Stereo out", .dev_addr = __PREG(PCDR), - .drcmr = &DRCMRTXPCDR, + .drcmr = &DRCMR(12), .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST32 | DCMD_WIDTH4, }; @@ -57,7 +57,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = { .name = "AC97 PCM Stereo in", .dev_addr = __PREG(PCDR), - .drcmr = &DRCMRRXPCDR, + .drcmr = &DRCMR(11), .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST32 | DCMD_WIDTH4, }; @@ -65,7 +65,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = { static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = { .name = "AC97 Aux PCM (Slot 5) Mono out", .dev_addr = __PREG(MODR), - .drcmr = &DRCMRTXMODR, + .drcmr = &DRCMR(10), .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST16 | DCMD_WIDTH2, }; @@ -73,7 +73,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = { static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = { .name = "AC97 Aux PCM (Slot 5) Mono in", .dev_addr = __PREG(MODR), - .drcmr = &DRCMRRXMODR, + .drcmr = &DRCMR(9), .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST16 | DCMD_WIDTH2, }; @@ -81,7 +81,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = { static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = { .name = "AC97 Mic PCM (Slot 6) Mono in", .dev_addr = __PREG(MCDR), - .drcmr = &DRCMRRXMCDR, + .drcmr = &DRCMR(8), .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST16 | DCMD_WIDTH2, }; diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 64057b1d220..e758034db5c 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -39,6 +39,45 @@ struct pxa2xx_gpio { u32 frm; }; +/* + * I2S Controller Register and Bit Definitions + */ +#define SACR0 __REG(0x40400000) /* Global Control Register */ +#define SACR1 __REG(0x40400004) /* Serial Audio I 2 S/MSB-Justified Control Register */ +#define SASR0 __REG(0x4040000C) /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */ +#define SAIMR __REG(0x40400014) /* Serial Audio Interrupt Mask Register */ +#define SAICR __REG(0x40400018) /* Serial Audio Interrupt Clear Register */ +#define SADIV __REG(0x40400060) /* Audio Clock Divider Register. */ +#define SADR __REG(0x40400080) /* Serial Audio Data Register (TX and RX FIFO access Register). */ + +#define SACR0_RFTH(x) ((x) << 12) /* Rx FIFO Interrupt or DMA Trigger Threshold */ +#define SACR0_TFTH(x) ((x) << 8) /* Tx FIFO Interrupt or DMA Trigger Threshold */ +#define SACR0_STRF (1 << 5) /* FIFO Select for EFWR Special Function */ +#define SACR0_EFWR (1 << 4) /* Enable EFWR Function */ +#define SACR0_RST (1 << 3) /* FIFO, i2s Register Reset */ +#define SACR0_BCKD (1 << 2) /* Bit Clock Direction */ +#define SACR0_ENB (1 << 0) /* Enable I2S Link */ +#define SACR1_ENLBF (1 << 5) /* Enable Loopback */ +#define SACR1_DRPL (1 << 4) /* Disable Replaying Function */ +#define SACR1_DREC (1 << 3) /* Disable Recording Function */ +#define SACR1_AMSL (1 << 0) /* Specify Alternate Mode */ + +#define SASR0_I2SOFF (1 << 7) /* Controller Status */ +#define SASR0_ROR (1 << 6) /* Rx FIFO Overrun */ +#define SASR0_TUR (1 << 5) /* Tx FIFO Underrun */ +#define SASR0_RFS (1 << 4) /* Rx FIFO Service Request */ +#define SASR0_TFS (1 << 3) /* Tx FIFO Service Request */ +#define SASR0_BSY (1 << 2) /* I2S Busy */ +#define SASR0_RNE (1 << 1) /* Rx FIFO Not Empty */ +#define SASR0_TNF (1 << 0) /* Tx FIFO Not Empty */ + +#define SAICR_ROR (1 << 6) /* Clear Rx FIFO Overrun Interrupt */ +#define SAICR_TUR (1 << 5) /* Clear Tx FIFO Underrun Interrupt */ + +#define SAIMR_ROR (1 << 6) /* Enable Rx FIFO Overrun Condition Interrupt */ +#define SAIMR_TUR (1 << 5) /* Enable Tx FIFO Underrun Condition Interrupt */ +#define SAIMR_RFS (1 << 4) /* Enable Rx FIFO Service Interrupt */ +#define SAIMR_TFS (1 << 3) /* Enable Tx FIFO Service Interrupt */ struct pxa_i2s_port { u32 sadiv; @@ -54,7 +93,7 @@ static struct clk *clk_i2s; static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { .name = "I2S PCM Stereo out", .dev_addr = __PREG(SADR), - .drcmr = &DRCMRTXSADR, + .drcmr = &DRCMR(3), .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST32 | DCMD_WIDTH4, }; @@ -62,7 +101,7 @@ static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = { .name = "I2S PCM Stereo in", .dev_addr = __PREG(SADR), - .drcmr = &DRCMRRXSADR, + .drcmr = &DRCMR(2), .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST32 | DCMD_WIDTH4, }; diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index 8f89188e541..d307b6757e9 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -19,16 +19,15 @@ #include <linux/timer.h> #include <linux/interrupt.h> #include <linux/platform_device.h> +#include <linux/gpio.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> #include <sound/soc-dapm.h> #include <asm/mach-types.h> -#include <asm/hardware/scoop.h> #include <mach/pxa-regs.h> #include <mach/hardware.h> -#include <mach/akita.h> #include <mach/spitz.h> #include "../codecs/wm8750.h" #include "pxa2xx-pcm.h" @@ -63,8 +62,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec) snd_soc_dapm_disable_pin(codec, "Mic Jack"); snd_soc_dapm_disable_pin(codec, "Line Jack"); snd_soc_dapm_enable_pin(codec, "Headphone Jack"); - set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); - set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); + gpio_set_value(SPITZ_GPIO_MUTE_L, 1); + gpio_set_value(SPITZ_GPIO_MUTE_R, 1); break; case SPITZ_MIC: /* enable mic jack and bias, mute hp */ @@ -72,8 +71,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec) snd_soc_dapm_disable_pin(codec, "Headset Jack"); snd_soc_dapm_disable_pin(codec, "Line Jack"); snd_soc_dapm_enable_pin(codec, "Mic Jack"); - reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); - reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); + gpio_set_value(SPITZ_GPIO_MUTE_L, 0); + gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; case SPITZ_LINE: /* enable line jack, disable mic bias and mute hp */ @@ -81,8 +80,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec) snd_soc_dapm_disable_pin(codec, "Headset Jack"); snd_soc_dapm_disable_pin(codec, "Mic Jack"); snd_soc_dapm_enable_pin(codec, "Line Jack"); - reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); - reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); + gpio_set_value(SPITZ_GPIO_MUTE_L, 0); + gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; case SPITZ_HEADSET: /* enable and unmute headset jack enable mic bias, mute L hp */ @@ -90,8 +89,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec) snd_soc_dapm_enable_pin(codec, "Mic Jack"); snd_soc_dapm_disable_pin(codec, "Line Jack"); snd_soc_dapm_enable_pin(codec, "Headset Jack"); - reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); - set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); + gpio_set_value(SPITZ_GPIO_MUTE_L, 0); + gpio_set_value(SPITZ_GPIO_MUTE_R, 1); break; case SPITZ_HP_OFF: @@ -100,8 +99,8 @@ static void spitz_ext_control(struct snd_soc_codec *codec) snd_soc_dapm_disable_pin(codec, "Headset Jack"); snd_soc_dapm_disable_pin(codec, "Mic Jack"); snd_soc_dapm_disable_pin(codec, "Line Jack"); - reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L); - reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R); + gpio_set_value(SPITZ_GPIO_MUTE_L, 0); + gpio_set_value(SPITZ_GPIO_MUTE_R, 0); break; } snd_soc_dapm_sync(codec); @@ -215,23 +214,14 @@ static int spitz_set_spk(struct snd_kcontrol *kcontrol, static int spitz_mic_bias(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { - if (machine_is_borzoi() || machine_is_spitz()) { - if (SND_SOC_DAPM_EVENT_ON(event)) - set_scoop_gpio(&spitzscoop2_device.dev, - SPITZ_SCP2_MIC_BIAS); - else - reset_scoop_gpio(&spitzscoop2_device.dev, - SPITZ_SCP2_MIC_BIAS); - } + if (machine_is_borzoi() || machine_is_spitz()) + gpio_set_value(SPITZ_GPIO_MIC_BIAS, + SND_SOC_DAPM_EVENT_ON(event)); + + if (machine_is_akita()) + gpio_set_value(AKITA_GPIO_MIC_BIAS, + SND_SOC_DAPM_EVENT_ON(event)); - if (machine_is_akita()) { - if (SND_SOC_DAPM_EVENT_ON(event)) - akita_set_ioexp(&akitaioexp_device.dev, - AKITA_IOEXP_MIC_BIAS); - else - akita_reset_ioexp(&akitaioexp_device.dev, - AKITA_IOEXP_MIC_BIAS); - } return 0; } diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0af3bbde5bb..16c7453f494 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1462,7 +1462,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; int max = mc->max; - unsigned int shift = mc->min; + unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; if (max == 1) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index efbd0b37810..7351db9606e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -831,7 +831,7 @@ int snd_soc_dapm_sys_add(struct device *dev) return ret; asoc_debugfs = debugfs_create_dir("asoc", NULL); - if (!IS_ERR(asoc_debugfs)) + if (!IS_ERR(asoc_debugfs) && asoc_debugfs) debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs, &pop_time); else diff --git a/sound/sound_core.c b/sound/sound_core.c index ee66d43f848..a75b289a5d7 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c @@ -220,9 +220,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati else sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP); - device_create_drvdata(sound_class, dev, - MKDEV(SOUND_MAJOR, s->unit_minor), - NULL, s->name+6); + device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor), + NULL, s->name+6); return r; fail: diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 49acee0c484..f87933e4881 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c @@ -1,6 +1,6 @@ /* * Driver for AMD7930 sound chips found on Sparcs. - * Copyright (C) 2002 David S. Miller <davem@redhat.com> + * Copyright (C) 2002, 2008 David S. Miller <davem@davemloft.net> * * Based entirely upon drivers/sbus/audio/amd7930.c which is: * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu) @@ -35,6 +35,8 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/moduleparam.h> +#include <linux/of.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> @@ -44,7 +46,6 @@ #include <asm/io.h> #include <asm/irq.h> -#include <asm/sbus.h> #include <asm/prom.h> static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ @@ -335,8 +336,8 @@ struct snd_amd7930 { int pgain; int mgain; + struct of_device *op; unsigned int irq; - unsigned int regs_size; struct snd_amd7930 *next; }; @@ -905,13 +906,16 @@ static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd) static int snd_amd7930_free(struct snd_amd7930 *amd) { + struct of_device *op = amd->op; + amd7930_idle(amd); if (amd->irq) free_irq(amd->irq, amd); if (amd->regs) - sbus_iounmap(amd->regs, amd->regs_size); + of_iounmap(&op->resource[0], amd->regs, + resource_size(&op->resource[0])); kfree(amd); @@ -930,13 +934,12 @@ static struct snd_device_ops snd_amd7930_dev_ops = { }; static int __devinit snd_amd7930_create(struct snd_card *card, - struct resource *rp, - unsigned int reg_size, + struct of_device *op, int irq, int dev, struct snd_amd7930 **ramd) { - unsigned long flags; struct snd_amd7930 *amd; + unsigned long flags; int err; *ramd = NULL; @@ -946,9 +949,10 @@ static int __devinit snd_amd7930_create(struct snd_card *card, spin_lock_init(&amd->lock); amd->card = card; - amd->regs_size = reg_size; + amd->op = op; - amd->regs = sbus_ioremap(rp, 0, amd->regs_size, "amd7930"); + amd->regs = of_ioremap(&op->resource[0], 0, + resource_size(&op->resource[0]), "amd7930"); if (!amd->regs) { snd_printk("amd7930-%d: Unable to map chip registers.\n", dev); return -EIO; @@ -997,12 +1001,15 @@ static int __devinit snd_amd7930_create(struct snd_card *card, return 0; } -static int __devinit amd7930_attach_common(struct resource *rp, int irq) +static int __devinit amd7930_sbus_probe(struct of_device *op, const struct of_device_id *match) { + struct resource *rp = &op->resource[0]; static int dev_num; struct snd_card *card; struct snd_amd7930 *amd; - int err; + int err, irq; + + irq = op->irqs[0]; if (dev_num >= SNDRV_CARDS) return -ENODEV; @@ -1023,8 +1030,7 @@ static int __devinit amd7930_attach_common(struct resource *rp, int irq) (unsigned long long)rp->start, irq); - if ((err = snd_amd7930_create(card, rp, - (rp->end - rp->start) + 1, + if ((err = snd_amd7930_create(card, op, irq, dev_num, &amd)) < 0) goto out_err; @@ -1049,43 +1055,7 @@ out_err: return err; } -static int __devinit amd7930_obio_attach(struct device_node *dp) -{ - const struct linux_prom_registers *regs; - const struct linux_prom_irqs *irqp; - struct resource res, *rp; - int len; - - irqp = of_get_property(dp, "intr", &len); - if (!irqp) { - snd_printk("%s: Firmware node lacks IRQ property.\n", - dp->full_name); - return -ENODEV; - } - - regs = of_get_property(dp, "reg", &len); - if (!regs) { - snd_printk("%s: Firmware node lacks register property.\n", - dp->full_name); - return -ENODEV; - } - - rp = &res; - rp->start = regs->phys_addr; - rp->end = rp->start + regs->reg_size - 1; - rp->flags = IORESOURCE_IO | (regs->which_io & 0xff); - - return amd7930_attach_common(rp, irqp->pri); -} - -static int __devinit amd7930_sbus_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - - return amd7930_attach_common(&sdev->resource[0], sdev->irqs[0]); -} - -static struct of_device_id amd7930_match[] = { +static const struct of_device_id amd7930_match[] = { { .name = "audio", }, @@ -1100,20 +1070,7 @@ static struct of_platform_driver amd7930_sbus_driver = { static int __init amd7930_init(void) { - struct device_node *dp; - - /* Try to find the sun4c "audio" node first. */ - dp = of_find_node_by_path("/"); - dp = dp->child; - while (dp) { - if (!strcmp(dp->name, "audio")) - amd7930_obio_attach(dp); - - dp = dp->sibling; - } - - /* Probe each SBUS for amd7930 chips. */ - return of_register_driver(&amd7930_sbus_driver, &sbus_bus_type); + return of_register_driver(&amd7930_sbus_driver, &of_bus_type); } static void __exit amd7930_exit(void) diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 791d2fb821d..d44bf98e965 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -1,6 +1,6 @@ /* * Driver for CS4231 sound chips found on Sparcs. - * Copyright (C) 2002 David S. Miller <davem@redhat.com> + * Copyright (C) 2002, 2008 David S. Miller <davem@davemloft.net> * * Based entirely upon drivers/sbus/audio/cs4231.c which is: * Copyright (C) 1996, 1997, 1998 Derrick J Brashear (shadow@andrew.cmu.edu) @@ -17,7 +17,8 @@ #include <linux/moduleparam.h> #include <linux/irq.h> #include <linux/io.h> - +#include <linux/of.h> +#include <linux/of_device.h> #include <sound/core.h> #include <sound/pcm.h> @@ -29,13 +30,12 @@ #ifdef CONFIG_SBUS #define SBUS_SUPPORT -#include <asm/sbus.h> #endif #if defined(CONFIG_PCI) && defined(CONFIG_SPARC64) #define EBUS_SUPPORT #include <linux/pci.h> -#include <asm/ebus.h> +#include <asm/ebus_dma.h> #endif static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ @@ -70,8 +70,6 @@ struct cs4231_dma_control { int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len); unsigned int (*address)(struct cs4231_dma_control *dma_cont); - void (*preallocate)(struct snd_cs4231 *chip, - struct snd_pcm *pcm); #ifdef EBUS_SUPPORT struct ebus_dma_info ebus_info; #endif @@ -114,21 +112,12 @@ struct snd_cs4231 { struct mutex mce_mutex; /* mutex for mce register */ struct mutex open_mutex; /* mutex for ALSA open/close */ - union { -#ifdef SBUS_SUPPORT - struct sbus_dev *sdev; -#endif -#ifdef EBUS_SUPPORT - struct pci_dev *pdev; -#endif - } dev_u; + struct of_device *op; unsigned int irq[2]; unsigned int regs_size; struct snd_cs4231 *next; }; -static struct snd_cs4231 *cs4231_list; - /* Eventually we can use sound/isa/cs423x/cs4231_lib.c directly, but for * now.... -DaveM */ @@ -267,27 +256,19 @@ static unsigned char snd_cs4231_original_image[32] = static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr) { -#ifdef EBUS_SUPPORT if (cp->flags & CS4231_FLAG_EBUS) return readb(reg_addr); else -#endif -#ifdef SBUS_SUPPORT return sbus_readb(reg_addr); -#endif } static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, void __iomem *reg_addr) { -#ifdef EBUS_SUPPORT if (cp->flags & CS4231_FLAG_EBUS) return writeb(val, reg_addr); else -#endif -#ifdef SBUS_SUPPORT return sbus_writeb(val, reg_addr); -#endif } /* @@ -1258,7 +1239,9 @@ static int __init snd_cs4231_pcm(struct snd_card *card) pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; strcpy(pcm->name, "CS4231"); - chip->p_dma.preallocate(chip, pcm); + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, + &chip->op->dev, + 64 * 1024, 128 * 1024); chip->pcm = pcm; @@ -1627,8 +1610,7 @@ static int __init cs4231_attach_finish(struct snd_card *card) if (err < 0) goto out_err; - chip->next = cs4231_list; - cs4231_list = chip; + dev_set_drvdata(&chip->op->dev, chip); dev++; return 0; @@ -1783,24 +1765,19 @@ static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) return sbus_readl(base->regs + base->dir + APCVA); } -static void sbus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, - snd_dma_sbus_data(chip->dev_u.sdev), - 64 * 1024, 128 * 1024); -} - /* * Init and exit routines */ static int snd_cs4231_sbus_free(struct snd_cs4231 *chip) { + struct of_device *op = chip->op; + if (chip->irq[0]) free_irq(chip->irq[0], chip); if (chip->port) - sbus_iounmap(chip->port, chip->regs_size); + of_iounmap(&op->resource[0], chip->port, chip->regs_size); return 0; } @@ -1817,7 +1794,7 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = { }; static int __init snd_cs4231_sbus_create(struct snd_card *card, - struct sbus_dev *sdev, + struct of_device *op, int dev) { struct snd_cs4231 *chip = card->private_data; @@ -1828,13 +1805,13 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, spin_lock_init(&chip->p_dma.sbus_info.lock); mutex_init(&chip->mce_mutex); mutex_init(&chip->open_mutex); - chip->dev_u.sdev = sdev; - chip->regs_size = sdev->reg_addrs[0].reg_size; + chip->op = op; + chip->regs_size = resource_size(&op->resource[0]); memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image)); - chip->port = sbus_ioremap(&sdev->resource[0], 0, - chip->regs_size, "cs4231"); + chip->port = of_ioremap(&op->resource[0], 0, + chip->regs_size, "cs4231"); if (!chip->port) { snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); return -EIO; @@ -1849,22 +1826,20 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, chip->p_dma.enable = sbus_dma_enable; chip->p_dma.request = sbus_dma_request; chip->p_dma.address = sbus_dma_addr; - chip->p_dma.preallocate = sbus_dma_preallocate; chip->c_dma.prepare = sbus_dma_prepare; chip->c_dma.enable = sbus_dma_enable; chip->c_dma.request = sbus_dma_request; chip->c_dma.address = sbus_dma_addr; - chip->c_dma.preallocate = sbus_dma_preallocate; - if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, + if (request_irq(op->irqs[0], snd_cs4231_sbus_interrupt, IRQF_SHARED, "cs4231", chip)) { snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %d\n", - dev, sdev->irqs[0]); + dev, op->irqs[0]); snd_cs4231_sbus_free(chip); return -EBUSY; } - chip->irq[0] = sdev->irqs[0]; + chip->irq[0] = op->irqs[0]; if (snd_cs4231_probe(chip) < 0) { snd_cs4231_sbus_free(chip); @@ -1881,9 +1856,9 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, return 0; } -static int __init cs4231_sbus_attach(struct sbus_dev *sdev) +static int __devinit cs4231_sbus_probe(struct of_device *op, const struct of_device_id *match) { - struct resource *rp = &sdev->resource[0]; + struct resource *rp = &op->resource[0]; struct snd_card *card; int err; @@ -1895,9 +1870,9 @@ static int __init cs4231_sbus_attach(struct sbus_dev *sdev) card->shortname, rp->flags & 0xffL, (unsigned long long)rp->start, - sdev->irqs[0]); + op->irqs[0]); - err = snd_cs4231_sbus_create(card, sdev, dev); + err = snd_cs4231_sbus_create(card, op, dev); if (err < 0) { snd_card_free(card); return err; @@ -1950,30 +1925,25 @@ static unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont) return ebus_dma_addr(&dma_cont->ebus_info); } -static void _ebus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->dev_u.pdev), - 64*1024, 128*1024); -} - /* * Init and exit routines */ static int snd_cs4231_ebus_free(struct snd_cs4231 *chip) { + struct of_device *op = chip->op; + if (chip->c_dma.ebus_info.regs) { ebus_dma_unregister(&chip->c_dma.ebus_info); - iounmap(chip->c_dma.ebus_info.regs); + of_iounmap(&op->resource[2], chip->c_dma.ebus_info.regs, 0x10); } if (chip->p_dma.ebus_info.regs) { ebus_dma_unregister(&chip->p_dma.ebus_info); - iounmap(chip->p_dma.ebus_info.regs); + of_iounmap(&op->resource[1], chip->p_dma.ebus_info.regs, 0x10); } if (chip->port) - iounmap(chip->port); + of_iounmap(&op->resource[0], chip->port, 0x10); return 0; } @@ -1990,7 +1960,7 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = { }; static int __init snd_cs4231_ebus_create(struct snd_card *card, - struct linux_ebus_device *edev, + struct of_device *op, int dev) { struct snd_cs4231 *chip = card->private_data; @@ -2002,35 +1972,35 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, mutex_init(&chip->mce_mutex); mutex_init(&chip->open_mutex); chip->flags |= CS4231_FLAG_EBUS; - chip->dev_u.pdev = edev->bus->self; + chip->op = op; memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image)); strcpy(chip->c_dma.ebus_info.name, "cs4231(capture)"); chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback; chip->c_dma.ebus_info.client_cookie = chip; - chip->c_dma.ebus_info.irq = edev->irqs[0]; + chip->c_dma.ebus_info.irq = op->irqs[0]; strcpy(chip->p_dma.ebus_info.name, "cs4231(play)"); chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback; chip->p_dma.ebus_info.client_cookie = chip; - chip->p_dma.ebus_info.irq = edev->irqs[1]; + chip->p_dma.ebus_info.irq = op->irqs[1]; chip->p_dma.prepare = _ebus_dma_prepare; chip->p_dma.enable = _ebus_dma_enable; chip->p_dma.request = _ebus_dma_request; chip->p_dma.address = _ebus_dma_addr; - chip->p_dma.preallocate = _ebus_dma_preallocate; chip->c_dma.prepare = _ebus_dma_prepare; chip->c_dma.enable = _ebus_dma_enable; chip->c_dma.request = _ebus_dma_request; chip->c_dma.address = _ebus_dma_addr; - chip->c_dma.preallocate = _ebus_dma_preallocate; - chip->port = ioremap(edev->resource[0].start, 0x10); - chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10); - chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10); + chip->port = of_ioremap(&op->resource[0], 0, 0x10, "cs4231"); + chip->p_dma.ebus_info.regs = + of_ioremap(&op->resource[1], 0, 0x10, "cs4231_pdma"); + chip->c_dma.ebus_info.regs = + of_ioremap(&op->resource[2], 0, 0x10, "cs4231_cdma"); if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) { snd_cs4231_ebus_free(chip); @@ -2078,7 +2048,7 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, return 0; } -static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) +static int __devinit cs4231_ebus_probe(struct of_device *op, const struct of_device_id *match) { struct snd_card *card; int err; @@ -2089,10 +2059,10 @@ static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname, - edev->resource[0].start, - edev->irqs[0]); + op->resource[0].start, + op->irqs[0]); - err = snd_cs4231_ebus_create(card, edev, dev); + err = snd_cs4231_ebus_create(card, op, dev); if (err < 0) { snd_card_free(card); return err; @@ -2102,68 +2072,57 @@ static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) } #endif -static int __init cs4231_init(void) +static int __devinit cs4231_probe(struct of_device *op, const struct of_device_id *match) { -#ifdef SBUS_SUPPORT - struct sbus_bus *sbus; - struct sbus_dev *sdev; -#endif #ifdef EBUS_SUPPORT - struct linux_ebus *ebus; - struct linux_ebus_device *edev; + if (!strcmp(op->node->parent->name, "ebus")) + return cs4231_ebus_probe(op, match); #endif - int found; - - found = 0; - #ifdef SBUS_SUPPORT - for_all_sbusdev(sdev, sbus) { - if (!strcmp(sdev->prom_name, "SUNW,CS4231")) { - if (cs4231_sbus_attach(sdev) == 0) - found++; - } - } + if (!strcmp(op->node->parent->name, "sbus") || + !strcmp(op->node->parent->name, "sbi")) + return cs4231_sbus_probe(op, match); #endif -#ifdef EBUS_SUPPORT - for_each_ebus(ebus) { - for_each_ebusdev(edev, ebus) { - int match = 0; - - if (!strcmp(edev->prom_node->name, "SUNW,CS4231")) { - match = 1; - } else if (!strcmp(edev->prom_node->name, "audio")) { - const char *compat; - - compat = of_get_property(edev->prom_node, - "compatible", NULL); - if (compat && !strcmp(compat, "SUNW,CS4231")) - match = 1; - } + return -ENODEV; +} - if (match && - cs4231_ebus_attach(edev) == 0) - found++; - } - } -#endif +static int __devexit cs4231_remove(struct of_device *op) +{ + struct snd_cs4231 *chip = dev_get_drvdata(&op->dev); + snd_card_free(chip->card); - return (found > 0) ? 0 : -EIO; + return 0; } -static void __exit cs4231_exit(void) -{ - struct snd_cs4231 *p = cs4231_list; +static const struct of_device_id cs4231_match[] = { + { + .name = "SUNW,CS4231", + }, + { + .name = "audio", + .compatible = "SUNW,CS4231", + }, + {}, +}; - while (p != NULL) { - struct snd_cs4231 *next = p->next; +MODULE_DEVICE_TABLE(of, cs4231_match); - snd_card_free(p->card); +static struct of_platform_driver cs4231_driver = { + .name = "audio", + .match_table = cs4231_match, + .probe = cs4231_probe, + .remove = __devexit_p(cs4231_remove), +}; - p = next; - } +static int __init cs4231_init(void) +{ + return of_register_driver(&cs4231_driver, &of_bus_type); +} - cs4231_list = NULL; +static void __exit cs4231_exit(void) +{ + of_unregister_driver(&cs4231_driver); } module_init(cs4231_init); diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index c534a2a849f..23ed6f04a71 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -57,6 +57,7 @@ #include <linux/delay.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/dma-mapping.h> #include <sound/core.h> #include <sound/pcm.h> @@ -66,7 +67,7 @@ #include <sound/initval.h> #include <linux/of.h> -#include <asm/sbus.h> +#include <linux/of_device.h> #include <asm/atomic.h> MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets"); @@ -297,7 +298,7 @@ struct dbri_streaminfo { /* This structure holds the information for both chips (DBRI & CS4215) */ struct snd_dbri { int regs_size, irq; /* Needed for unload */ - struct sbus_dev *sdev; /* SBUS device info */ + struct of_device *op; /* OF device info */ spinlock_t lock; struct dbri_dma *dma; /* Pointer to our DMA block */ @@ -2093,14 +2094,15 @@ static int snd_dbri_hw_params(struct snd_pcm_substream *substream, */ if (info->dvma_buffer == 0) { if (DBRI_STREAMNO(substream) == DBRI_PLAY) - direction = SBUS_DMA_TODEVICE; + direction = DMA_TO_DEVICE; else - direction = SBUS_DMA_FROMDEVICE; + direction = DMA_FROM_DEVICE; - info->dvma_buffer = sbus_map_single(dbri->sdev, - runtime->dma_area, - params_buffer_bytes(hw_params), - direction); + info->dvma_buffer = + dma_map_single(&dbri->op->dev, + runtime->dma_area, + params_buffer_bytes(hw_params), + direction); } direction = params_buffer_bytes(hw_params); @@ -2121,12 +2123,12 @@ static int snd_dbri_hw_free(struct snd_pcm_substream *substream) */ if (info->dvma_buffer) { if (DBRI_STREAMNO(substream) == DBRI_PLAY) - direction = SBUS_DMA_TODEVICE; + direction = DMA_TO_DEVICE; else - direction = SBUS_DMA_FROMDEVICE; + direction = DMA_FROM_DEVICE; - sbus_unmap_single(dbri->sdev, info->dvma_buffer, - substream->runtime->buffer_size, direction); + dma_unmap_single(&dbri->op->dev, info->dvma_buffer, + substream->runtime->buffer_size, direction); info->dvma_buffer = 0; } if (info->pipe != -1) { @@ -2519,31 +2521,34 @@ static void __devinit snd_dbri_proc(struct snd_card *card) static void snd_dbri_free(struct snd_dbri *dbri); static int __devinit snd_dbri_create(struct snd_card *card, - struct sbus_dev *sdev, - int irq, int dev) + struct of_device *op, + int irq, int dev) { struct snd_dbri *dbri = card->private_data; int err; spin_lock_init(&dbri->lock); - dbri->sdev = sdev; + dbri->op = op; dbri->irq = irq; - dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), - &dbri->dma_dvma); + dbri->dma = dma_alloc_coherent(&op->dev, + sizeof(struct dbri_dma), + &dbri->dma_dvma, GFP_ATOMIC); + if (!dbri->dma) + return -ENOMEM; memset((void *)dbri->dma, 0, sizeof(struct dbri_dma)); dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n", dbri->dma, dbri->dma_dvma); /* Map the registers into memory. */ - dbri->regs_size = sdev->reg_addrs[0].reg_size; - dbri->regs = sbus_ioremap(&sdev->resource[0], 0, - dbri->regs_size, "DBRI Registers"); + dbri->regs_size = resource_size(&op->resource[0]); + dbri->regs = of_ioremap(&op->resource[0], 0, + dbri->regs_size, "DBRI Registers"); if (!dbri->regs) { printk(KERN_ERR "DBRI: could not allocate registers\n"); - sbus_free_consistent(sdev, sizeof(struct dbri_dma), - (void *)dbri->dma, dbri->dma_dvma); + dma_free_coherent(&op->dev, sizeof(struct dbri_dma), + (void *)dbri->dma, dbri->dma_dvma); return -EIO; } @@ -2551,9 +2556,9 @@ static int __devinit snd_dbri_create(struct snd_card *card, "DBRI audio", dbri); if (err) { printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq); - sbus_iounmap(dbri->regs, dbri->regs_size); - sbus_free_consistent(sdev, sizeof(struct dbri_dma), - (void *)dbri->dma, dbri->dma_dvma); + of_iounmap(&op->resource[0], dbri->regs, dbri->regs_size); + dma_free_coherent(&op->dev, sizeof(struct dbri_dma), + (void *)dbri->dma, dbri->dma_dvma); return err; } @@ -2577,27 +2582,23 @@ static void snd_dbri_free(struct snd_dbri *dbri) free_irq(dbri->irq, dbri); if (dbri->regs) - sbus_iounmap(dbri->regs, dbri->regs_size); + of_iounmap(&dbri->op->resource[0], dbri->regs, dbri->regs_size); if (dbri->dma) - sbus_free_consistent(dbri->sdev, sizeof(struct dbri_dma), - (void *)dbri->dma, dbri->dma_dvma); + dma_free_coherent(&dbri->op->dev, + sizeof(struct dbri_dma), + (void *)dbri->dma, dbri->dma_dvma); } -static int __devinit dbri_probe(struct of_device *of_dev, - const struct of_device_id *match) +static int __devinit dbri_probe(struct of_device *op, const struct of_device_id *match) { - struct sbus_dev *sdev = to_sbus_device(&of_dev->dev); struct snd_dbri *dbri; - int irq; struct resource *rp; struct snd_card *card; static int dev = 0; + int irq; int err; - dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", - sdev->prom_name, sdev->slot); - if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { @@ -2605,7 +2606,7 @@ static int __devinit dbri_probe(struct of_device *of_dev, return -ENOENT; } - irq = sdev->irqs[0]; + irq = op->irqs[0]; if (irq <= 0) { printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev); return -ENODEV; @@ -2618,12 +2619,12 @@ static int __devinit dbri_probe(struct of_device *of_dev, strcpy(card->driver, "DBRI"); strcpy(card->shortname, "Sun DBRI"); - rp = &sdev->resource[0]; + rp = &op->resource[0]; sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d", card->shortname, rp->flags & 0xffL, (unsigned long long)rp->start, irq); - err = snd_dbri_create(card, sdev, irq, dev); + err = snd_dbri_create(card, op, irq, dev); if (err < 0) { snd_card_free(card); return err; @@ -2640,7 +2641,7 @@ static int __devinit dbri_probe(struct of_device *of_dev, /* /proc file handling */ snd_dbri_proc(card); - dev_set_drvdata(&of_dev->dev, card); + dev_set_drvdata(&op->dev, card); err = snd_card_register(card); if (err < 0) @@ -2648,7 +2649,7 @@ static int __devinit dbri_probe(struct of_device *of_dev, printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n", dev, dbri->regs, - dbri->irq, sdev->prom_name[9], dbri->mm.version); + dbri->irq, op->node->name[9], dbri->mm.version); dev++; return 0; @@ -2659,19 +2660,19 @@ _err: return err; } -static int __devexit dbri_remove(struct of_device *dev) +static int __devexit dbri_remove(struct of_device *op) { - struct snd_card *card = dev_get_drvdata(&dev->dev); + struct snd_card *card = dev_get_drvdata(&op->dev); snd_dbri_free(card->private_data); snd_card_free(card); - dev_set_drvdata(&dev->dev, NULL); + dev_set_drvdata(&op->dev, NULL); return 0; } -static struct of_device_id dbri_match[] = { +static const struct of_device_id dbri_match[] = { { .name = "SUNW,DBRIe", }, @@ -2693,7 +2694,7 @@ static struct of_platform_driver dbri_sbus_driver = { /* Probe for the dbri chip and then attach the driver. */ static int __init dbri_init(void) { - return of_register_driver(&dbri_sbus_driver, &sbus_bus_type); + return of_register_driver(&dbri_sbus_driver, &of_bus_type); } static void __exit dbri_exit(void) |