diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-28 08:41:58 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-28 08:41:58 -0700 |
commit | 7b70888a192eff457c2ca0a4ffa04815f5e19734 (patch) | |
tree | 8c75d6908b1e83b750b50e7a26da867926e0f5cd | |
parent | cd85c8b4457a52d3545fdb9532082b2c1ebd5f21 (diff) | |
parent | 0a97af41b0e77f834acc0870155de616a373e899 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/perex/alsa
65 files changed, 5055 insertions, 1118 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 104a994b828..a18ecb92b35 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -636,11 +636,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 3stack-digout 3-jack in back, a HP out and a SPDIF out 5stack 5-jack in back, 2-jack in front 5stack-digout 5-jack in back, 2-jack in front, a SPDIF out + 6stack 6-jack in back, 2-jack in front + 6stack-digout 6-jack with a SPDIF out w810 3-jack z71v 3-jack (HP shared SPDIF) asus 3-jack uniwill 3-jack F1734 2-jack + test for testing/debugging purpose, almost all controls can be + adjusted. Appearing only when compiled with + $CONFIG_SND_DEBUG=y CMI9880 minimal 3-jack in back @@ -1054,6 +1059,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. The power-management is supported. + Module snd-pxa2xx-ac97 (on arm only) + ------------------------------------ + + Module for AC97 driver for the Intel PXA2xx chip + + For ARM architecture only. + Module snd-rme32 ---------------- @@ -1173,6 +1185,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module supports up to 8 cards. + Module snd-sun-dbri (on sparc only) + ----------------------------------- + + Module for DBRI sound chips found on Sparcs. + + Module supports up to 8 cards. + Module snd-wavefront -------------------- @@ -1371,7 +1390,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Module snd-vxpocket ------------------- - Module for Digigram VX-Pocket VX2 PCMCIA card. + Module for Digigram VX-Pocket VX2 and 440 PCMCIA cards. ibl - Capture IBL size. (default = 0, minimum size) @@ -1391,29 +1410,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Note: the driver is build only when CONFIG_ISA is set. - Module snd-vxp440 - ----------------- - - Module for Digigram VX-Pocket 440 PCMCIA card. - - ibl - Capture IBL size. (default = 0, minimum size) - - Module supports up to 8 cards. The module is compiled only when - PCMCIA is supported on kernel. - - To activate the driver via the card manager, you'll need to set - up /etc/pcmcia/vxp440.conf. See the sound/pcmcia/vx/vxp440.c. - - When the driver is compiled as a module and the hotplug firmware - is supported, the firmware data is loaded via hotplug automatically. - Install the necessary firmware files in alsa-firmware package. - When no hotplug fw loader is available, you need to load the - firmware via vxloader utility in alsa-tools package. - - About capture IBL, see the description of snd-vx222 module. - - Note: the driver is build only when CONFIG_ISA is set. - Module snd-ymfpci ----------------- diff --git a/include/sound/core.h b/include/sound/core.h index f8c4ef0aa35..38b357fc895 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -126,25 +126,26 @@ struct snd_monitor_file { struct snd_monitor_file *next; }; -struct snd_shutdown_f_ops; /* define it later */ +struct snd_shutdown_f_ops; /* define it later in init.c */ /* main structure for soundcard */ struct _snd_card { - int number; /* number of soundcard (index to snd_cards) */ + int number; /* number of soundcard (index to + snd_cards) */ char id[16]; /* id string of this card */ char driver[16]; /* driver name */ char shortname[32]; /* short name of this soundcard */ char longname[80]; /* name of this soundcard */ char mixername[80]; /* mixer name */ - char components[80]; /* card components delimited with space */ - + char components[80]; /* card components delimited with + space */ struct module *module; /* top-level module */ void *private_data; /* private data for soundcard */ - void (*private_free) (snd_card_t *card); /* callback for freeing of private data */ - + void (*private_free) (snd_card_t *card); /* callback for freeing of + private data */ struct list_head devices; /* devices */ unsigned int last_numid; /* last used numeric ID */ @@ -160,7 +161,8 @@ struct _snd_card { struct proc_dir_entry *proc_root_link; /* number link to real id */ struct snd_monitor_file *files; /* all files associated to this card */ - struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown state */ + struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown + state */ spinlock_t files_lock; /* lock the files for this card */ int shutdown; /* this card is going down */ wait_queue_head_t shutdown_sleep; @@ -196,8 +198,6 @@ static inline void snd_power_unlock(snd_card_t *card) up(&card->power_lock); } -int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file); - static inline unsigned int snd_power_get_state(snd_card_t *card) { return card->power_state; @@ -208,6 +208,10 @@ static inline void snd_power_change_state(snd_card_t *card, unsigned int state) card->power_state = state; wake_up(&card->power_sleep); } + +/* init.c */ +int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file); + int snd_card_set_pm_callback(snd_card_t *card, int (*suspend)(snd_card_t *, pm_message_t), int (*resume)(snd_card_t *), @@ -238,15 +242,14 @@ static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct fi #endif /* CONFIG_PM */ -/* device.c */ - struct _snd_minor { struct list_head list; /* list of all minors per card */ int number; /* minor number */ int device; /* device number */ const char *comment; /* for /proc/asound/devices */ struct file_operations *f_ops; /* file operations */ - char name[0]; /* device name (keep at the end of structure) */ + char name[0]; /* device name (keep at the end of + structure) */ }; typedef struct _snd_minor snd_minor_t; @@ -287,12 +290,12 @@ void snd_memory_init(void); void snd_memory_done(void); int snd_memory_info_init(void); int snd_memory_info_done(void); -void *snd_hidden_kmalloc(size_t size, int flags); -void *snd_hidden_kcalloc(size_t n, size_t size, int flags); +void *snd_hidden_kmalloc(size_t size, unsigned int __nocast flags); +void *snd_hidden_kcalloc(size_t n, size_t size, unsigned int __nocast flags); void snd_hidden_kfree(const void *obj); void *snd_hidden_vmalloc(unsigned long size); void snd_hidden_vfree(void *obj); -char *snd_hidden_kstrdup(const char *s, int flags); +char *snd_hidden_kstrdup(const char *s, unsigned int __nocast flags); #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags) #define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags) #define kfree(obj) snd_hidden_kfree(obj) @@ -411,7 +414,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) printk(fmt ,##args) #endif /** - * snd_assert - run-time assersion macro + * snd_assert - run-time assertion macro * @expr: expression * @args...: the action * @@ -427,7 +430,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) }\ } while (0) /** - * snd_runtime_check - run-time assersion macro + * snd_runtime_check - run-time assertion macro * @expr: expression * @args...: the action * diff --git a/include/sound/driver.h b/include/sound/driver.h index 948e9a1aebe..0d12456ec3a 100644 --- a/include/sound/driver.h +++ b/include/sound/driver.h @@ -51,7 +51,7 @@ #ifdef CONFIG_SND_DEBUG_MEMORY #include <linux/slab.h> #include <linux/vmalloc.h> -void *snd_wrapper_kmalloc(size_t, int); +void *snd_wrapper_kmalloc(size_t, unsigned int __nocast); #undef kmalloc void snd_wrapper_kfree(const void *); #undef kfree diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index c50b91958ff..c2ef3f02368 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -1167,6 +1167,7 @@ int snd_emu10k1_create(snd_card_t * card, unsigned short extout_mask, long max_cache_bytes, int enable_ir, + uint subsystem, emu10k1_t ** remu); int snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm); diff --git a/include/sound/version.h b/include/sound/version.h index 46acfa8c998..c085136f391 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h. Generated by configure. */ -#define CONFIG_SND_VERSION "1.0.9" -#define CONFIG_SND_DATE " (Sun May 29 07:31:02 2005 UTC)" +#define CONFIG_SND_VERSION "1.0.9b" +#define CONFIG_SND_DATE " (Thu Jul 28 12:20:13 2005 UTC)" diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig index 34c1740aa6e..2e4a5e0d16d 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig @@ -20,5 +20,17 @@ config SND_ARMAACI select SND_PCM select SND_AC97_CODEC -endmenu +config SND_PXA2XX_PCM + tristate + select SND_PCM + +config SND_PXA2XX_AC97 + tristate "AC97 driver for the Intel PXA2xx chip" + depends on ARCH_PXA && SND + select SND_PXA2XX_PCM + select SND_AC97_CODEC + help + Say Y or M if you want to support any AC97 codec attached to + the PXA2xx AC97 interface. +endmenu diff --git a/sound/arm/Makefile b/sound/arm/Makefile index f74ec28e106..103f136926d 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile @@ -3,9 +3,11 @@ # snd-sa11xx-uda1341-objs := sa11xx-uda1341.o +snd-aaci-objs := aaci.o devdma.o +snd-pxa2xx-pcm-objs := pxa2xx-pcm.o +snd-pxa2xx-ac97-objs := pxa2xx-ac97.o -# Toplevel Module Dependency obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o - obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o -snd-aaci-objs := aaci.o devdma.o +obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o +obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c new file mode 100644 index 00000000000..46052304e23 --- /dev/null +++ b/sound/arm/pxa2xx-ac97.c @@ -0,0 +1,410 @@ +/* + * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip. + * + * Author: Nicolas Pitre + * Created: Dec 02, 2004 + * Copyright: MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/wait.h> +#include <linux/delay.h> + +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/ac97_codec.h> +#include <sound/initval.h> + +#include <asm/irq.h> +#include <asm/semaphore.h> +#include <asm/hardware.h> +#include <asm/arch/pxa-regs.h> +#include <asm/arch/audio.h> + +#include "pxa2xx-pcm.h" + + +static DECLARE_MUTEX(car_mutex); +static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); +static volatile long gsr_bits; + +static unsigned short pxa2xx_ac97_read(ac97_t *ac97, unsigned short reg) +{ + unsigned short val = -1; + volatile u32 *reg_addr; + + down(&car_mutex); + if (CAR & CAR_CAIP) { + printk(KERN_CRIT"%s: CAR_CAIP already set\n", __FUNCTION__); + goto out; + } + + /* set up primary or secondary codec space */ + reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; + reg_addr += (reg >> 1); + + /* start read access across the ac97 link */ + gsr_bits = 0; + val = *reg_addr; + if (reg == AC97_GPIO_STATUS) + goto out; + wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1); + if (!gsr_bits & GSR_SDONE) { + printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", + __FUNCTION__, reg, gsr_bits); + val = -1; + goto out; + } + + /* valid data now */ + gsr_bits = 0; + val = *reg_addr; + /* but we've just started another cycle... */ + wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1); + +out: up(&car_mutex); + return val; +} + +static void pxa2xx_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val) +{ + volatile u32 *reg_addr; + + down(&car_mutex); + + if (CAR & CAR_CAIP) { + printk(KERN_CRIT "%s: CAR_CAIP already set\n", __FUNCTION__); + goto out; + } + + /* set up primary or secondary codec space */ + reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; + reg_addr += (reg >> 1); + gsr_bits = 0; + *reg_addr = val; + wait_event_timeout(gsr_wq, gsr_bits & GSR_CDONE, 1); + if (!gsr_bits & GSR_SDONE) + printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n", + __FUNCTION__, reg, gsr_bits); + +out: up(&car_mutex); +} + +static void pxa2xx_ac97_reset(ac97_t *ac97) +{ + /* First, try cold reset */ + GCR &= GCR_COLD_RST; /* clear everything but nCRST */ + GCR &= ~GCR_COLD_RST; /* then assert nCRST */ + + gsr_bits = 0; +#ifdef CONFIG_PXA27x + /* PXA27x Developers Manual section 13.5.2.2.1 */ + pxa_set_cken(1 << 31, 1); + udelay(5); + pxa_set_cken(1 << 31, 0); + GCR = GCR_COLD_RST; + udelay(50); +#else + GCR = GCR_COLD_RST; + GCR |= GCR_CDONE_IE|GCR_SDONE_IE; + wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); +#endif + + if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { + printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", + __FUNCTION__, gsr_bits); + + /* let's try warm reset */ + gsr_bits = 0; +#ifdef CONFIG_PXA27x + /* warm reset broken on Bulverde, + so manually keep AC97 reset high */ + pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); + udelay(10); + GCR |= GCR_WARM_RST; + pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + udelay(50); +#else + GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN;; + wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); +#endif + + if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) + printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", + __FUNCTION__, gsr_bits); + } + + GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); + GCR |= GCR_SDONE_IE|GCR_CDONE_IE; +} + +static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + long status; + + status = GSR; + if (status) { + GSR = status; + gsr_bits |= status; + wake_up(&gsr_wq); + +#ifdef CONFIG_PXA27x + /* Although we don't use those we still need to clear them + since they tend to spuriously trigger when MMC is used + (hardware bug? go figure)... */ + MISR = MISR_EOC; + PISR = PISR_EOC; + MCSR = MCSR_EOC; +#endif + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static ac97_bus_ops_t pxa2xx_ac97_ops = { + .read = pxa2xx_ac97_read, + .write = pxa2xx_ac97_write, + .reset = pxa2xx_ac97_reset, +}; + +static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_out = { + .name = "AC97 PCM out", + .dev_addr = __PREG(PCDR), + .drcmr = &DRCMRTXPCDR, + .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | + DCMD_BURST32 | DCMD_WIDTH4, +}; + +static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_in = { + .name = "AC97 PCM in", + .dev_addr = __PREG(PCDR), + .drcmr = &DRCMRRXPCDR, + .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | + DCMD_BURST32 | DCMD_WIDTH4, +}; + +static snd_pcm_t *pxa2xx_ac97_pcm; +static ac97_t *pxa2xx_ac97_ac97; + +static int pxa2xx_ac97_pcm_startup(snd_pcm_substream_t *substream) +{ + snd_pcm_runtime_t *runtime = substream->runtime; + pxa2xx_audio_ops_t *platform_ops; + int r; + + runtime->hw.channels_min = 2; + runtime->hw.channels_max = 2; + + r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + AC97_RATES_FRONT_DAC : AC97_RATES_ADC; + runtime->hw.rates = pxa2xx_ac97_ac97->rates[r]; + snd_pcm_limit_hw_rates(runtime); + + platform_ops = substream->pcm->card->dev->platform_data; + if (platform_ops && platform_ops->startup) + return platform_ops->startup(substream, platform_ops->priv); + else + return 0; +} + +static void pxa2xx_ac97_pcm_shutdown(snd_pcm_substream_t *substream) +{ + pxa2xx_audio_ops_t *platform_ops; + + platform_ops = substream->pcm->card->dev->platform_data; + if (platform_ops && platform_ops->shutdown) + platform_ops->shutdown(substream, platform_ops->priv); +} + +static int pxa2xx_ac97_pcm_prepare(snd_pcm_substream_t *substream) +{ + snd_pcm_runtime_t *runtime = substream->runtime; + int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; + return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate); +} + +static pxa2xx_pcm_client_t pxa2xx_ac97_pcm_client = { + .playback_params = &pxa2xx_ac97_pcm_out, + .capture_params = &pxa2xx_ac97_pcm_in, + .startup = pxa2xx_ac97_pcm_startup, + .shutdown = pxa2xx_ac97_pcm_shutdown, + .prepare = pxa2xx_ac97_pcm_prepare, +}; + +#ifdef CONFIG_PM + +static int pxa2xx_ac97_do_suspend(snd_card_t *card, unsigned int state) +{ + if (card->power_state != SNDRV_CTL_POWER_D3cold) { + pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; + snd_pcm_suspend_all(pxa2xx_ac97_pcm); + snd_ac97_suspend(pxa2xx_ac97_ac97); + snd_power_change_state(card, SNDRV_CTL_POWER_D3cold); + if (platform_ops && platform_ops->suspend) + platform_ops->suspend(platform_ops->priv); + GCR |= GCR_ACLINK_OFF; + pxa_set_cken(CKEN2_AC97, 0); + } + + return 0; +} + +static int pxa2xx_ac97_do_resume(snd_card_t *card, unsigned int state) +{ + if (card->power_state != SNDRV_CTL_POWER_D0) { + pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; + pxa_set_cken(CKEN2_AC97, 1); + if (platform_ops && platform_ops->resume) + platform_ops->resume(platform_ops->priv); + snd_ac97_resume(pxa2xx_ac97_ac97); + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + } + + return 0; +} + +static int pxa2xx_ac97_suspend(struct device *_dev, u32 state, u32 level) +{ + snd_card_t *card = dev_get_drvdata(_dev); + int ret = 0; + + if (card && level == SUSPEND_DISABLE) + ret = pxa2xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold); + + return ret; +} + +static int pxa2xx_ac97_resume(struct device *_dev, u32 level) +{ + snd_card_t *card = dev_get_drvdata(_dev); + int ret = 0; + + if (card && level == RESUME_ENABLE) + ret = pxa2xx_ac97_do_re |