diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-10-26 23:51:48 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-10-26 23:51:48 +0200 |
commit | 9430148d800dd929ad73da4c6afb67f793f8af43 (patch) | |
tree | 437d0aec41428cbb310a202100ba581c63fbe89e /sound/soc | |
parent | d22665702226e9c40bc331098559e3d55e7cd43d (diff) | |
parent | 88e24c3a4b30a6bd361f2b5ce602667a8161b2e8 (diff) |
Merge branch 'topic/remove-irqf_disable' into for-linus
Diffstat (limited to 'sound/soc')
101 files changed, 6032 insertions, 1152 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 8224db5f043..1381db853ef 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -7,6 +7,8 @@ menuconfig SND_SOC select SND_PCM select AC97_BUS if SND_SOC_AC97_BUS select SND_JACK if INPUT=y || INPUT=SND + select REGMAP_I2C if I2C + select REGMAP_SPI if SPI_MASTER ---help--- If you want ASoC support, you should say Y here and also to the @@ -51,6 +53,7 @@ source "sound/soc/nuc900/Kconfig" source "sound/soc/omap/Kconfig" source "sound/soc/kirkwood/Kconfig" source "sound/soc/mid-x86/Kconfig" +source "sound/soc/mxs/Kconfig" source "sound/soc/pxa/Kconfig" source "sound/soc/samsung/Kconfig" source "sound/soc/s6000/Kconfig" diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 4f913876f33..9ea8ac827ad 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_SND_SOC) += fsl/ obj-$(CONFIG_SND_SOC) += imx/ obj-$(CONFIG_SND_SOC) += jz4740/ obj-$(CONFIG_SND_SOC) += mid-x86/ +obj-$(CONFIG_SND_SOC) += mxs/ obj-$(CONFIG_SND_SOC) += nuc900/ obj-$(CONFIG_SND_SOC) += omap/ obj-$(CONFIG_SND_SOC) += kirkwood/ diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c index 1aac2f4dbcf..2909bfaed26 100644 --- a/sound/soc/atmel/playpaq_wm8510.c +++ b/sound/soc/atmel/playpaq_wm8510.c @@ -383,14 +383,17 @@ static int __init playpaq_asoc_init(void) _gclk0 = clk_get(NULL, "gclk0"); if (IS_ERR(_gclk0)) { _gclk0 = NULL; + ret = PTR_ERR(_gclk0); goto err_gclk0; } _pll0 = clk_get(NULL, "pll0"); if (IS_ERR(_pll0)) { _pll0 = NULL; + ret = PTR_ERR(_pll0); goto err_pll0; } - if (clk_set_parent(_gclk0, _pll0)) { + ret = clk_set_parent(_gclk0, _pll0); + if (ret) { pr_warning("snd-soc-playpaq: " "Failed to set PLL0 as parent for DAC clock\n"); goto err_set_clk; diff --git a/sound/soc/au1x/Kconfig b/sound/soc/au1x/Kconfig index 4b67140fdec..6d592546e8f 100644 --- a/sound/soc/au1x/Kconfig +++ b/sound/soc/au1x/Kconfig @@ -18,10 +18,38 @@ config SND_SOC_AU1XPSC_AC97 select SND_AC97_CODEC select SND_SOC_AC97_BUS +## +## Au1000/1500/1100 DMA + AC97C/I2SC +## +config SND_SOC_AU1XAUDIO + tristate "SoC Audio for Au1000/Au1500/Au1100" + depends on MIPS_ALCHEMY + help + This is a driver set for the AC97 unit and the + old DMA controller as found on the Au1000/Au1500/Au1100 chips. + +config SND_SOC_AU1XAC97C + tristate + select AC97_BUS + select SND_AC97_CODEC + select SND_SOC_AC97_BUS + +config SND_SOC_AU1XI2SC + tristate + ## ## Boards ## +config SND_SOC_DB1000 + tristate "DB1000 Audio support" + depends on SND_SOC_AU1XAUDIO + select SND_SOC_AU1XAC97C + select SND_SOC_AC97_CODEC + help + Select this option to enable AC97 audio on the early DB1x00 series + of boards (DB1000/DB1500/DB1100). + config SND_SOC_DB1200 tristate "DB1200 AC97+I2S audio support" depends on SND_SOC_AU1XPSC diff --git a/sound/soc/au1x/Makefile b/sound/soc/au1x/Makefile index 16873076e8c..920710514ea 100644 --- a/sound/soc/au1x/Makefile +++ b/sound/soc/au1x/Makefile @@ -3,11 +3,21 @@ snd-soc-au1xpsc-dbdma-objs := dbdma2.o snd-soc-au1xpsc-i2s-objs := psc-i2s.o snd-soc-au1xpsc-ac97-objs := psc-ac97.o +# Au1000/1500/1100 Audio units +snd-soc-au1x-dma-objs := dma.o +snd-soc-au1x-ac97c-objs := ac97c.o +snd-soc-au1x-i2sc-objs := i2sc.o + obj-$(CONFIG_SND_SOC_AU1XPSC) += snd-soc-au1xpsc-dbdma.o obj-$(CONFIG_SND_SOC_AU1XPSC_I2S) += snd-soc-au1xpsc-i2s.o obj-$(CONFIG_SND_SOC_AU1XPSC_AC97) += snd-soc-au1xpsc-ac97.o +obj-$(CONFIG_SND_SOC_AU1XAUDIO) += snd-soc-au1x-dma.o +obj-$(CONFIG_SND_SOC_AU1XAC97C) += snd-soc-au1x-ac97c.o +obj-$(CONFIG_SND_SOC_AU1XI2SC) += snd-soc-au1x-i2sc.o # Boards +snd-soc-db1000-objs := db1000.o snd-soc-db1200-objs := db1200.o +obj-$(CONFIG_SND_SOC_DB1000) += snd-soc-db1000.o obj-$(CONFIG_SND_SOC_DB1200) += snd-soc-db1200.o diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c new file mode 100644 index 00000000000..13802ff7cf0 --- /dev/null +++ b/sound/soc/au1x/ac97c.c @@ -0,0 +1,363 @@ +/* + * Au1000/Au1500/Au1100 AC97C controller driver for ASoC + * + * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com> + * + * based on the old ALSA driver originally written by + * Charles Eidsness <charles@cooper-street.com> + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/suspend.h> +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/initval.h> +#include <sound/soc.h> +#include <asm/mach-au1x00/au1000.h> + +#include "psc.h" + +/* register offsets and bits */ +#define AC97_CONFIG 0x00 +#define AC97_STATUS 0x04 +#define AC97_DATA 0x08 +#define AC97_CMDRESP 0x0c +#define AC97_ENABLE 0x10 + +#define CFG_RC(x) (((x) & 0x3ff) << 13) /* valid rx slots mask */ +#define CFG_XS(x) (((x) & 0x3ff) << 3) /* valid tx slots mask */ +#define CFG_SG (1 << 2) /* sync gate */ +#define CFG_SN (1 << 1) /* sync control */ +#define CFG_RS (1 << 0) /* acrst# control */ +#define STAT_XU (1 << 11) /* tx underflow */ +#define STAT_XO (1 << 10) /* tx overflow */ +#define STAT_RU (1 << 9) /* rx underflow */ +#define STAT_RO (1 << 8) /* rx overflow */ +#define STAT_RD (1 << 7) /* codec ready */ +#define STAT_CP (1 << 6) /* command pending */ +#define STAT_TE (1 << 4) /* tx fifo empty */ +#define STAT_TF (1 << 3) /* tx fifo full */ +#define STAT_RE (1 << 1) /* rx fifo empty */ +#define STAT_RF (1 << 0) /* rx fifo full */ +#define CMD_SET_DATA(x) (((x) & 0xffff) << 16) +#define CMD_GET_DATA(x) ((x) & 0xffff) +#define CMD_READ (1 << 7) +#define CMD_WRITE (0 << 7) +#define CMD_IDX(x) ((x) & 0x7f) +#define EN_D (1 << 1) /* DISable bit */ +#define EN_CE (1 << 0) /* clock enable bit */ + +/* how often to retry failed codec register reads/writes */ +#define AC97_RW_RETRIES 5 + +#define AC97_RATES \ + SNDRV_PCM_RATE_CONTINUOUS + +#define AC97_FMTS \ + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE) + +/* instance data. There can be only one, MacLeod!!!!, fortunately there IS only + * once AC97C on early Alchemy chips. The newer ones aren't so lucky. + */ +static struct au1xpsc_audio_data *ac97c_workdata; +#define ac97_to_ctx(x) ac97c_workdata + +static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg) +{ + return __raw_readl(ctx->mmio + reg); +} + +static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v) +{ + __raw_writel(v, ctx->mmio + reg); + wmb(); +} + +static unsigned short au1xac97c_ac97_read(struct snd_ac97 *ac97, + unsigned short r) +{ + struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); + unsigned int tmo, retry; + unsigned long data; + + data = ~0; + retry = AC97_RW_RETRIES; + do { + mutex_lock(&ctx->lock); + + tmo = 5; + while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--) + udelay(21); /* wait an ac97 frame time */ + if (!tmo) { + pr_debug("ac97rd timeout #1\n"); + goto next; + } + + WR(ctx, AC97_CMDRESP, CMD_IDX(r) | CMD_READ); + + /* stupid errata: data is only valid for 21us, so + * poll, Forrest, poll... + */ + tmo = 0x10000; + while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--) + asm volatile ("nop"); + data = RD(ctx, AC97_CMDRESP); + + if (!tmo) + pr_debug("ac97rd timeout #2\n"); + +next: + mutex_unlock(&ctx->lock); + } while (--retry && !tmo); + + pr_debug("AC97RD %04x %04lx %d\n", r, data, retry); + + return retry ? data & 0xffff : 0xffff; +} + +static void au1xac97c_ac97_write(struct snd_ac97 *ac97, unsigned short r, + unsigned short v) +{ + struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); + unsigned int tmo, retry; + + retry = AC97_RW_RETRIES; + do { + mutex_lock(&ctx->lock); + + for (tmo = 5; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--) + udelay(21); + if (!tmo) { + pr_debug("ac97wr timeout #1\n"); + goto next; + } + + WR(ctx, AC97_CMDRESP, CMD_WRITE | CMD_IDX(r) | CMD_SET_DATA(v)); + + for (tmo = 10; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--) + udelay(21); + if (!tmo) + pr_debug("ac97wr timeout #2\n"); +next: + mutex_unlock(&ctx->lock); + } while (--retry && !tmo); + + pr_debug("AC97WR %04x %04x %d\n", r, v, retry); +} + +static void au1xac97c_ac97_warm_reset(struct snd_ac97 *ac97) +{ + struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); + + WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG | CFG_SN); + msleep(20); + WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG); + WR(ctx, AC97_CONFIG, ctx->cfg); +} + +static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97) +{ + struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); + int i; |