diff --git a/[refs] b/[refs] index 9f3813c01cb2..0fb73ac28ffe 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5314adc3612d893c7cc526b3312d124805e45bc3 +refs/heads/master: 6335d05548eece40092000aa91b64a50310d69d5 diff --git a/trunk/arch/arm/mach-pxa/include/mach/regs-ssp.h b/trunk/arch/arm/mach-pxa/include/mach/regs-ssp.h index f43905a27737..3c04cde2cf1f 100644 --- a/trunk/arch/arm/mach-pxa/include/mach/regs-ssp.h +++ b/trunk/arch/arm/mach-pxa/include/mach/regs-ssp.h @@ -47,7 +47,7 @@ #define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun interrupt mask */ #define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */ #define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24) /* Time slots per frame [1..8] */ -#define SSCR0_ACS (1 << 30) /* Audio clock select */ +#define SSCR0_ADC (1 << 30) /* Audio clock select */ #define SSCR0_MOD (1 << 31) /* Mode (normal or network) */ #endif @@ -106,11 +106,6 @@ #define SSSR_TINT (1 << 19) /* Receiver Time-out Interrupt */ #define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */ -#if defined(CONFIG_PXA3xx) -#define SSPSP_EDMYSTOP(x) ((x) << 28) /* Extended Dummy Stop */ -#define SSPSP_EDMYSTRT(x) ((x) << 26) /* Extended Dummy Start */ -#endif - #define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */ #define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */ #define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */ diff --git a/trunk/arch/arm/mach-s3c2410/dma.c b/trunk/arch/arm/mach-s3c2410/dma.c index 440c014e24b3..552b4c778fdc 100644 --- a/trunk/arch/arm/mach-s3c2410/dma.c +++ b/trunk/arch/arm/mach-s3c2410/dma.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = { diff --git a/trunk/arch/arm/plat-s3c/include/plat/audio.h b/trunk/arch/arm/mach-s3c2410/include/mach/audio.h similarity index 100% rename from trunk/arch/arm/plat-s3c/include/plat/audio.h rename to trunk/arch/arm/mach-s3c2410/include/mach/audio.h diff --git a/trunk/arch/arm/mach-s3c2410/include/mach/io.h b/trunk/arch/arm/mach-s3c2410/include/mach/io.h index c477771c0924..9813dbf2ae4f 100644 --- a/trunk/arch/arm/mach-s3c2410/include/mach/io.h +++ b/trunk/arch/arm/mach-s3c2410/include/mach/io.h @@ -9,7 +9,7 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#include +#include #define IO_SPACE_LIMIT 0xffffffff diff --git a/trunk/arch/arm/mach-s3c2412/dma.c b/trunk/arch/arm/mach-s3c2412/dma.c index 9e3478506c6f..919856c9433f 100644 --- a/trunk/arch/arm/mach-s3c2412/dma.c +++ b/trunk/arch/arm/mach-s3c2412/dma.c @@ -29,8 +29,8 @@ #include #include #include -#include -#include +#include +#include #include #define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID } diff --git a/trunk/arch/arm/mach-s3c2440/dma.c b/trunk/arch/arm/mach-s3c2440/dma.c index 69b6cf34df47..5b5ee0b8f4e0 100644 --- a/trunk/arch/arm/mach-s3c2440/dma.c +++ b/trunk/arch/arm/mach-s3c2440/dma.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = { diff --git a/trunk/arch/arm/mach-s3c2443/dma.c b/trunk/arch/arm/mach-s3c2443/dma.c index 8430e5829186..2a58a4d5aa5a 100644 --- a/trunk/arch/arm/mach-s3c2443/dma.c +++ b/trunk/arch/arm/mach-s3c2443/dma.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #define MAP(x) { \ diff --git a/trunk/arch/arm/plat-s3c24xx/clock-dclk.c b/trunk/arch/arm/plat-s3c24xx/clock-dclk.c index 35219dcf9f08..5b75a797b5ab 100644 --- a/trunk/arch/arm/plat-s3c24xx/clock-dclk.c +++ b/trunk/arch/arm/plat-s3c24xx/clock-dclk.c @@ -18,7 +18,6 @@ #include #include -#include #include #include diff --git a/trunk/arch/arm/plat-s3c24xx/include/plat/regs-iis.h b/trunk/include/asm-arm/plat-s3c24xx/regs-iis.h similarity index 100% rename from trunk/arch/arm/plat-s3c24xx/include/plat/regs-iis.h rename to trunk/include/asm-arm/plat-s3c24xx/regs-iis.h diff --git a/trunk/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h b/trunk/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h similarity index 93% rename from trunk/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h rename to trunk/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h index 0fad7571030e..25d4058bcfed 100644 --- a/trunk/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h +++ b/trunk/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h @@ -33,9 +33,6 @@ #define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1) #define S3C2412_IISCON_IIS_ACTIVE (1 << 0) -#define S3C64XX_IISMOD_IMS_PCLK (0 << 10) -#define S3C64XX_IISMOD_IMS_SYSMUX (1 << 10) - #define S3C2412_IISMOD_MASTER_INTERNAL (0 << 10) #define S3C2412_IISMOD_MASTER_EXTERNAL (1 << 10) #define S3C2412_IISMOD_SLAVE (2 << 10) @@ -47,8 +44,8 @@ #define S3C2412_IISMOD_LR_LLOW (0 << 7) #define S3C2412_IISMOD_LR_RLOW (1 << 7) #define S3C2412_IISMOD_SDF_IIS (0 << 5) -#define S3C2412_IISMOD_SDF_MSB (1 << 5) -#define S3C2412_IISMOD_SDF_LSB (2 << 5) +#define S3C2412_IISMOD_SDF_MSB (0 << 5) +#define S3C2412_IISMOD_SDF_LSB (0 << 5) #define S3C2412_IISMOD_SDF_MASK (3 << 5) #define S3C2412_IISMOD_RCLK_256FS (0 << 3) #define S3C2412_IISMOD_RCLK_512FS (1 << 3) diff --git a/trunk/include/linux/mfd/wm8400-audio.h b/trunk/include/linux/mfd/wm8400-audio.h index e06ed3eb1d0a..b6640e018046 100644 --- a/trunk/include/linux/mfd/wm8400-audio.h +++ b/trunk/include/linux/mfd/wm8400-audio.h @@ -1181,7 +1181,6 @@ #define WM8400_FLL_OUTDIV_SHIFT 0 /* FLL_OUTDIV - [2:0] */ #define WM8400_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [2:0] */ -struct wm8400; void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400); #endif diff --git a/trunk/include/sound/soc-dai.h b/trunk/include/sound/soc-dai.h index 24247f763608..13676472ddfc 100644 --- a/trunk/include/sound/soc-dai.h +++ b/trunk/include/sound/soc-dai.h @@ -203,7 +203,7 @@ struct snd_soc_dai { int (*resume)(struct snd_soc_dai *dai); /* ops */ - struct snd_soc_dai_ops ops; + struct snd_soc_dai_ops *ops; /* DAI capabilities */ struct snd_soc_pcm_stream capture; diff --git a/trunk/include/sound/soc.h b/trunk/include/sound/soc.h index a40bc6f316fc..0e7735264169 100644 --- a/trunk/include/sound/soc.h +++ b/trunk/include/sound/soc.h @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include #include #include @@ -170,9 +168,6 @@ struct soc_enum; struct snd_soc_ac97_ops; struct snd_soc_jack; struct snd_soc_jack_pin; -#ifdef CONFIG_GPIOLIB -struct snd_soc_jack_gpio; -#endif typedef int (*hw_write_t)(void *,const char* ,int); typedef int (*hw_read_t)(void *,char* ,int); @@ -199,12 +194,6 @@ int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, struct snd_soc_jack_pin *pins); -#ifdef CONFIG_GPIOLIB -int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios); -void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios); -#endif /* codec IO */ #define snd_soc_read(codec, reg) codec->read(codec, reg) @@ -275,27 +264,6 @@ struct snd_soc_jack_pin { bool invert; }; -/** - * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection - * - * @gpio: gpio number - * @name: gpio name - * @report: value to report when jack detected - * @invert: report presence in low state - * @debouce_time: debouce time in ms - */ -#ifdef CONFIG_GPIOLIB -struct snd_soc_jack_gpio { - unsigned int gpio; - const char *name; - int report; - int invert; - int debounce_time; - struct snd_soc_jack *jack; - struct work_struct work; -}; -#endif - struct snd_soc_jack { struct snd_jack *jack; struct snd_soc_card *card; diff --git a/trunk/sound/soc/atmel/atmel_ssc_dai.c b/trunk/sound/soc/atmel/atmel_ssc_dai.c index ff0054b76502..e588e63f18d2 100644 --- a/trunk/sound/soc/atmel/atmel_ssc_dai.c +++ b/trunk/sound/soc/atmel/atmel_ssc_dai.c @@ -697,6 +697,15 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai) #define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) +static struct snd_soc_dai_ops atmel_ssc_dai_ops = { + .startup = atmel_ssc_startup, + .shutdown = atmel_ssc_shutdown, + .prepare = atmel_ssc_prepare, + .hw_params = atmel_ssc_hw_params, + .set_fmt = atmel_ssc_set_dai_fmt, + .set_clkdiv = atmel_ssc_set_dai_clkdiv, +}; + struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { { .name = "atmel-ssc0", .id = 0, @@ -712,13 +721,7 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { .channels_max = 2, .rates = ATMEL_SSC_RATES, .formats = ATMEL_SSC_FORMATS,}, - .ops = { - .startup = atmel_ssc_startup, - .shutdown = atmel_ssc_shutdown, - .prepare = atmel_ssc_prepare, - .hw_params = atmel_ssc_hw_params, - .set_fmt = atmel_ssc_set_dai_fmt, - .set_clkdiv = atmel_ssc_set_dai_clkdiv,}, + .ops = &atmel_ssc_dai_ops, .private_data = &ssc_info[0], }, #if NUM_SSC_DEVICES == 3 @@ -736,13 +739,7 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { .channels_max = 2, .rates = ATMEL_SSC_RATES, .formats = ATMEL_SSC_FORMATS,}, - .ops = { - .startup = atmel_ssc_startup, - .shutdown = atmel_ssc_shutdown, - .prepare = atmel_ssc_prepare, - .hw_params = atmel_ssc_hw_params, - .set_fmt = atmel_ssc_set_dai_fmt, - .set_clkdiv = atmel_ssc_set_dai_clkdiv,}, + .ops = &atmel_ssc_dai_ops, .private_data = &ssc_info[1], }, { .name = "atmel-ssc2", @@ -759,13 +756,7 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { .channels_max = 2, .rates = ATMEL_SSC_RATES, .formats = ATMEL_SSC_FORMATS,}, - .ops = { - .startup = atmel_ssc_startup, - .shutdown = atmel_ssc_shutdown, - .prepare = atmel_ssc_prepare, - .hw_params = atmel_ssc_hw_params, - .set_fmt = atmel_ssc_set_dai_fmt, - .set_clkdiv = atmel_ssc_set_dai_clkdiv,}, + .ops = &atmel_ssc_dai_ops, .private_data = &ssc_info[2], }, #endif diff --git a/trunk/sound/soc/atmel/playpaq_wm8510.c b/trunk/sound/soc/atmel/playpaq_wm8510.c index 70657534e6b1..43dd8cee83c6 100644 --- a/trunk/sound/soc/atmel/playpaq_wm8510.c +++ b/trunk/sound/soc/atmel/playpaq_wm8510.c @@ -164,38 +164,38 @@ static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream, */ switch (params_rate(params)) { case 48000: - pll_out = 24576000; - mclk_div = WM8510_MCLKDIV_2; + pll_out = 12288000; + mclk_div = WM8510_MCLKDIV_1; bclk = WM8510_BCLKDIV_8; break; case 44100: - pll_out = 22579200; - mclk_div = WM8510_MCLKDIV_2; + pll_out = 11289600; + mclk_div = WM8510_MCLKDIV_1; bclk = WM8510_BCLKDIV_8; break; case 22050: - pll_out = 22579200; - mclk_div = WM8510_MCLKDIV_4; + pll_out = 11289600; + mclk_div = WM8510_MCLKDIV_2; bclk = WM8510_BCLKDIV_8; break; case 16000: - pll_out = 24576000; - mclk_div = WM8510_MCLKDIV_6; + pll_out = 12288000; + mclk_div = WM8510_MCLKDIV_3; bclk = WM8510_BCLKDIV_8; break; case 11025: - pll_out = 22579200; - mclk_div = WM8510_MCLKDIV_8; + pll_out = 11289600; + mclk_div = WM8510_MCLKDIV_4; bclk = WM8510_BCLKDIV_8; break; case 8000: - pll_out = 24576000; - mclk_div = WM8510_MCLKDIV_12; + pll_out = 12288000; + mclk_div = WM8510_MCLKDIV_6; bclk = WM8510_BCLKDIV_8; break; diff --git a/trunk/sound/soc/au1x/psc-ac97.c b/trunk/sound/soc/au1x/psc-ac97.c index f0e30aec7f23..479d7bdf1865 100644 --- a/trunk/sound/soc/au1x/psc-ac97.c +++ b/trunk/sound/soc/au1x/psc-ac97.c @@ -342,6 +342,11 @@ static int au1xpsc_ac97_resume(struct snd_soc_dai *dai) return 0; } +static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { + .trigger = au1xpsc_ac97_trigger, + .hw_params = au1xpsc_ac97_hw_params, +}; + struct snd_soc_dai au1xpsc_ac97_dai = { .name = "au1xpsc_ac97", .ac97_control = 1, @@ -361,10 +366,7 @@ struct snd_soc_dai au1xpsc_ac97_dai = { .channels_min = 2, .channels_max = 2, }, - .ops = { - .trigger = au1xpsc_ac97_trigger, - .hw_params = au1xpsc_ac97_hw_params, - }, + .ops = &au1xpsc_ac97_dai_ops, }; EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai); diff --git a/trunk/sound/soc/au1x/psc-i2s.c b/trunk/sound/soc/au1x/psc-i2s.c index f916de4400ed..bb589327ee32 100644 --- a/trunk/sound/soc/au1x/psc-i2s.c +++ b/trunk/sound/soc/au1x/psc-i2s.c @@ -367,6 +367,12 @@ static int au1xpsc_i2s_resume(struct snd_soc_dai *cpu_dai) return 0; } +static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { + .trigger = au1xpsc_i2s_trigger, + .hw_params = au1xpsc_i2s_hw_params, + .set_fmt = au1xpsc_i2s_set_fmt, +}; + struct snd_soc_dai au1xpsc_i2s_dai = { .name = "au1xpsc_i2s", .probe = au1xpsc_i2s_probe, @@ -385,11 +391,7 @@ struct snd_soc_dai au1xpsc_i2s_dai = { .channels_min = 2, .channels_max = 8, /* 2 without external help */ }, - .ops = { - .trigger = au1xpsc_i2s_trigger, - .hw_params = au1xpsc_i2s_hw_params, - .set_fmt = au1xpsc_i2s_set_fmt, - }, + .ops = &au1xpsc_i2s_dai_ops, }; EXPORT_SYMBOL(au1xpsc_i2s_dai); diff --git a/trunk/sound/soc/blackfin/bf5xx-ac97.c b/trunk/sound/soc/blackfin/bf5xx-ac97.c index 8a935f2d1767..5885702c78ff 100644 --- a/trunk/sound/soc/blackfin/bf5xx-ac97.c +++ b/trunk/sound/soc/blackfin/bf5xx-ac97.c @@ -357,8 +357,8 @@ static int bf5xx_ac97_probe(struct platform_device *pdev, sport_err: #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); -gpio_err: #endif +gpio_err: peripheral_free_list(sport_req[sport_num]); peripheral_err: free_page((unsigned long)cmd_count); diff --git a/trunk/sound/soc/blackfin/bf5xx-i2s.c b/trunk/sound/soc/blackfin/bf5xx-i2s.c index d1d95d2393fe..964824419678 100644 --- a/trunk/sound/soc/blackfin/bf5xx-i2s.c +++ b/trunk/sound/soc/blackfin/bf5xx-i2s.c @@ -287,6 +287,13 @@ static int bf5xx_i2s_resume(struct platform_device *pdev, #define BF5XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\ SNDRV_PCM_FMTBIT_S32_LE) +static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { + .startup = bf5xx_i2s_startup, + .shutdown = bf5xx_i2s_shutdown, + .hw_params = bf5xx_i2s_hw_params, + .set_fmt = bf5xx_i2s_set_dai_fmt, +}; + struct snd_soc_dai bf5xx_i2s_dai = { .name = "bf5xx-i2s", .id = 0, @@ -304,12 +311,7 @@ struct snd_soc_dai bf5xx_i2s_dai = { .channels_max = 2, .rates = BF5XX_I2S_RATES, .formats = BF5XX_I2S_FORMATS,}, - .ops = { - .startup = bf5xx_i2s_startup, - .shutdown = bf5xx_i2s_shutdown, - .hw_params = bf5xx_i2s_hw_params, - .set_fmt = bf5xx_i2s_set_dai_fmt, - }, + .ops = &bf5xx_i2s_dai_ops, }; EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); diff --git a/trunk/sound/soc/codecs/Kconfig b/trunk/sound/soc/codecs/Kconfig index b6c7f7a01cb0..628a591c728f 100644 --- a/trunk/sound/soc/codecs/Kconfig +++ b/trunk/sound/soc/codecs/Kconfig @@ -14,7 +14,6 @@ config SND_SOC_ALL_CODECS select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 if I2C - select SND_SOC_AK4104 if SPI_MASTER select SND_SOC_AK4535 if I2C select SND_SOC_CS4270 if I2C select SND_SOC_PCM3008 @@ -26,7 +25,6 @@ config SND_SOC_ALL_CODECS select SND_SOC_UDA134X select SND_SOC_UDA1380 if I2C select SND_SOC_WM8350 if MFD_WM8350 - select SND_SOC_WM8400 if MFD_WM8400 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8580 if I2C select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI @@ -62,9 +60,6 @@ config SND_SOC_AD1980 config SND_SOC_AD73311 tristate -config SND_SOC_AK4104 - tristate - config SND_SOC_AK4535 tristate @@ -111,9 +106,6 @@ config SND_SOC_UDA1380 config SND_SOC_WM8350 tristate -config SND_SOC_WM8400 - tristate - config SND_SOC_WM8510 tristate diff --git a/trunk/sound/soc/codecs/Makefile b/trunk/sound/soc/codecs/Makefile index 030d2454725f..3664cdc300b2 100644 --- a/trunk/sound/soc/codecs/Makefile +++ b/trunk/sound/soc/codecs/Makefile @@ -1,7 +1,6 @@ snd-soc-ac97-objs := ac97.o snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o -snd-soc-ak4104-objs := ak4104.o snd-soc-ak4535-objs := ak4535.o snd-soc-cs4270-objs := cs4270.o snd-soc-l3-objs := l3.o @@ -14,7 +13,6 @@ snd-soc-twl4030-objs := twl4030.o snd-soc-uda134x-objs := uda134x.o snd-soc-uda1380-objs := uda1380.o snd-soc-wm8350-objs := wm8350.o -snd-soc-wm8400-objs := wm8400.o snd-soc-wm8510-objs := wm8510.o snd-soc-wm8580-objs := wm8580.o snd-soc-wm8728-objs := wm8728.o @@ -32,7 +30,6 @@ snd-soc-wm9713-objs := wm9713.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o -obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o @@ -45,7 +42,6 @@ obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o -obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o diff --git a/trunk/sound/soc/codecs/ac97.c b/trunk/sound/soc/codecs/ac97.c index 11f84b6e5cb8..b0d4af145b87 100644 --- a/trunk/sound/soc/codecs/ac97.c +++ b/trunk/sound/soc/codecs/ac97.c @@ -41,6 +41,10 @@ static int ac97_prepare(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ SNDRV_PCM_RATE_48000) +static struct snd_soc_dai_ops ac97_dai_ops = { + .prepare = ac97_prepare, +}; + struct snd_soc_dai ac97_dai = { .name = "AC97 HiFi", .ac97_control = 1, @@ -56,8 +60,7 @@ struct snd_soc_dai ac97_dai = { .channels_max = 2, .rates = STD_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .prepare = ac97_prepare,}, + .ops = &ac97_dai_ops, }; EXPORT_SYMBOL_GPL(ac97_dai); diff --git a/trunk/sound/soc/codecs/ad73311.h b/trunk/sound/soc/codecs/ad73311.h index 569573d2d4d7..507ce0c30edf 100644 --- a/trunk/sound/soc/codecs/ad73311.h +++ b/trunk/sound/soc/codecs/ad73311.h @@ -70,7 +70,7 @@ #define REGD_IGS(x) (x & 0x7) #define REGD_RMOD (1 << 3) #define REGD_OGS(x) ((x & 0x7) << 4) -#define REGD_MUTE (1 << 7) +#define REGD_MUTE (x << 7) /* Control register E */ #define CTRL_REG_E (4 << 8) diff --git a/trunk/sound/soc/codecs/ak4104.c b/trunk/sound/soc/codecs/ak4104.c deleted file mode 100644 index 338381f4fe1e..000000000000 --- a/trunk/sound/soc/codecs/ak4104.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * AK4104 ALSA SoC (ASoC) driver - * - * Copyright (c) 2009 Daniel Mack - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include - -#include "ak4104.h" - -/* AK4104 registers addresses */ -#define AK4104_REG_CONTROL1 0x00 -#define AK4104_REG_RESERVED 0x01 -#define AK4104_REG_CONTROL2 0x02 -#define AK4104_REG_TX 0x03 -#define AK4104_REG_CHN_STATUS(x) ((x) + 0x04) -#define AK4104_NUM_REGS 10 - -#define AK4104_REG_MASK 0x1f -#define AK4104_READ 0xc0 -#define AK4104_WRITE 0xe0 -#define AK4104_RESERVED_VAL 0x5b - -/* Bit masks for AK4104 registers */ -#define AK4104_CONTROL1_RSTN (1 << 0) -#define AK4104_CONTROL1_PW (1 << 1) -#define AK4104_CONTROL1_DIF0 (1 << 2) -#define AK4104_CONTROL1_DIF1 (1 << 3) - -#define AK4104_CONTROL2_SEL0 (1 << 0) -#define AK4104_CONTROL2_SEL1 (1 << 1) -#define AK4104_CONTROL2_MODE (1 << 2) - -#define AK4104_TX_TXE (1 << 0) -#define AK4104_TX_V (1 << 1) - -#define DRV_NAME "ak4104" - -struct ak4104_private { - struct snd_soc_codec codec; - u8 reg_cache[AK4104_NUM_REGS]; -}; - -static int ak4104_fill_cache(struct snd_soc_codec *codec) -{ - int i; - u8 *reg_cache = codec->reg_cache; - struct spi_device *spi = codec->control_data; - - for (i = 0; i < codec->reg_cache_size; i++) { - int ret = spi_w8r8(spi, i | AK4104_READ); - if (ret < 0) { - dev_err(&spi->dev, "SPI write failure\n"); - return ret; - } - - reg_cache[i] = ret; - } - - return 0; -} - -static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 *reg_cache = codec->reg_cache; - - if (reg >= codec->reg_cache_size) - return -EINVAL; - - return reg_cache[reg]; -} - -static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 *cache = codec->reg_cache; - struct spi_device *spi = codec->control_data; - - if (reg >= codec->reg_cache_size) - return -EINVAL; - - reg &= AK4104_REG_MASK; - reg |= AK4104_WRITE; - - /* only write to the hardware if value has changed */ - if (cache[reg] != value) { - u8 tmp[2] = { reg, value }; - if (spi_write(spi, tmp, sizeof(tmp))) { - dev_err(&spi->dev, "SPI write failed\n"); - return -EIO; - } - - cache[reg] = value; - } - - return 0; -} - -static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int format) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int val = 0; - - val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); - if (val < 0) - return val; - - val &= ~(AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1); - - /* set DAI format */ - switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - val |= AK4104_CONTROL1_DIF0; - break; - case SND_SOC_DAIFMT_I2S: - val |= AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1; - break; - default: - dev_err(codec->dev, "invalid dai format\n"); - return -EINVAL; - } - - /* This device can only be slave */ - if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) - return -EINVAL; - - return ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); -} - -static int ak4104_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - int val = 0; - - /* set the IEC958 bits: consumer mode, no copyright bit */ - val |= IEC958_AES0_CON_NOT_COPYRIGHT; - ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(0), val); - - val = 0; - - switch (params_rate(params)) { - case 44100: - val |= IEC958_AES3_CON_FS_44100; - break; - case 48000: - val |= IEC958_AES3_CON_FS_48000; - break; - case 32000: - val |= IEC958_AES3_CON_FS_32000; - break; - default: - dev_err(codec->dev, "unsupported sampling rate\n"); - return -EINVAL; - } - - return ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(3), val); -} - -struct snd_soc_dai ak4104_dai = { - .name = DRV_NAME, - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_32000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S24_LE - }, - .ops = { - .hw_params = ak4104_hw_params, - .set_fmt = ak4104_set_dai_fmt, - } -}; - -static struct snd_soc_codec *ak4104_codec; - -static int ak4104_spi_probe(struct spi_device *spi) -{ - struct snd_soc_codec *codec; - struct ak4104_private *ak4104; - int ret, val; - - spi->bits_per_word = 8; - spi->mode = SPI_MODE_0; - ret = spi_setup(spi); - if (ret < 0) - return ret; - - ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL); - if (!ak4104) { - dev_err(&spi->dev, "could not allocate codec\n"); - return -ENOMEM; - } - - codec = &ak4104->codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->dev = &spi->dev; - codec->name = DRV_NAME; - codec->owner = THIS_MODULE; - codec->dai = &ak4104_dai; - codec->num_dai = 1; - codec->private_data = ak4104; - codec->control_data = spi; - codec->reg_cache = ak4104->reg_cache; - codec->reg_cache_size = AK4104_NUM_REGS; - - /* read all regs and fill the cache */ - ret = ak4104_fill_cache(codec); - if (ret < 0) { - dev_err(&spi->dev, "failed to fill register cache\n"); - return ret; - } - - /* read the 'reserved' register - according to the datasheet, it - * should contain 0x5b. Not a good way to verify the presence of - * the device, but there is no hardware ID register. */ - if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) != - AK4104_RESERVED_VAL) { - ret = -ENODEV; - goto error_free_codec; - } - - /* set power-up and non-reset bits */ - val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); - val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN; - ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); - if (ret < 0) - goto error_free_codec; - - /* enable transmitter */ - val = ak4104_read_reg_cache(codec, AK4104_REG_TX); - val |= AK4104_TX_TXE; - ret = ak4104_spi_write(codec, AK4104_REG_TX, val); - if (ret < 0) - goto error_free_codec; - - ak4104_codec = codec; - ret = snd_soc_register_dai(&ak4104_dai); - if (ret < 0) { - dev_err(&spi->dev, "failed to register DAI\n"); - goto error_free_codec; - } - - spi_set_drvdata(spi, ak4104); - dev_info(&spi->dev, "SPI device initialized\n"); - return 0; - -error_free_codec: - kfree(ak4104); - ak4104_dai.dev = NULL; - return ret; -} - -static int __devexit ak4104_spi_remove(struct spi_device *spi) -{ - int ret, val; - struct ak4104_private *ak4104 = spi_get_drvdata(spi); - - val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1); - if (val < 0) - return val; - - /* clear power-up and non-reset bits */ - val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); - ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val); - if (ret < 0) - return ret; - - ak4104_codec = NULL; - kfree(ak4104); - return 0; -} - -static int ak4104_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = ak4104_codec; - int ret; - - /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ - socdev->card->codec = codec; - - /* Register PCMs */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms\n"); - return ret; - } - - /* Register the socdev */ - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card\n"); - snd_soc_free_pcms(socdev); - return ret; - } - - return 0; -} - -static int ak4104_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - snd_soc_free_pcms(socdev); - return 0; -}; - -struct snd_soc_codec_device soc_codec_device_ak4104 = { - .probe = ak4104_probe, - .remove = ak4104_remove -}; -EXPORT_SYMBOL_GPL(soc_codec_device_ak4104); - -static struct spi_driver ak4104_spi_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, - .probe = ak4104_spi_probe, - .remove = __devexit_p(ak4104_spi_remove), -}; - -static int __init ak4104_init(void) -{ - pr_info("Asahi Kasei AK4104 ALSA SoC Codec Driver\n"); - return spi_register_driver(&ak4104_spi_driver); -} -module_init(ak4104_init); - -static void __exit ak4104_exit(void) -{ - spi_unregister_driver(&ak4104_spi_driver); -} -module_exit(ak4104_exit); - -MODULE_AUTHOR("Daniel Mack "); -MODULE_DESCRIPTION("Asahi Kasei AK4104 ALSA SoC driver"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/sound/soc/codecs/ak4104.h b/trunk/sound/soc/codecs/ak4104.h deleted file mode 100644 index eb88fe7e4def..000000000000 --- a/trunk/sound/soc/codecs/ak4104.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _AK4104_H -#define _AK4104_H - -extern struct snd_soc_dai ak4104_dai; -extern struct snd_soc_codec_device soc_codec_device_ak4104; - -#endif diff --git a/trunk/sound/soc/codecs/ak4535.c b/trunk/sound/soc/codecs/ak4535.c index d56e6bb1fedb..1f63d387a2f4 100644 --- a/trunk/sound/soc/codecs/ak4535.c +++ b/trunk/sound/soc/codecs/ak4535.c @@ -421,6 +421,13 @@ static int ak4535_set_bias_level(struct snd_soc_codec *codec, SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) +static struct snd_soc_dai_ops ak4535_dai_ops = { + .hw_params = ak4535_hw_params, + .set_fmt = ak4535_set_dai_fmt, + .digital_mute = ak4535_mute, + .set_sysclk = ak4535_set_dai_sysclk, +}; + struct snd_soc_dai ak4535_dai = { .name = "AK4535", .playback = { @@ -435,12 +442,7 @@ struct snd_soc_dai ak4535_dai = { .channels_max = 2, .rates = AK4535_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .hw_params = ak4535_hw_params, - .set_fmt = ak4535_set_dai_fmt, - .digital_mute = ak4535_mute, - .set_sysclk = ak4535_set_dai_sysclk, - }, + .ops = &ak4535_dai_ops, }; EXPORT_SYMBOL_GPL(ak4535_dai); diff --git a/trunk/sound/soc/codecs/cs4270.c b/trunk/sound/soc/codecs/cs4270.c index 0e0c23ee6afc..7ae3d6520e3f 100644 --- a/trunk/sound/soc/codecs/cs4270.c +++ b/trunk/sound/soc/codecs/cs4270.c @@ -12,13 +12,14 @@ * * Current features/limitations: * - * - Software mode is supported. Stand-alone mode is not supported. - * - Only I2C is supported, not SPI - * - Support for master and slave mode - * - The machine driver's 'startup' function must call - * cs4270_set_dai_sysclk() with the value of MCLK. - * - Only I2S and left-justified modes are supported - * - Power management is not supported + * 1) Software mode is supported. Stand-alone mode is not supported. + * 2) Only I2C is supported, not SPI + * 3) Only Master mode is supported, not Slave. + * 4) The machine driver's 'startup' function must call + * cs4270_set_dai_sysclk() with the value of MCLK. + * 5) Only I2S and left-justified modes are supported + * 6) Power management is not supported + * 7) The only supported control is volume and hardware mute (if enabled) */ #include @@ -502,6 +503,13 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { */ static struct snd_soc_codec *cs4270_codec; +static struct snd_soc_dai_ops cs4270_dai_ops = { + .hw_params = cs4270_hw_params, + .set_sysclk = cs4270_set_dai_sysclk, + .set_fmt = cs4270_set_dai_fmt, + .digital_mute = cs4270_mute, +}; + struct snd_soc_dai cs4270_dai = { .name = "cs4270", .playback = { @@ -518,12 +526,7 @@ struct snd_soc_dai cs4270_dai = { .rates = 0, .formats = CS4270_FORMATS, }, - .ops = { - .hw_params = cs4270_hw_params, - .set_sysclk = cs4270_set_dai_sysclk, - .set_fmt = cs4270_set_dai_fmt, - .digital_mute = cs4270_mute, - }, + .ops = &cs4270_dai_ops, }; EXPORT_SYMBOL_GPL(cs4270_dai); diff --git a/trunk/sound/soc/codecs/ssm2602.c b/trunk/sound/soc/codecs/ssm2602.c index 58e225dadc7e..87f606c76822 100644 --- a/trunk/sound/soc/codecs/ssm2602.c +++ b/trunk/sound/soc/codecs/ssm2602.c @@ -506,6 +506,16 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) +static struct snd_soc_dai_ops ssm2602_dai_ops = { + .startup = ssm2602_startup, + .prepare = ssm2602_pcm_prepare, + .hw_params = ssm2602_hw_params, + .shutdown = ssm2602_shutdown, + .digital_mute = ssm2602_mute, + .set_sysclk = ssm2602_set_dai_sysclk, + .set_fmt = ssm2602_set_dai_fmt, +}; + struct snd_soc_dai ssm2602_dai = { .name = "SSM2602", .playback = { @@ -520,15 +530,7 @@ struct snd_soc_dai ssm2602_dai = { .channels_max = 2, .rates = SSM2602_RATES, .formats = SSM2602_FORMATS,}, - .ops = { - .startup = ssm2602_startup, - .prepare = ssm2602_pcm_prepare, - .hw_params = ssm2602_hw_params, - .shutdown = ssm2602_shutdown, - .digital_mute = ssm2602_mute, - .set_sysclk = ssm2602_set_dai_sysclk, - .set_fmt = ssm2602_set_dai_fmt, - } + .ops = &ssm2602_dai_ops, }; EXPORT_SYMBOL_GPL(ssm2602_dai); diff --git a/trunk/sound/soc/codecs/tlv320aic23.c b/trunk/sound/soc/codecs/tlv320aic23.c index 8b20c360adf5..c3f4afb5d017 100644 --- a/trunk/sound/soc/codecs/tlv320aic23.c +++ b/trunk/sound/soc/codecs/tlv320aic23.c @@ -580,6 +580,15 @@ static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, #define AIC23_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) +static struct snd_soc_dai_ops tlv320aic23_dai_ops = { + .prepare = tlv320aic23_pcm_prepare, + .hw_params = tlv320aic23_hw_params, + .shutdown = tlv320aic23_shutdown, + .digital_mute = tlv320aic23_mute, + .set_fmt = tlv320aic23_set_dai_fmt, + .set_sysclk = tlv320aic23_set_dai_sysclk, +}; + struct snd_soc_dai tlv320aic23_dai = { .name = "tlv320aic23", .playback = { @@ -594,14 +603,7 @@ struct snd_soc_dai tlv320aic23_dai = { .channels_max = 2, .rates = AIC23_RATES, .formats = AIC23_FORMATS,}, - .ops = { - .prepare = tlv320aic23_pcm_prepare, - .hw_params = tlv320aic23_hw_params, - .shutdown = tlv320aic23_shutdown, - .digital_mute = tlv320aic23_mute, - .set_fmt = tlv320aic23_set_dai_fmt, - .set_sysclk = tlv320aic23_set_dai_sysclk, - } + .ops = &tlv320aic23_dai_ops, }; EXPORT_SYMBOL_GPL(tlv320aic23_dai); diff --git a/trunk/sound/soc/codecs/tlv320aic26.c b/trunk/sound/soc/codecs/tlv320aic26.c index 229e464cf713..a7f333fc579e 100644 --- a/trunk/sound/soc/codecs/tlv320aic26.c +++ b/trunk/sound/soc/codecs/tlv320aic26.c @@ -270,6 +270,13 @@ static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) #define AIC26_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |\ SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE) +static struct snd_soc_dai_ops aic26_dai_ops = { + .hw_params = aic26_hw_params, + .digital_mute = aic26_mute, + .set_sysclk = aic26_set_sysclk, + .set_fmt = aic26_set_fmt, +}; + struct snd_soc_dai aic26_dai = { .name = "tlv320aic26", .playback = { @@ -286,12 +293,7 @@ struct snd_soc_dai aic26_dai = { .rates = AIC26_RATES, .formats = AIC26_FORMATS, }, - .ops = { - .hw_params = aic26_hw_params, - .digital_mute = aic26_mute, - .set_sysclk = aic26_set_sysclk, - .set_fmt = aic26_set_fmt, - }, + .ops = &aic26_dai_ops, }; EXPORT_SYMBOL_GPL(aic26_dai); diff --git a/trunk/sound/soc/codecs/tlv320aic3x.c b/trunk/sound/soc/codecs/tlv320aic3x.c index d638e3f0728b..ab099f482487 100644 --- a/trunk/sound/soc/codecs/tlv320aic3x.c +++ b/trunk/sound/soc/codecs/tlv320aic3x.c @@ -1088,6 +1088,13 @@ EXPORT_SYMBOL_GPL(aic3x_button_pressed); #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) +static struct snd_soc_dai_ops aic3x_dai_ops = { + .hw_params = aic3x_hw_params, + .digital_mute = aic3x_mute, + .set_sysclk = aic3x_set_dai_sysclk, + .set_fmt = aic3x_set_dai_fmt, +}; + struct snd_soc_dai aic3x_dai = { .name = "tlv320aic3x", .playback = { @@ -1102,12 +1109,7 @@ struct snd_soc_dai aic3x_dai = { .channels_max = 2, .rates = AIC3X_RATES, .formats = AIC3X_FORMATS,}, - .ops = { - .hw_params = aic3x_hw_params, - .digital_mute = aic3x_mute, - .set_sysclk = aic3x_set_dai_sysclk, - .set_fmt = aic3x_set_dai_fmt, - } + .ops = &aic3x_dai_ops, }; EXPORT_SYMBOL_GPL(aic3x_dai); diff --git a/trunk/sound/soc/codecs/twl4030.c b/trunk/sound/soc/codecs/twl4030.c index 86bb15cc82ce..535d8ce2c328 100644 --- a/trunk/sound/soc/codecs/twl4030.c +++ b/trunk/sound/soc/codecs/twl4030.c @@ -584,11 +584,12 @@ static int headsetl_event(struct snd_soc_dapm_widget *w, /* Save the current volume */ hs_gain = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_GAIN_SET); - hs_pop = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_POPN_SET); switch (event) { case SND_SOC_DAPM_POST_PMU: /* Do the anti-pop/bias ramp enable according to the TRM */ + hs_pop = TWL4030_RAMP_DELAY_645MS; + twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); hs_pop |= TWL4030_VMID_EN; twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); /* Is this needed? Can we just use whatever gain here? */ @@ -602,6 +603,8 @@ static int headsetl_event(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMD: /* Do the anti-pop/bias ramp disable according to the TRM */ + hs_pop = twl4030_read_reg_cache(w->codec, + TWL4030_REG_HS_POPN_SET); hs_pop &= ~TWL4030_RAMP_EN; twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); /* Bypass the reg_cache to mute the headset */ @@ -844,17 +847,6 @@ static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0); */ static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0); -static const char *twl4030_rampdelay_texts[] = { - "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", - "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms", - "3495/2581/1748 ms" -}; - -static const struct soc_enum twl4030_rampdelay_enum = - SOC_ENUM_SINGLE(TWL4030_REG_HS_POPN_SET, 2, - ARRAY_SIZE(twl4030_rampdelay_texts), - twl4030_rampdelay_texts); - static const struct snd_kcontrol_new twl4030_snd_controls[] = { /* Common playback gain controls */ SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume", @@ -909,8 +901,6 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = { SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN, 0, 3, 5, 0, input_gain_tlv), - - SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum), }; static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { diff --git a/trunk/sound/soc/codecs/uda134x.c b/trunk/sound/soc/codecs/uda134x.c index 661599295ca7..ddefb8f80145 100644 --- a/trunk/sound/soc/codecs/uda134x.c +++ b/trunk/sound/soc/codecs/uda134x.c @@ -431,6 +431,15 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), }; +static struct snd_soc_dai_ops uda134x_dai_ops = { + .startup = uda134x_startup, + .shutdown = uda134x_shutdown, + .hw_params = uda134x_hw_params, + .digital_mute = uda134x_mute, + .set_sysclk = uda134x_set_dai_sysclk, + .set_fmt = uda134x_set_dai_fmt, +}; + struct snd_soc_dai uda134x_dai = { .name = "UDA134X", /* playback capabilities */ @@ -450,14 +459,7 @@ struct snd_soc_dai uda134x_dai = { .formats = UDA134X_FORMATS, }, /* pcm operations */ - .ops = { - .startup = uda134x_startup, - .shutdown = uda134x_shutdown, - .hw_params = uda134x_hw_params, - .digital_mute = uda134x_mute, - .set_sysclk = uda134x_set_dai_sysclk, - .set_fmt = uda134x_set_dai_fmt, - } + .ops = &uda134x_dai_ops, }; EXPORT_SYMBOL(uda134x_dai); diff --git a/trunk/sound/soc/codecs/uda1380.c b/trunk/sound/soc/codecs/uda1380.c index 1b10f488328c..cafa7684c0e7 100644 --- a/trunk/sound/soc/codecs/uda1380.c +++ b/trunk/sound/soc/codecs/uda1380.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -36,8 +35,7 @@ #include "uda1380.h" -static struct work_struct uda1380_work; -static struct snd_soc_codec *uda1380_codec; +#define UDA1380_VERSION "0.6" /* * uda1380 register cache @@ -54,8 +52,6 @@ static const u16 uda1380_reg[UDA1380_CACHEREGNUM] = { 0x0000, 0x8000, 0x0002, 0x0000, }; -static unsigned long uda1380_cache_dirty; - /* * read uda1380 register cache */ @@ -77,11 +73,8 @@ static inline void uda1380_write_reg_cache(struct snd_soc_codec *codec, u16 reg, unsigned int value) { u16 *cache = codec->reg_cache; - if (reg >= UDA1380_CACHEREGNUM) return; - if ((reg >= 0x10) && (cache[reg] != value)) - set_bit(reg - 0x10, &uda1380_cache_dirty); cache[reg] = value; } @@ -120,8 +113,6 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, (data[0]<<8) | data[1]); return -EIO; } - if (reg >= 0x10) - clear_bit(reg - 0x10, &uda1380_cache_dirty); return 0; } else return -EIO; @@ -129,20 +120,6 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg, #define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0) -static void uda1380_flush_work(struct work_struct *work) -{ - int bit, reg; - - for_each_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { - reg = 0x10 + bit; - pr_debug("uda1380: flush reg %x val %x:\n", reg, - uda1380_read_reg_cache(uda1380_codec, reg)); - uda1380_write(uda1380_codec, reg, - uda1380_read_reg_cache(uda1380_codec, reg)); - clear_bit(bit, &uda1380_cache_dirty); - } -} - /* declarations of ALSA reg_elem_REAL controls */ static const char *uda1380_deemp[] = { "None", @@ -277,6 +254,7 @@ static const struct snd_kcontrol_new uda1380_snd_controls[] = { SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0), /* DA_POL_INV */ SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum), /* SEL_NS */ SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum), /* MIX_POS, MIX */ + SOC_SINGLE("Silence Switch", UDA1380_MIXER, 7, 1, 0), /* SILENCE, force DAC output to silence */ SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0), /* SDET_ON */ SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum), /* SD_VALUE */ SOC_ENUM("Oversampling Input", uda1380_os_enum), /* OS */ @@ -399,9 +377,8 @@ static int uda1380_set_dai_fmt_both(struct snd_soc_dai *codec_dai, iface |= R01_SFORI_MSB | R01_SFORO_MSB; } - /* DATAI is slave only, so in single-link mode, this has to be slave */ - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) - return -EINVAL; + if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) + iface |= R01_SIM; uda1380_write(codec, UDA1380_IFACE, iface); @@ -429,10 +406,6 @@ static int uda1380_set_dai_fmt_playback(struct snd_soc_dai *codec_dai, iface |= R01_SFORI_MSB; } - /* DATAI is slave only, so this has to be slave */ - if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) - return -EINVAL; - uda1380_write(codec, UDA1380_IFACE, iface); return 0; @@ -467,28 +440,41 @@ static int uda1380_set_dai_fmt_capture(struct snd_soc_dai *codec_dai, return 0; } -static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) +/* + * Flush reg cache + * We can only write the interpolator and decimator registers + * when the DAI is being clocked by the CPU DAI. It's up to the + * machine and cpu DAI driver to do this before we are called. + */ +static int uda1380_pcm_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - uda1380_write_reg_cache(codec, UDA1380_MIXER, - mixer & ~R14_SILENCE); - schedule_work(&uda1380_work); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - uda1380_write_reg_cache(codec, UDA1380_MIXER, - mixer | R14_SILENCE); - schedule_work(&uda1380_work); - break; + int reg, reg_start, reg_end, clk; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + reg_start = UDA1380_MVOL; + reg_end = UDA1380_MIXER; + } else { + reg_start = UDA1380_DEC; + reg_end = UDA1380_AGC; + } + + /* FIXME disable DAC_CLK */ + clk = uda1380_read_reg_cache(codec, UDA1380_CLK); + uda1380_write(codec, UDA1380_CLK, clk & ~R00_DAC_CLK); + + for (reg = reg_start; reg <= reg_end; reg++) { + pr_debug("uda1380: flush reg %x val %x:", reg, + uda1380_read_reg_cache(codec, reg)); + uda1380_write(codec, reg, uda1380_read_reg_cache(codec, reg)); } + + /* FIXME restore DAC_CLK */ + uda1380_write(codec, UDA1380_CLK, clk); + return 0; } @@ -554,6 +540,24 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, uda1380_write(codec, UDA1380_CLK, clk); } +static int uda1380_mute(struct snd_soc_dai *codec_dai, int mute) +{ + struct snd_soc_codec *codec = codec_dai->codec; + u16 mute_reg = uda1380_read_reg_cache(codec, UDA1380_DEEMP) & ~R13_MTM; + + /* FIXME: mute(codec,0) is called when the magician clock is already + * set to WSPLL, but for some unknown reason writing to interpolator + * registers works only when clocked by SYSCLK */ + u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); + uda1380_write(codec, UDA1380_CLK, ~R00_DAC_CLK & clk); + if (mute) + uda1380_write(codec, UDA1380_DEEMP, mute_reg | R13_MTM); + else + uda1380_write(codec, UDA1380_DEEMP, mute_reg); + uda1380_write(codec, UDA1380_CLK, clk); + return 0; +} + static int uda1380_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -579,6 +583,29 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec, SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) +static struct snd_soc_dai_ops uda1380_dai_ops = { + .hw_params = uda1380_pcm_hw_params, + .shutdown = uda1380_pcm_shutdown, + .prepare = uda1380_pcm_prepare, + .digital_mute = uda1380_mute, + .set_fmt = uda1380_set_dai_fmt_both, +}; + +static struct snd_soc_dai_ops uda1380_dai_ops_playback = { + .hw_params = uda1380_pcm_hw_params, + .shutdown = uda1380_pcm_shutdown, + .prepare = uda1380_pcm_prepare, + .digital_mute = uda1380_mute, + .set_fmt = uda1380_set_dai_fmt_playback, +}; + +static struct snd_soc_dai_ops uda1380_dai_ops_capture = { + .hw_params = uda1380_pcm_hw_params, + .shutdown = uda1380_pcm_shutdown, + .prepare = uda1380_pcm_prepare, + .set_fmt = uda1380_set_dai_fmt_capture, +}; + struct snd_soc_dai uda1380_dai[] = { { .name = "UDA1380", @@ -594,12 +621,7 @@ struct snd_soc_dai uda1380_dai[] = { .channels_max = 2, .rates = UDA1380_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .trigger = uda1380_trigger, - .hw_params = uda1380_pcm_hw_params, - .shutdown = uda1380_pcm_shutdown, - .set_fmt = uda1380_set_dai_fmt_both, - }, + .ops = &uda1380_dai_ops, }, { /* playback only - dual interface */ .name = "UDA1380", @@ -610,12 +632,7 @@ struct snd_soc_dai uda1380_dai[] = { .rates = UDA1380_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = { - .trigger = uda1380_trigger, - .hw_params = uda1380_pcm_hw_params, - .shutdown = uda1380_pcm_shutdown, - .set_fmt = uda1380_set_dai_fmt_playback, - }, + .ops = &uda1380_dai_ops_playback, }, { /* capture only - dual interface*/ .name = "UDA1380", @@ -626,12 +643,7 @@ struct snd_soc_dai uda1380_dai[] = { .rates = UDA1380_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = { - .trigger = uda1380_trigger, - .hw_params = uda1380_pcm_hw_params, - .shutdown = uda1380_pcm_shutdown, - .set_fmt = uda1380_set_dai_fmt_capture, - }, + .ops = &uda1380_dai_ops_capture, }, }; EXPORT_SYMBOL_GPL(uda1380_dai); @@ -688,9 +700,6 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) codec->reg_cache_step = 1; uda1380_reset(codec); - uda1380_codec = codec; - INIT_WORK(&uda1380_work, uda1380_flush_work); - /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { @@ -823,6 +832,8 @@ static int uda1380_probe(struct platform_device *pdev) struct snd_soc_codec *codec; int ret; + pr_info("UDA1380 Audio Codec %s", UDA1380_VERSION); + setup = socdev->codec_data; codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); if (codec == NULL) diff --git a/trunk/sound/soc/codecs/wm8350.c b/trunk/sound/soc/codecs/wm8350.c index 359e5cc86f34..3b1d0993bed9 100644 --- a/trunk/sound/soc/codecs/wm8350.c +++ b/trunk/sound/soc/codecs/wm8350.c @@ -1538,6 +1538,16 @@ static int wm8350_remove(struct platform_device *pdev) SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) +static struct snd_soc_dai_ops wm8350_dai_ops = { + .hw_params = wm8350_pcm_hw_params, + .digital_mute = wm8350_mute, + .trigger = wm8350_pcm_trigger, + .set_fmt = wm8350_set_dai_fmt, + .set_sysclk = wm8350_set_dai_sysclk, + .set_pll = wm8350_set_fll, + .set_clkdiv = wm8350_set_clkdiv, +}; + struct snd_soc_dai wm8350_dai = { .name = "WM8350", .playback = { @@ -1554,15 +1564,7 @@ struct snd_soc_dai wm8350_dai = { .rates = WM8350_RATES, .formats = WM8350_FORMATS, }, - .ops = { - .hw_params = wm8350_pcm_hw_params, - .digital_mute = wm8350_mute, - .trigger = wm8350_pcm_trigger, - .set_fmt = wm8350_set_dai_fmt, - .set_sysclk = wm8350_set_dai_sysclk, - .set_pll = wm8350_set_fll, - .set_clkdiv = wm8350_set_clkdiv, - }, + .ops = &wm8350_dai_ops, }; EXPORT_SYMBOL_GPL(wm8350_dai); diff --git a/trunk/sound/soc/codecs/wm8400.c b/trunk/sound/soc/codecs/wm8400.c deleted file mode 100644 index 9cb73d9d023d..000000000000 --- a/trunk/sound/soc/codecs/wm8400.c +++ /dev/null @@ -1,1479 +0,0 @@ -/* - * wm8400.c -- WM8400 ALSA Soc Audio driver - * - * Copyright 2008, 2009 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8400.h" - -/* Fake register for internal state */ -#define WM8400_INTDRIVBITS (WM8400_REGISTER_COUNT + 1) -#define WM8400_INMIXL_PWR 0 -#define WM8400_AINLMUX_PWR 1 -#define WM8400_INMIXR_PWR 2 -#define WM8400_AINRMUX_PWR 3 - -static struct regulator_bulk_data power[] = { - { - .supply = "I2S1VDD", - }, - { - .supply = "I2S2VDD", - }, - { - .supply = "DCVDD", - }, - { - .supply = "FLLVDD", - }, - { - .supply = "HPVDD", - }, - { - .supply = "SPKVDD", - }, -}; - -/* codec private data */ -struct wm8400_priv { - struct snd_soc_codec codec; - struct wm8400 *wm8400; - u16 fake_register; - unsigned int sysclk; - unsigned int pcmclk; - struct work_struct work; -}; - -static inline unsigned int wm8400_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - struct wm8400_priv *wm8400 = codec->private_data; - - if (reg == WM8400_INTDRIVBITS) - return wm8400->fake_register; - else - return wm8400_reg_read(wm8400->wm8400, reg); -} - -/* - * write to the wm8400 register space - */ -static int wm8400_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - struct wm8400_priv *wm8400 = codec->private_data; - - if (reg == WM8400_INTDRIVBITS) { - wm8400->fake_register = value; - return 0; - } else - return wm8400_set_bits(wm8400->wm8400, reg, 0xffff, value); -} - -static void wm8400_codec_reset(struct snd_soc_codec *codec) -{ - struct wm8400_priv *wm8400 = codec->private_data; - - wm8400_reset_codec_reg_cache(wm8400->wm8400); -} - -static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); - -static const DECLARE_TLV_DB_LINEAR(in_pga_tlv, -1650, 3000); - -static const DECLARE_TLV_DB_LINEAR(out_mix_tlv, -2100, 0); - -static const DECLARE_TLV_DB_LINEAR(out_pga_tlv, -7300, 600); - -static const DECLARE_TLV_DB_LINEAR(out_omix_tlv, -600, 0); - -static const DECLARE_TLV_DB_LINEAR(out_dac_tlv, -7163, 0); - -static const DECLARE_TLV_DB_LINEAR(in_adc_tlv, -7163, 1763); - -static const DECLARE_TLV_DB_LINEAR(out_sidetone_tlv, -3600, 0); - -static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int reg = mc->reg; - int ret; - u16 val; - - ret = snd_soc_put_volsw(kcontrol, ucontrol); - if (ret < 0) - return ret; - - /* now hit the volume update bits (always bit 8) */ - val = wm8400_read(codec, reg); - return wm8400_write(codec, reg, val | 0x0100); -} - -#define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_get_volsw, .put = wm8400_outpga_put_volsw_vu, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } - - -static const char *wm8400_digital_sidetone[] = - {"None", "Left ADC", "Right ADC", "Reserved"}; - -static const struct soc_enum wm8400_left_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, - WM8400_ADC_TO_DACL_SHIFT, 2, wm8400_digital_sidetone); - -static const struct soc_enum wm8400_right_digital_sidetone_enum = -SOC_ENUM_SINGLE(WM8400_DIGITAL_SIDE_TONE, - WM8400_ADC_TO_DACR_SHIFT, 2, wm8400_digital_sidetone); - -static const char *wm8400_adcmode[] = - {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; - -static const struct soc_enum wm8400_right_adcmode_enum = -SOC_ENUM_SINGLE(WM8400_ADC_CTRL, WM8400_ADC_HPF_CUT_SHIFT, 3, wm8400_adcmode); - -static const struct snd_kcontrol_new wm8400_snd_controls[] = { -/* INMIXL */ -SOC_SINGLE("LIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L12MNBST_SHIFT, - 1, 0), -SOC_SINGLE("LIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_L34MNBST_SHIFT, - 1, 0), -/* INMIXR */ -SOC_SINGLE("RIN12 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R12MNBST_SHIFT, - 1, 0), -SOC_SINGLE("RIN34 PGA Boost", WM8400_INPUT_MIXER3, WM8400_R34MNBST_SHIFT, - 1, 0), - -/* LOMIX */ -SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER3, - WM8400_LLI3LOVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3, - WM8400_LR12LOVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER3, - WM8400_LL12LOVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER5, - WM8400_LRI3LOVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER5, - WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER5, - WM8400_LRBLOVOL_SHIFT, 7, 0, out_mix_tlv), - -/* ROMIX */ -SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8400_OUTPUT_MIXER4, - WM8400_RRI3ROVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4, - WM8400_RL12ROVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8400_OUTPUT_MIXER4, - WM8400_RR12ROVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8400_OUTPUT_MIXER6, - WM8400_RLI3ROVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8400_OUTPUT_MIXER6, - WM8400_RLBROVOL_SHIFT, 7, 0, out_mix_tlv), -SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8400_OUTPUT_MIXER6, - WM8400_RRBROVOL_SHIFT, 7, 0, out_mix_tlv), - -/* LOUT */ -WM8400_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8400_LEFT_OUTPUT_VOLUME, - WM8400_LOUTVOL_SHIFT, WM8400_LOUTVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("LOUT ZC", WM8400_LEFT_OUTPUT_VOLUME, WM8400_LOZC_SHIFT, 1, 0), - -/* ROUT */ -WM8400_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8400_RIGHT_OUTPUT_VOLUME, - WM8400_ROUTVOL_SHIFT, WM8400_ROUTVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("ROUT ZC", WM8400_RIGHT_OUTPUT_VOLUME, WM8400_ROZC_SHIFT, 1, 0), - -/* LOPGA */ -WM8400_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8400_LEFT_OPGA_VOLUME, - WM8400_LOPGAVOL_SHIFT, WM8400_LOPGAVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("LOPGA ZC Switch", WM8400_LEFT_OPGA_VOLUME, - WM8400_LOPGAZC_SHIFT, 1, 0), - -/* ROPGA */ -WM8400_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8400_RIGHT_OPGA_VOLUME, - WM8400_ROPGAVOL_SHIFT, WM8400_ROPGAVOL_MASK, 0, out_pga_tlv), -SOC_SINGLE("ROPGA ZC Switch", WM8400_RIGHT_OPGA_VOLUME, - WM8400_ROPGAZC_SHIFT, 1, 0), - -SOC_SINGLE("LON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_LONMUTE_SHIFT, 1, 0), -SOC_SINGLE("LOP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_LOPMUTE_SHIFT, 1, 0), -SOC_SINGLE("LOP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_LOATTN_SHIFT, 1, 0), -SOC_SINGLE("RON Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_RONMUTE_SHIFT, 1, 0), -SOC_SINGLE("ROP Mute Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_ROPMUTE_SHIFT, 1, 0), -SOC_SINGLE("ROP Attenuation Switch", WM8400_LINE_OUTPUTS_VOLUME, - WM8400_ROATTN_SHIFT, 1, 0), - -SOC_SINGLE("OUT3 Mute Switch", WM8400_OUT3_4_VOLUME, - WM8400_OUT3MUTE_SHIFT, 1, 0), -SOC_SINGLE("OUT3 Attenuation Switch", WM8400_OUT3_4_VOLUME, - WM8400_OUT3ATTN_SHIFT, 1, 0), - -SOC_SINGLE("OUT4 Mute Switch", WM8400_OUT3_4_VOLUME, - WM8400_OUT4MUTE_SHIFT, 1, 0), -SOC_SINGLE("OUT4 Attenuation Switch", WM8400_OUT3_4_VOLUME, - WM8400_OUT4ATTN_SHIFT, 1, 0), - -SOC_SINGLE("Speaker Mode Switch", WM8400_CLASSD1, - WM8400_CDMODE_SHIFT, 1, 0), - -SOC_SINGLE("Speaker Output Attenuation Volume", WM8400_SPEAKER_VOLUME, - WM8400_SPKATTN_SHIFT, WM8400_SPKATTN_MASK, 0), -SOC_SINGLE("Speaker DC Boost Volume", WM8400_CLASSD3, - WM8400_DCGAIN_SHIFT, 6, 0), -SOC_SINGLE("Speaker AC Boost Volume", WM8400_CLASSD3, - WM8400_ACGAIN_SHIFT, 6, 0), - -WM8400_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume", - WM8400_LEFT_DAC_DIGITAL_VOLUME, WM8400_DACL_VOL_SHIFT, - 127, 0, out_dac_tlv), - -WM8400_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume", - WM8400_RIGHT_DAC_DIGITAL_VOLUME, WM8400_DACR_VOL_SHIFT, - 127, 0, out_dac_tlv), - -SOC_ENUM("Left Digital Sidetone", wm8400_left_digital_sidetone_enum), -SOC_ENUM("Right Digital Sidetone", wm8400_right_digital_sidetone_enum), - -SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE, - WM8400_ADCL_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv), -SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8400_DIGITAL_SIDE_TONE, - WM8400_ADCR_DAC_SVOL_SHIFT, 15, 0, out_sidetone_tlv), - -SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8400_ADC_CTRL, - WM8400_ADC_HPF_ENA_SHIFT, 1, 0), - -SOC_ENUM("ADC HPF Mode", wm8400_right_adcmode_enum), - -WM8400_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume", - WM8400_LEFT_ADC_DIGITAL_VOLUME, - WM8400_ADCL_VOL_SHIFT, - WM8400_ADCL_VOL_MASK, - 0, - in_adc_tlv), - -WM8400_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume", - WM8400_RIGHT_ADC_DIGITAL_VOLUME, - WM8400_ADCR_VOL_SHIFT, - WM8400_ADCR_VOL_MASK, - 0, - in_adc_tlv), - -WM8400_OUTPGA_SINGLE_R_TLV("LIN12 Volume", - WM8400_LEFT_LINE_INPUT_1_2_VOLUME, - WM8400_LIN12VOL_SHIFT, - WM8400_LIN12VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("LIN12 ZC Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME, - WM8400_LI12ZC_SHIFT, 1, 0), - -SOC_SINGLE("LIN12 Mute Switch", WM8400_LEFT_LINE_INPUT_1_2_VOLUME, - WM8400_LI12MUTE_SHIFT, 1, 0), - -WM8400_OUTPGA_SINGLE_R_TLV("LIN34 Volume", - WM8400_LEFT_LINE_INPUT_3_4_VOLUME, - WM8400_LIN34VOL_SHIFT, - WM8400_LIN34VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("LIN34 ZC Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME, - WM8400_LI34ZC_SHIFT, 1, 0), - -SOC_SINGLE("LIN34 Mute Switch", WM8400_LEFT_LINE_INPUT_3_4_VOLUME, - WM8400_LI34MUTE_SHIFT, 1, 0), - -WM8400_OUTPGA_SINGLE_R_TLV("RIN12 Volume", - WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8400_RIN12VOL_SHIFT, - WM8400_RIN12VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("RIN12 ZC Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8400_RI12ZC_SHIFT, 1, 0), - -SOC_SINGLE("RIN12 Mute Switch", WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8400_RI12MUTE_SHIFT, 1, 0), - -WM8400_OUTPGA_SINGLE_R_TLV("RIN34 Volume", - WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8400_RIN34VOL_SHIFT, - WM8400_RIN34VOL_MASK, - 0, - in_pga_tlv), - -SOC_SINGLE("RIN34 ZC Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8400_RI34ZC_SHIFT, 1, 0), - -SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8400_RI34MUTE_SHIFT, 1, 0), - -}; - -/* add non dapm controls */ -static int wm8400_add_controls(struct snd_soc_codec *codec) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(wm8400_snd_controls); i++) { - err = snd_ctl_add(codec->card, - snd_soc_cnew(&wm8400_snd_controls[i],codec, - NULL)); - if (err < 0) - return err; - } - return 0; -} - -/* - * _DAPM_ Controls - */ - -static int inmixer_event (struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - u16 reg, fakepower; - - reg = wm8400_read(w->codec, WM8400_POWER_MANAGEMENT_2); - fakepower = wm8400_read(w->codec, WM8400_INTDRIVBITS); - - if (fakepower & ((1 << WM8400_INMIXL_PWR) | - (1 << WM8400_AINLMUX_PWR))) { - reg |= WM8400_AINL_ENA; - } else { - reg &= ~WM8400_AINL_ENA; - } - - if (fakepower & ((1 << WM8400_INMIXR_PWR) | - (1 << WM8400_AINRMUX_PWR))) { - reg |= WM8400_AINR_ENA; - } else { - reg &= ~WM8400_AINL_ENA; - } - wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg); - - return 0; -} - -static int outmixer_event (struct snd_soc_dapm_widget *w, - struct snd_kcontrol * kcontrol, int event) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - u32 reg_shift = mc->shift; - int ret = 0; - u16 reg; - - switch (reg_shift) { - case WM8400_SPEAKER_MIXER | (WM8400_LDSPK << 8) : - reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER1); - if (reg & WM8400_LDLO) { - printk(KERN_WARNING - "Cannot set as Output Mixer 1 LDLO Set\n"); - ret = -1; - } - break; - case WM8400_SPEAKER_MIXER | (WM8400_RDSPK << 8): - reg = wm8400_read(w->codec, WM8400_OUTPUT_MIXER2); - if (reg & WM8400_RDRO) { - printk(KERN_WARNING - "Cannot set as Output Mixer 2 RDRO Set\n"); - ret = -1; - } - break; - case WM8400_OUTPUT_MIXER1 | (WM8400_LDLO << 8): - reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER); - if (reg & WM8400_LDSPK) { - printk(KERN_WARNING - "Cannot set as Speaker Mixer LDSPK Set\n"); - ret = -1; - } - break; - case WM8400_OUTPUT_MIXER2 | (WM8400_RDRO << 8): - reg = wm8400_read(w->codec, WM8400_SPEAKER_MIXER); - if (reg & WM8400_RDSPK) { - printk(KERN_WARNING - "Cannot set as Speaker Mixer RDSPK Set\n"); - ret = -1; - } - break; - } - - return ret; -} - -/* INMIX dB values */ -static const unsigned int in_mix_tlv[] = { - TLV_DB_RANGE_HEAD(1), - 0,7, TLV_DB_LINEAR_ITEM(-1200, 600), -}; - -/* Left In PGA Connections */ -static const struct snd_kcontrol_new wm8400_dapm_lin12_pga_controls[] = { -SOC_DAPM_SINGLE("LIN1 Switch", WM8400_INPUT_MIXER2, WM8400_LMN1_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LIN2 Switch", WM8400_INPUT_MIXER2, WM8400_LMP2_SHIFT, 1, 0), -}; - -static const struct snd_kcontrol_new wm8400_dapm_lin34_pga_controls[] = { -SOC_DAPM_SINGLE("LIN3 Switch", WM8400_INPUT_MIXER2, WM8400_LMN3_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LIN4 Switch", WM8400_INPUT_MIXER2, WM8400_LMP4_SHIFT, 1, 0), -}; - -/* Right In PGA Connections */ -static const struct snd_kcontrol_new wm8400_dapm_rin12_pga_controls[] = { -SOC_DAPM_SINGLE("RIN1 Switch", WM8400_INPUT_MIXER2, WM8400_RMN1_SHIFT, 1, 0), -SOC_DAPM_SINGLE("RIN2 Switch", WM8400_INPUT_MIXER2, WM8400_RMP2_SHIFT, 1, 0), -}; - -static const struct snd_kcontrol_new wm8400_dapm_rin34_pga_controls[] = { -SOC_DAPM_SINGLE("RIN3 Switch", WM8400_INPUT_MIXER2, WM8400_RMN3_SHIFT, 1, 0), -SOC_DAPM_SINGLE("RIN4 Switch", WM8400_INPUT_MIXER2, WM8400_RMP4_SHIFT, 1, 0), -}; - -/* INMIXL */ -static const struct snd_kcontrol_new wm8400_dapm_inmixl_controls[] = { -SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8400_INPUT_MIXER3, - WM8400_LDBVOL_SHIFT, WM8400_LDBVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8400_INPUT_MIXER5, WM8400_LI2BVOL_SHIFT, - 7, 0, in_mix_tlv), -SOC_DAPM_SINGLE("LINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT, - 1, 0), -SOC_DAPM_SINGLE("LINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT, - 1, 0), -}; - -/* INMIXR */ -static const struct snd_kcontrol_new wm8400_dapm_inmixr_controls[] = { -SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8400_INPUT_MIXER4, - WM8400_RDBVOL_SHIFT, WM8400_RDBVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8400_INPUT_MIXER6, WM8400_RI2BVOL_SHIFT, - 7, 0, in_mix_tlv), -SOC_DAPM_SINGLE("RINPGA12 Switch", WM8400_INPUT_MIXER3, WM8400_L12MNB_SHIFT, - 1, 0), -SOC_DAPM_SINGLE("RINPGA34 Switch", WM8400_INPUT_MIXER3, WM8400_L34MNB_SHIFT, - 1, 0), -}; - -/* AINLMUX */ -static const char *wm8400_ainlmux[] = - {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; - -static const struct soc_enum wm8400_ainlmux_enum = -SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINLMODE_SHIFT, - ARRAY_SIZE(wm8400_ainlmux), wm8400_ainlmux); - -static const struct snd_kcontrol_new wm8400_dapm_ainlmux_controls = -SOC_DAPM_ENUM("Route", wm8400_ainlmux_enum); - -/* DIFFINL */ - -/* AINRMUX */ -static const char *wm8400_ainrmux[] = - {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; - -static const struct soc_enum wm8400_ainrmux_enum = -SOC_ENUM_SINGLE( WM8400_INPUT_MIXER1, WM8400_AINRMODE_SHIFT, - ARRAY_SIZE(wm8400_ainrmux), wm8400_ainrmux); - -static const struct snd_kcontrol_new wm8400_dapm_ainrmux_controls = -SOC_DAPM_ENUM("Route", wm8400_ainrmux_enum); - -/* RXVOICE */ -static const struct snd_kcontrol_new wm8400_dapm_rxvoice_controls[] = { -SOC_DAPM_SINGLE_TLV("LIN4/RXN", WM8400_INPUT_MIXER5, WM8400_LR4BVOL_SHIFT, - WM8400_LR4BVOL_MASK, 0, in_mix_tlv), -SOC_DAPM_SINGLE_TLV("RIN4/RXP", WM8400_INPUT_MIXER6, WM8400_RL4BVOL_SHIFT, - WM8400_RL4BVOL_MASK, 0, in_mix_tlv), -}; - -/* LOMIX */ -static const struct snd_kcontrol_new wm8400_dapm_lomix_controls[] = { -SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LRBLO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LLBLO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LRI3LO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LLI3LO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LR12LO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER1, - WM8400_LL12LO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8400_OUTPUT_MIXER1, - WM8400_LDLO_SHIFT, 1, 0), -}; - -/* ROMIX */ -static const struct snd_kcontrol_new wm8400_dapm_romix_controls[] = { -SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RLBRO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RRBRO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RLI3RO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RRI3RO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RL12RO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8400_OUTPUT_MIXER2, - WM8400_RR12RO_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8400_OUTPUT_MIXER2, - WM8400_RDRO_SHIFT, 1, 0), -}; - -/* LONMIX */ -static const struct snd_kcontrol_new wm8400_dapm_lonmix_controls[] = { -SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1, - WM8400_LLOPGALON_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER1, - WM8400_LROPGALON_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8400_LINE_MIXER1, - WM8400_LOPLON_SHIFT, 1, 0), -}; - -/* LOPMIX */ -static const struct snd_kcontrol_new wm8400_dapm_lopmix_controls[] = { -SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER1, - WM8400_LR12LOP_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER1, - WM8400_LL12LOP_SHIFT, 1, 0), -SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8400_LINE_MIXER1, - WM8400_LLOPGALOP_SHIFT, 1, 0), -}; - -/* RONMIX */ -static const struct snd_kcontrol_new wm8400_dapm_ronmix_controls[] = { -SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2, - WM8400_RROPGARON_SHIFT, 1, 0), -SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8400_LINE_MIXER2, - WM8400_RLOPGARON_SHIFT, 1, 0), -SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8400_LINE_MIXER2, - WM8400_ROPRON_SHIFT, 1, 0), -}; - -/* ROPMIX */ -static const struct snd_kcontrol_new wm8400_dapm_ropmix_controls[] = { -SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8400_LINE_MIXER2, - WM8400_RL12ROP_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8400_LINE_MIXER2, - WM8400_RR12ROP_SHIFT, 1, 0), -SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8400_LINE_MIXER2, - WM8400_RROPGAROP_SHIFT, 1, 0), -}; - -/* OUT3MIX */ -static const struct snd_kcontrol_new wm8400_dapm_out3mix_controls[] = { -SOC_DAPM_SINGLE("OUT3MIX LIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER, - WM8400_LI4O3_SHIFT, 1, 0), -SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8400_OUT3_4_MIXER, - WM8400_LPGAO3_SHIFT, 1, 0), -}; - -/* OUT4MIX */ -static const struct snd_kcontrol_new wm8400_dapm_out4mix_controls[] = { -SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8400_OUT3_4_MIXER, - WM8400_RPGAO4_SHIFT, 1, 0), -SOC_DAPM_SINGLE("OUT4MIX RIN4/RXP Bypass Switch", WM8400_OUT3_4_MIXER, - WM8400_RI4O4_SHIFT, 1, 0), -}; - -/* SPKMIX */ -static const struct snd_kcontrol_new wm8400_dapm_spkmix_controls[] = { -SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8400_SPEAKER_MIXER, - WM8400_LI2SPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8400_SPEAKER_MIXER, - WM8400_LB2SPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8400_SPEAKER_MIXER, - WM8400_LOPGASPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8400_SPEAKER_MIXER, - WM8400_LDSPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8400_SPEAKER_MIXER, - WM8400_RDSPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8400_SPEAKER_MIXER, - WM8400_ROPGASPK_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8400_SPEAKER_MIXER, - WM8400_RL12ROP_SHIFT, 1, 0), -SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8400_SPEAKER_MIXER, - WM8400_RI2SPK_SHIFT, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8400_dapm_widgets[] = { -/* Input Side */ -/* Input Lines */ -SND_SOC_DAPM_INPUT("LIN1"), -SND_SOC_DAPM_INPUT("LIN2"), -SND_SOC_DAPM_INPUT("LIN3"), -SND_SOC_DAPM_INPUT("LIN4/RXN"), -SND_SOC_DAPM_INPUT("RIN3"), -SND_SOC_DAPM_INPUT("RIN4/RXP"), -SND_SOC_DAPM_INPUT("RIN1"), -SND_SOC_DAPM_INPUT("RIN2"), -SND_SOC_DAPM_INPUT("Internal ADC Source"), - -/* DACs */ -SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8400_POWER_MANAGEMENT_2, - WM8400_ADCL_ENA_SHIFT, 0), -SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8400_POWER_MANAGEMENT_2, - WM8400_ADCR_ENA_SHIFT, 0), - -/* Input PGAs */ -SND_SOC_DAPM_MIXER("LIN12 PGA", WM8400_POWER_MANAGEMENT_2, - WM8400_LIN12_ENA_SHIFT, - 0, &wm8400_dapm_lin12_pga_controls[0], - ARRAY_SIZE(wm8400_dapm_lin12_pga_controls)), -SND_SOC_DAPM_MIXER("LIN34 PGA", WM8400_POWER_MANAGEMENT_2, - WM8400_LIN34_ENA_SHIFT, - 0, &wm8400_dapm_lin34_pga_controls[0], - ARRAY_SIZE(wm8400_dapm_lin34_pga_controls)), -SND_SOC_DAPM_MIXER("RIN12 PGA", WM8400_POWER_MANAGEMENT_2, - WM8400_RIN12_ENA_SHIFT, - 0, &wm8400_dapm_rin12_pga_controls[0], - ARRAY_SIZE(wm8400_dapm_rin12_pga_controls)), -SND_SOC_DAPM_MIXER("RIN34 PGA", WM8400_POWER_MANAGEMENT_2, - WM8400_RIN34_ENA_SHIFT, - 0, &wm8400_dapm_rin34_pga_controls[0], - ARRAY_SIZE(wm8400_dapm_rin34_pga_controls)), - -/* INMIXL */ -SND_SOC_DAPM_MIXER_E("INMIXL", WM8400_INTDRIVBITS, WM8400_INMIXL_PWR, 0, - &wm8400_dapm_inmixl_controls[0], - ARRAY_SIZE(wm8400_dapm_inmixl_controls), - inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* AINLMUX */ -SND_SOC_DAPM_MUX_E("AILNMUX", WM8400_INTDRIVBITS, WM8400_AINLMUX_PWR, 0, - &wm8400_dapm_ainlmux_controls, inmixer_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* INMIXR */ -SND_SOC_DAPM_MIXER_E("INMIXR", WM8400_INTDRIVBITS, WM8400_INMIXR_PWR, 0, - &wm8400_dapm_inmixr_controls[0], - ARRAY_SIZE(wm8400_dapm_inmixr_controls), - inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* AINRMUX */ -SND_SOC_DAPM_MUX_E("AIRNMUX", WM8400_INTDRIVBITS, WM8400_AINRMUX_PWR, 0, - &wm8400_dapm_ainrmux_controls, inmixer_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - -/* Output Side */ -/* DACs */ -SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8400_POWER_MANAGEMENT_3, - WM8400_DACL_ENA_SHIFT, 0), -SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8400_POWER_MANAGEMENT_3, - WM8400_DACR_ENA_SHIFT, 0), - -/* LOMIX */ -SND_SOC_DAPM_MIXER_E("LOMIX", WM8400_POWER_MANAGEMENT_3, - WM8400_LOMIX_ENA_SHIFT, - 0, &wm8400_dapm_lomix_controls[0], - ARRAY_SIZE(wm8400_dapm_lomix_controls), - outmixer_event, SND_SOC_DAPM_PRE_REG), - -/* LONMIX */ -SND_SOC_DAPM_MIXER("LONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LON_ENA_SHIFT, - 0, &wm8400_dapm_lonmix_controls[0], - ARRAY_SIZE(wm8400_dapm_lonmix_controls)), - -/* LOPMIX */ -SND_SOC_DAPM_MIXER("LOPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_LOP_ENA_SHIFT, - 0, &wm8400_dapm_lopmix_controls[0], - ARRAY_SIZE(wm8400_dapm_lopmix_controls)), - -/* OUT3MIX */ -SND_SOC_DAPM_MIXER("OUT3MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT3_ENA_SHIFT, - 0, &wm8400_dapm_out3mix_controls[0], - ARRAY_SIZE(wm8400_dapm_out3mix_controls)), - -/* SPKMIX */ -SND_SOC_DAPM_MIXER_E("SPKMIX", WM8400_POWER_MANAGEMENT_1, WM8400_SPK_ENA_SHIFT, - 0, &wm8400_dapm_spkmix_controls[0], - ARRAY_SIZE(wm8400_dapm_spkmix_controls), outmixer_event, - SND_SOC_DAPM_PRE_REG), - -/* OUT4MIX */ -SND_SOC_DAPM_MIXER("OUT4MIX", WM8400_POWER_MANAGEMENT_1, WM8400_OUT4_ENA_SHIFT, - 0, &wm8400_dapm_out4mix_controls[0], - ARRAY_SIZE(wm8400_dapm_out4mix_controls)), - -/* ROPMIX */ -SND_SOC_DAPM_MIXER("ROPMIX", WM8400_POWER_MANAGEMENT_3, WM8400_ROP_ENA_SHIFT, - 0, &wm8400_dapm_ropmix_controls[0], - ARRAY_SIZE(wm8400_dapm_ropmix_controls)), - -/* RONMIX */ -SND_SOC_DAPM_MIXER("RONMIX", WM8400_POWER_MANAGEMENT_3, WM8400_RON_ENA_SHIFT, - 0, &wm8400_dapm_ronmix_controls[0], - ARRAY_SIZE(wm8400_dapm_ronmix_controls)), - -/* ROMIX */ -SND_SOC_DAPM_MIXER_E("ROMIX", WM8400_POWER_MANAGEMENT_3, - WM8400_ROMIX_ENA_SHIFT, - 0, &wm8400_dapm_romix_controls[0], - ARRAY_SIZE(wm8400_dapm_romix_controls), - outmixer_event, SND_SOC_DAPM_PRE_REG), - -/* LOUT PGA */ -SND_SOC_DAPM_PGA("LOUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_LOUT_ENA_SHIFT, - 0, NULL, 0), - -/* ROUT PGA */ -SND_SOC_DAPM_PGA("ROUT PGA", WM8400_POWER_MANAGEMENT_1, WM8400_ROUT_ENA_SHIFT, - 0, NULL, 0), - -/* LOPGA */ -SND_SOC_DAPM_PGA("LOPGA", WM8400_POWER_MANAGEMENT_3, WM8400_LOPGA_ENA_SHIFT, 0, - NULL, 0), - -/* ROPGA */ -SND_SOC_DAPM_PGA("ROPGA", WM8400_POWER_MANAGEMENT_3, WM8400_ROPGA_ENA_SHIFT, 0, - NULL, 0), - -/* MICBIAS */ -SND_SOC_DAPM_MICBIAS("MICBIAS", WM8400_POWER_MANAGEMENT_1, - WM8400_MIC1BIAS_ENA_SHIFT, 0), - -SND_SOC_DAPM_OUTPUT("LON"), -SND_SOC_DAPM_OUTPUT("LOP"), -SND_SOC_DAPM_OUTPUT("OUT3"), -SND_SOC_DAPM_OUTPUT("LOUT"), -SND_SOC_DAPM_OUTPUT("SPKN"), -SND_SOC_DAPM_OUTPUT("SPKP"), -SND_SOC_DAPM_OUTPUT("ROUT"), -SND_SOC_DAPM_OUTPUT("OUT4"), -SND_SOC_DAPM_OUTPUT("ROP"), -SND_SOC_DAPM_OUTPUT("RON"), - -SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* Make DACs turn on when playing even if not mixed into any outputs */ - {"Internal DAC Sink", NULL, "Left DAC"}, - {"Internal DAC Sink", NULL, "Right DAC"}, - - /* Make ADCs turn on when recording - * even if not mixed from any inputs */ - {"Left ADC", NULL, "Internal ADC Source"}, - {"Right ADC", NULL, "Internal ADC Source"}, - - /* Input Side */ - /* LIN12 PGA */ - {"LIN12 PGA", "LIN1 Switch", "LIN1"}, - {"LIN12 PGA", "LIN2 Switch", "LIN2"}, - /* LIN34 PGA */ - {"LIN34 PGA", "LIN3 Switch", "LIN3"}, - {"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"}, - /* INMIXL */ - {"INMIXL", "Record Left Volume", "LOMIX"}, - {"INMIXL", "LIN2 Volume", "LIN2"}, - {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"}, - {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"}, - /* AILNMUX */ - {"AILNMUX", "INMIXL Mix", "INMIXL"}, - {"AILNMUX", "DIFFINL Mix", "LIN12 PGA"}, - {"AILNMUX", "DIFFINL Mix", "LIN34 PGA"}, - {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"}, - {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"}, - /* ADC */ - {"Left ADC", NULL, "AILNMUX"}, - - /* RIN12 PGA */ - {"RIN12 PGA", "RIN1 Switch", "RIN1"}, - {"RIN12 PGA", "RIN2 Switch", "RIN2"}, - /* RIN34 PGA */ - {"RIN34 PGA", "RIN3 Switch", "RIN3"}, - {"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"}, - /* INMIXL */ - {"INMIXR", "Record Right Volume", "ROMIX"}, - {"INMIXR", "RIN2 Volume", "RIN2"}, - {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"}, - {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"}, - /* AIRNMUX */ - {"AIRNMUX", "INMIXR Mix", "INMIXR"}, - {"AIRNMUX", "DIFFINR Mix", "RIN12 PGA"}, - {"AIRNMUX", "DIFFINR Mix", "RIN34 PGA"}, - {"AIRNMUX", "RXVOICE Mix", "LIN4/RXN"}, - {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"}, - /* ADC */ - {"Right ADC", NULL, "AIRNMUX"}, - - /* LOMIX */ - {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"}, - {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"}, - {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, - {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, - {"LOMIX", "LOMIX Right ADC Bypass Switch", "AIRNMUX"}, - {"LOMIX", "LOMIX Left ADC Bypass Switch", "AILNMUX"}, - {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"}, - - /* ROMIX */ - {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"}, - {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"}, - {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, - {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, - {"ROMIX", "ROMIX Right ADC Bypass Switch", "AIRNMUX"}, - {"ROMIX", "ROMIX Left ADC Bypass Switch", "AILNMUX"}, - {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"}, - - /* SPKMIX */ - {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"}, - {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"}, - {"SPKMIX", "SPKMIX LADC Bypass Switch", "AILNMUX"}, - {"SPKMIX", "SPKMIX RADC Bypass Switch", "AIRNMUX"}, - {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"}, - {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"}, - {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"}, - {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"}, - - /* LONMIX */ - {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"}, - {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"}, - {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"}, - - /* LOPMIX */ - {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"}, - {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"}, - {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"}, - - /* OUT3MIX */ - {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXN"}, - {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"}, - - /* OUT4MIX */ - {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"}, - {"OUT4MIX", "OUT4MIX RIN4/RXP Bypass Switch", "RIN4/RXP"}, - - /* RONMIX */ - {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"}, - {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"}, - {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"}, - - /* ROPMIX */ - {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"}, - {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"}, - {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"}, - - /* Out Mixer PGAs */ - {"LOPGA", NULL, "LOMIX"}, - {"ROPGA", NULL, "ROMIX"}, - - {"LOUT PGA", NULL, "LOMIX"}, - {"ROUT PGA", NULL, "ROMIX"}, - - /* Output Pins */ - {"LON", NULL, "LONMIX"}, - {"LOP", NULL, "LOPMIX"}, - {"OUT3", NULL, "OUT3MIX"}, - {"LOUT", NULL, "LOUT PGA"}, - {"SPKN", NULL, "SPKMIX"}, - {"ROUT", NULL, "ROUT PGA"}, - {"OUT4", NULL, "OUT4MIX"}, - {"ROP", NULL, "ROPMIX"}, - {"RON", NULL, "RONMIX"}, -}; - -static int wm8400_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, wm8400_dapm_widgets, - ARRAY_SIZE(wm8400_dapm_widgets)); - - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - - snd_soc_dapm_new_widgets(codec); - return 0; -} - -/* - * Clock after FLL and dividers - */ -static int wm8400_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8400_priv *wm8400 = codec->private_data; - - wm8400->sysclk = freq; - return 0; -} - -/* - * Sets ADC and Voice DAC format. - */ -static int wm8400_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 audio1, audio3; - - audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); - audio3 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_3); - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - audio3 &= ~WM8400_AIF_MSTR1; - break; - case SND_SOC_DAIFMT_CBM_CFM: - audio3 |= WM8400_AIF_MSTR1; - break; - default: - return -EINVAL; - } - - audio1 &= ~WM8400_AIF_FMT_MASK; - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - audio1 |= WM8400_AIF_FMT_I2S; - audio1 &= ~WM8400_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_RIGHT_J: - audio1 |= WM8400_AIF_FMT_RIGHTJ; - audio1 &= ~WM8400_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_LEFT_J: - audio1 |= WM8400_AIF_FMT_LEFTJ; - audio1 &= ~WM8400_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_DSP_A: - audio1 |= WM8400_AIF_FMT_DSP; - audio1 &= ~WM8400_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_DSP_B: - audio1 |= WM8400_AIF_FMT_DSP | WM8400_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - - wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1); - wm8400_write(codec, WM8400_AUDIO_INTERFACE_3, audio3); - return 0; -} - -static int wm8400_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - switch (div_id) { - case WM8400_MCLK_DIV: - reg = wm8400_read(codec, WM8400_CLOCKING_2) & - ~WM8400_MCLK_DIV_MASK; - wm8400_write(codec, WM8400_CLOCKING_2, reg | div); - break; - case WM8400_DACCLK_DIV: - reg = wm8400_read(codec, WM8400_CLOCKING_2) & - ~WM8400_DAC_CLKDIV_MASK; - wm8400_write(codec, WM8400_CLOCKING_2, reg | div); - break; - case WM8400_ADCCLK_DIV: - reg = wm8400_read(codec, WM8400_CLOCKING_2) & - ~WM8400_ADC_CLKDIV_MASK; - wm8400_write(codec, WM8400_CLOCKING_2, reg | div); - break; - case WM8400_BCLK_DIV: - reg = wm8400_read(codec, WM8400_CLOCKING_1) & - ~WM8400_BCLK_DIV_MASK; - wm8400_write(codec, WM8400_CLOCKING_1, reg | div); - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * Set PCM DAI bit size and sample rate. - */ -static int wm8400_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); - - audio1 &= ~WM8400_AIF_WL_MASK; - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - audio1 |= WM8400_AIF_WL_20BITS; - break; - case SNDRV_PCM_FORMAT_S24_LE: - audio1 |= WM8400_AIF_WL_24BITS; - break; - case SNDRV_PCM_FORMAT_S32_LE: - audio1 |= WM8400_AIF_WL_32BITS; - break; - } - - wm8400_write(codec, WM8400_AUDIO_INTERFACE_1, audio1); - return 0; -} - -static int wm8400_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 val = wm8400_read(codec, WM8400_DAC_CTRL) & ~WM8400_DAC_MUTE; - - if (mute) - wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); - else - wm8400_write(codec, WM8400_DAC_CTRL, val); - - return 0; -} - -/* TODO: set bias for best performance at standby */ -static int wm8400_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8400_priv *wm8400 = codec->private_data; - u16 val; - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* VMID=2*50k */ - val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) & - ~WM8400_VMID_MODE_MASK; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x2); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(power), - &power[0]); - if (ret != 0) { - dev_err(wm8400->wm8400->dev, - "Failed to enable regulators: %d\n", - ret); - return ret; - } - - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, - WM8400_CODEC_ENA | WM8400_SYSCLK_ENA); - - /* Enable all output discharge bits */ - wm8400_write(codec, WM8400_ANTIPOP1, WM8400_DIS_LLINE | - WM8400_DIS_RLINE | WM8400_DIS_OUT3 | - WM8400_DIS_OUT4 | WM8400_DIS_LOUT | - WM8400_DIS_ROUT); - - /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ - wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | - WM8400_BUFDCOPEN | WM8400_POBCTRL); - - msleep(500); - - /* Enable outputs */ - val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); - val |= WM8400_SPK_ENA | WM8400_OUT3_ENA | - WM8400_OUT4_ENA | WM8400_LOUT_ENA | - WM8400_ROUT_ENA; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - /* disable all output discharge bits */ - wm8400_write(codec, WM8400_ANTIPOP1, 0); - - /* Enable VREF & VMID at 2x50k */ - val |= 0x2 | WM8400_VREF_ENA; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - msleep(600); - - /* Enable BUFIOEN */ - wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | - WM8400_BUFDCOPEN | WM8400_POBCTRL | - WM8400_BUFIOEN); - - /* Disable outputs */ - val &= ~(WM8400_SPK_ENA | WM8400_OUT3_ENA | - WM8400_OUT4_ENA | WM8400_LOUT_ENA | - WM8400_ROUT_ENA); - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ - wm8400_write(codec, WM8400_ANTIPOP2, WM8400_BUFIOEN); - } - - /* VMID=2*300k */ - val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1) & - ~WM8400_VMID_MODE_MASK; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val | 0x4); - break; - - case SND_SOC_BIAS_OFF: - /* Enable POBCTRL and SOFT_ST */ - wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | - WM8400_POBCTRL | WM8400_BUFIOEN); - - /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ - wm8400_write(codec, WM8400_ANTIPOP2, WM8400_SOFTST | - WM8400_BUFDCOPEN | WM8400_POBCTRL | - WM8400_BUFIOEN); - - /* mute DAC */ - val = wm8400_read(codec, WM8400_DAC_CTRL); - wm8400_write(codec, WM8400_DAC_CTRL, val | WM8400_DAC_MUTE); - - /* Enable any disabled outputs */ - val = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); - val |= WM8400_SPK_ENA | WM8400_OUT3_ENA | - WM8400_OUT4_ENA | WM8400_LOUT_ENA | - WM8400_ROUT_ENA; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - /* Disable VMID */ - val &= ~WM8400_VMID_MODE_MASK; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - msleep(300); - - /* Enable all output discharge bits */ - wm8400_write(codec, WM8400_ANTIPOP1, WM8400_DIS_LLINE | - WM8400_DIS_RLINE | WM8400_DIS_OUT3 | - WM8400_DIS_OUT4 | WM8400_DIS_LOUT | - WM8400_DIS_ROUT); - - /* Disable VREF */ - val &= ~WM8400_VREF_ENA; - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, val); - - /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ - wm8400_write(codec, WM8400_ANTIPOP2, 0x0); - - ret = regulator_bulk_disable(ARRAY_SIZE(power), - &power[0]); - if (ret != 0) - return ret; - - break; - } - - codec->bias_level = level; - return 0; -} - -#define WM8400_RATES SNDRV_PCM_RATE_8000_96000 - -#define WM8400_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -/* - * The WM8400 supports 2 different and mutually exclusive DAI - * configurations. - * - * 1. ADC/DAC on Primary Interface - * 2. ADC on Primary Interface/DAC on secondary - */ -struct snd_soc_dai wm8400_dai = { -/* ADC/DAC on primary */ - .name = "WM8400 ADC/DAC Primary", - .id = 1, - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8400_RATES, - .formats = WM8400_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8400_RATES, - .formats = WM8400_FORMATS, - }, - .ops = { - .hw_params = wm8400_hw_params, - .digital_mute = wm8400_mute, - .set_fmt = wm8400_set_dai_fmt, - .set_clkdiv = wm8400_set_dai_clkdiv, - .set_sysclk = wm8400_set_dai_sysclk, - }, -}; -EXPORT_SYMBOL_GPL(wm8400_dai); - -static int wm8400_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8400_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} - -static struct snd_soc_codec *wm8400_codec; - -static int wm8400_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret; - - if (!wm8400_codec) { - dev_err(&pdev->dev, "wm8400 not yet discovered\n"); - return -ENODEV; - } - codec = wm8400_codec; - - socdev->card->codec = codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "failed to create pcms\n"); - goto pcm_err; - } - - wm8400_add_controls(codec); - wm8400_add_widgets(codec); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register card\n"); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -/* power down chip */ -static int wm8400_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8400 = { - .probe = wm8400_probe, - .remove = wm8400_remove, - .suspend = wm8400_suspend, - .resume = wm8400_resume, -}; - -static void wm8400_probe_deferred(struct work_struct *work) -{ - struct wm8400_priv *priv = container_of(work, struct wm8400_priv, - work); - struct snd_soc_codec *codec = &priv->codec; - int ret; - - /* charge output caps */ - wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* We're done, tell the subsystem. */ - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(priv->wm8400->dev, - "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&wm8400_dai); - if (ret != 0) { - dev_err(priv->wm8400->dev, - "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return; - -err_codec: - snd_soc_unregister_codec(codec); -err: - wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); -} - -static int wm8400_codec_probe(struct platform_device *dev) -{ - struct wm8400_priv *priv; - int ret; - u16 reg; - struct snd_soc_codec *codec; - - priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - - codec = &priv->codec; - codec->private_data = priv; - codec->control_data = dev->dev.driver_data; - priv->wm8400 = dev->dev.driver_data; - - ret = regulator_bulk_get(priv->wm8400->dev, - ARRAY_SIZE(power), &power[0]); - if (ret != 0) { - dev_err(&dev->dev, "Failed to get regulators: %d\n", ret); - goto err; - } - - codec->dev = &dev->dev; - wm8400_dai.dev = &dev->dev; - - codec->name = "WM8400"; - codec->owner = THIS_MODULE; - codec->read = wm8400_read; - codec->write = wm8400_write; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8400_set_bias_level; - codec->dai = &wm8400_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8400_REGISTER_COUNT; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - INIT_WORK(&priv->work, wm8400_probe_deferred); - - wm8400_codec_reset(codec); - - reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1); - wm8400_write(codec, WM8400_POWER_MANAGEMENT_1, reg | WM8400_CODEC_ENA); - - /* Latch volume update bits */ - reg = wm8400_read(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME); - wm8400_write(codec, WM8400_LEFT_LINE_INPUT_1_2_VOLUME, - reg & WM8400_IPVU); - reg = wm8400_read(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME); - wm8400_write(codec, WM8400_RIGHT_LINE_INPUT_1_2_VOLUME, - reg & WM8400_IPVU); - - wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); - wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); - - wm8400_codec = codec; - - if (!schedule_work(&priv->work)) { - ret = -EINVAL; - goto err_regulator; - } - - return 0; - -err_regulator: - wm8400_codec = NULL; - regulator_bulk_free(ARRAY_SIZE(power), power); -err: - kfree(priv); - return ret; -} - -static int __exit wm8400_codec_remove(struct platform_device *dev) -{ - struct wm8400_priv *priv = wm8400_codec->private_data; - u16 reg; - - snd_soc_unregister_dai(&wm8400_dai); - snd_soc_unregister_codec(wm8400_codec); - - reg = wm8400_read(wm8400_codec, WM8400_POWER_MANAGEMENT_1); - wm8400_write(wm8400_codec, WM8400_POWER_MANAGEMENT_1, - reg & (~WM8400_CODEC_ENA)); - - regulator_bulk_free(ARRAY_SIZE(power), power); - kfree(priv); - - wm8400_codec = NULL; - - return 0; -} - -static struct platform_driver wm8400_codec_driver = { - .driver = { - .name = "wm8400-codec", - .owner = THIS_MODULE, - }, - .probe = wm8400_codec_probe, - .remove = __exit_p(wm8400_codec_remove), -}; - -static int __init wm8400_codec_init(void) -{ - return platform_driver_register(&wm8400_codec_driver); -} -module_init(wm8400_codec_init); - -static void __exit wm8400_codec_exit(void) -{ - platform_driver_unregister(&wm8400_codec_driver); -} -module_exit(wm8400_codec_exit); - -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400); - -MODULE_DESCRIPTION("ASoC WM8400 driver"); -MODULE_AUTHOR("Mark Brown"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:wm8400-codec"); diff --git a/trunk/sound/soc/codecs/wm8400.h b/trunk/sound/soc/codecs/wm8400.h deleted file mode 100644 index 79c5934d4776..000000000000 --- a/trunk/sound/soc/codecs/wm8400.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * wm8400.h -- audio driver for WM8400 - * - * Copyright 2008 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#ifndef _WM8400_CODEC_H -#define _WM8400_CODEC_H - -#define WM8400_MCLK_DIV 0 -#define WM8400_DACCLK_DIV 1 -#define WM8400_ADCCLK_DIV 2 -#define WM8400_BCLK_DIV 3 - -#define WM8400_MCLK_DIV_1 0x400 -#define WM8400_MCLK_DIV_2 0x800 - -#define WM8400_DAC_CLKDIV_1 0x00 -#define WM8400_DAC_CLKDIV_1_5 0x04 -#define WM8400_DAC_CLKDIV_2 0x08 -#define WM8400_DAC_CLKDIV_3 0x0c -#define WM8400_DAC_CLKDIV_4 0x10 -#define WM8400_DAC_CLKDIV_5_5 0x14 -#define WM8400_DAC_CLKDIV_6 0x18 - -#define WM8400_ADC_CLKDIV_1 0x00 -#define WM8400_ADC_CLKDIV_1_5 0x20 -#define WM8400_ADC_CLKDIV_2 0x40 -#define WM8400_ADC_CLKDIV_3 0x60 -#define WM8400_ADC_CLKDIV_4 0x80 -#define WM8400_ADC_CLKDIV_5_5 0xa0 -#define WM8400_ADC_CLKDIV_6 0xc0 - - -#define WM8400_BCLK_DIV_1 (0x0 << 1) -#define WM8400_BCLK_DIV_1_5 (0x1 << 1) -#define WM8400_BCLK_DIV_2 (0x2 << 1) -#define WM8400_BCLK_DIV_3 (0x3 << 1) -#define WM8400_BCLK_DIV_4 (0x4 << 1) -#define WM8400_BCLK_DIV_5_5 (0x5 << 1) -#define WM8400_BCLK_DIV_6 (0x6 << 1) -#define WM8400_BCLK_DIV_8 (0x7 << 1) -#define WM8400_BCLK_DIV_11 (0x8 << 1) -#define WM8400_BCLK_DIV_12 (0x9 << 1) -#define WM8400_BCLK_DIV_16 (0xA << 1) -#define WM8400_BCLK_DIV_22 (0xB << 1) -#define WM8400_BCLK_DIV_24 (0xC << 1) -#define WM8400_BCLK_DIV_32 (0xD << 1) -#define WM8400_BCLK_DIV_44 (0xE << 1) -#define WM8400_BCLK_DIV_48 (0xF << 1) - -extern struct snd_soc_dai wm8400_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8400; - -#endif diff --git a/trunk/sound/soc/codecs/wm8510.c b/trunk/sound/soc/codecs/wm8510.c index 6d4ef71e9195..cc975a62fa5c 100644 --- a/trunk/sound/soc/codecs/wm8510.c +++ b/trunk/sound/soc/codecs/wm8510.c @@ -336,7 +336,7 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, return 0; } - pll_factors(freq_out*4, freq_in); + pll_factors(freq_out*8, freq_in); wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18); @@ -367,7 +367,7 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai, wm8510_write(codec, WM8510_GPIO, reg | div); break; case WM8510_MCLKDIV: - reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x11f; + reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1f; wm8510_write(codec, WM8510_CLOCK, reg | div); break; case WM8510_ADCCLK: @@ -554,6 +554,14 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, #define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) +static struct snd_soc_dai_ops wm8510_dai_ops = { + .hw_params = wm8510_pcm_hw_params, + .digital_mute = wm8510_mute, + .set_fmt = wm8510_set_dai_fmt, + .set_clkdiv = wm8510_set_dai_clkdiv, + .set_pll = wm8510_set_dai_pll, +}; + struct snd_soc_dai wm8510_dai = { .name = "WM8510 HiFi", .playback = { @@ -568,13 +576,7 @@ struct snd_soc_dai wm8510_dai = { .channels_max = 2, .rates = WM8510_RATES, .formats = WM8510_FORMATS,}, - .ops = { - .hw_params = wm8510_pcm_hw_params, - .digital_mute = wm8510_mute, - .set_fmt = wm8510_set_dai_fmt, - .set_clkdiv = wm8510_set_dai_clkdiv, - .set_pll = wm8510_set_dai_pll, - }, + .ops = &wm8510_dai_ops, }; EXPORT_SYMBOL_GPL(wm8510_dai); diff --git a/trunk/sound/soc/codecs/wm8580.c b/trunk/sound/soc/codecs/wm8580.c index 6cab82a9c9d7..ee0af23a1acc 100644 --- a/trunk/sound/soc/codecs/wm8580.c +++ b/trunk/sound/soc/codecs/wm8580.c @@ -35,6 +35,8 @@ #include "wm8580.h" +#define WM8580_VERSION "0.1" + struct pll_state { unsigned int in; unsigned int out; @@ -769,6 +771,21 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, #define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) +static struct snd_soc_dai_ops wm8580_dai_ops_playback = { + .hw_params = wm8580_paif_hw_params, + .set_fmt = wm8580_set_paif_dai_fmt, + .set_clkdiv = wm8580_set_dai_clkdiv, + .set_pll = wm8580_set_dai_pll, + .digital_mute = wm8580_digital_mute, +}; + +static struct snd_soc_dai_ops wm8580_dai_ops_capture = { + .hw_params = wm8580_paif_hw_params, + .set_fmt = wm8580_set_paif_dai_fmt, + .set_clkdiv = wm8580_set_dai_clkdiv, + .set_pll = wm8580_set_dai_pll, +}; + struct snd_soc_dai wm8580_dai[] = { { .name = "WM8580 PAIFRX", @@ -780,13 +797,7 @@ struct snd_soc_dai wm8580_dai[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = WM8580_FORMATS, }, - .ops = { - .hw_params = wm8580_paif_hw_params, - .set_fmt = wm8580_set_paif_dai_fmt, - .set_clkdiv = wm8580_set_dai_clkdiv, - .set_pll = wm8580_set_dai_pll, - .digital_mute = wm8580_digital_mute, - }, + .ops = &wm8580_dai_ops_playback, }, { .name = "WM8580 PAIFTX", @@ -798,12 +809,7 @@ struct snd_soc_dai wm8580_dai[] = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = WM8580_FORMATS, }, - .ops = { - .hw_params = wm8580_paif_hw_params, - .set_fmt = wm8580_set_paif_dai_fmt, - .set_clkdiv = wm8580_set_dai_clkdiv, - .set_pll = wm8580_set_dai_pll, - }, + .ops = &wm8580_dai_ops_capture, }, }; EXPORT_SYMBOL_GPL(wm8580_dai); @@ -970,6 +976,8 @@ static int wm8580_probe(struct platform_device *pdev) struct wm8580_priv *wm8580; int ret = 0; + pr_info("WM8580 Audio Codec %s\n", WM8580_VERSION); + setup = socdev->codec_data; codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); if (codec == NULL) diff --git a/trunk/sound/soc/codecs/wm8728.c b/trunk/sound/soc/codecs/wm8728.c index f8363b308895..e7ff2121ede9 100644 --- a/trunk/sound/soc/codecs/wm8728.c +++ b/trunk/sound/soc/codecs/wm8728.c @@ -244,6 +244,12 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, #define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) +static struct snd_soc_dai_ops wm8728_dai_ops = { + .hw_params = wm8728_hw_params, + .digital_mute = wm8728_mute, + .set_fmt = wm8728_set_dai_fmt, +}; + struct snd_soc_dai wm8728_dai = { .name = "WM8728", .playback = { @@ -253,11 +259,7 @@ struct snd_soc_dai wm8728_dai = { .rates = WM8728_RATES, .formats = WM8728_FORMATS, }, - .ops = { - .hw_params = wm8728_hw_params, - .digital_mute = wm8728_mute, - .set_fmt = wm8728_set_dai_fmt, - } + .ops = &wm8728_dai_ops, }; EXPORT_SYMBOL_GPL(wm8728_dai); diff --git a/trunk/sound/soc/codecs/wm8731.c b/trunk/sound/soc/codecs/wm8731.c index 9e7ebcc2c491..e043e3f60008 100644 --- a/trunk/sound/soc/codecs/wm8731.c +++ b/trunk/sound/soc/codecs/wm8731.c @@ -433,6 +433,15 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) +static struct snd_soc_dai_ops wm8731_dai_ops = { + .prepare = wm8731_pcm_prepare, + .hw_params = wm8731_hw_params, + .shutdown = wm8731_shutdown, + .digital_mute = wm8731_mute, + .set_sysclk = wm8731_set_dai_sysclk, + .set_fmt = wm8731_set_dai_fmt, +}; + struct snd_soc_dai wm8731_dai = { .name = "WM8731", .playback = { @@ -447,14 +456,7 @@ struct snd_soc_dai wm8731_dai = { .channels_max = 2, .rates = WM8731_RATES, .formats = WM8731_FORMATS,}, - .ops = { - .prepare = wm8731_pcm_prepare, - .hw_params = wm8731_hw_params, - .shutdown = wm8731_shutdown, - .digital_mute = wm8731_mute, - .set_sysclk = wm8731_set_dai_sysclk, - .set_fmt = wm8731_set_dai_fmt, - } + .ops = &wm8731_dai_ops, }; EXPORT_SYMBOL_GPL(wm8731_dai); diff --git a/trunk/sound/soc/codecs/wm8750.c b/trunk/sound/soc/codecs/wm8750.c index 96afb86addc6..b64509b01a49 100644 --- a/trunk/sound/soc/codecs/wm8750.c +++ b/trunk/sound/soc/codecs/wm8750.c @@ -679,6 +679,13 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec, #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) +static struct snd_soc_dai_ops wm8750_dai_ops = { + .hw_params = wm8750_pcm_hw_params, + .digital_mute = wm8750_mute, + .set_fmt = wm8750_set_dai_fmt, + .set_sysclk = wm8750_set_dai_sysclk, +}; + struct snd_soc_dai wm8750_dai = { .name = "WM8750", .playback = { @@ -693,12 +700,7 @@ struct snd_soc_dai wm8750_dai = { .channels_max = 2, .rates = WM8750_RATES, .formats = WM8750_FORMATS,}, - .ops = { - .hw_params = wm8750_pcm_hw_params, - .digital_mute = wm8750_mute, - .set_fmt = wm8750_set_dai_fmt, - .set_sysclk = wm8750_set_dai_sysclk, - }, + .ops = &wm8750_dai_ops, }; EXPORT_SYMBOL_GPL(wm8750_dai); diff --git a/trunk/sound/soc/codecs/wm8753.c b/trunk/sound/soc/codecs/wm8753.c index 1d5eca89de60..cc6e57f9acf8 100644 --- a/trunk/sound/soc/codecs/wm8753.c +++ b/trunk/sound/soc/codecs/wm8753.c @@ -51,6 +51,11 @@ #include "wm8753.h" +#ifdef CONFIG_SPI_MASTER +static struct spi_driver wm8753_spi_driver; +static int wm8753_spi_write(struct spi_device *spi, const char *data, int len); +#endif + static int caps_charge = 2000; module_param(caps_charge, int, 0); MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); @@ -1301,6 +1306,51 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, * 3. Voice disabled - HIFI over HIFI * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture */ +static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { + .hw_params = wm8753_i2s_hw_params, + .digital_mute = wm8753_mute, + .set_fmt = wm8753_mode1h_set_dai_fmt, + .set_clkdiv = wm8753_set_dai_clkdiv, + .set_pll = wm8753_set_dai_pll, + .set_sysclk = wm8753_set_dai_sysclk, +}; + +static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { + .hw_params = wm8753_pcm_hw_params, + .digital_mute = wm8753_mute, + .set_fmt = wm8753_mode1v_set_dai_fmt, + .set_clkdiv = wm8753_set_dai_clkdiv, + .set_pll = wm8753_set_dai_pll, + .set_sysclk = wm8753_set_dai_sysclk, +}; + +static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { + .hw_params = wm8753_pcm_hw_params, + .digital_mute = wm8753_mute, + .set_fmt = wm8753_mode2_set_dai_fmt, + .set_clkdiv = wm8753_set_dai_clkdiv, + .set_pll = wm8753_set_dai_pll, + .set_sysclk = wm8753_set_dai_sysclk, +}; + +static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { + .hw_params = wm8753_i2s_hw_params, + .digital_mute = wm8753_mute, + .set_fmt = wm8753_mode3_4_set_dai_fmt, + .set_clkdiv = wm8753_set_dai_clkdiv, + .set_pll = wm8753_set_dai_pll, + .set_sysclk = wm8753_set_dai_sysclk, +}; + +static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { + .hw_params = wm8753_i2s_hw_params, + .digital_mute = wm8753_mute, + .set_fmt = wm8753_mode3_4_set_dai_fmt, + .set_clkdiv = wm8753_set_dai_clkdiv, + .set_pll = wm8753_set_dai_pll, + .set_sysclk = wm8753_set_dai_sysclk, +}; + static const struct snd_soc_dai wm8753_all_dai[] = { /* DAI HiFi mode 1 */ { .name = "WM8753 HiFi", @@ -1317,14 +1367,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { .channels_max = 2, .rates = WM8753_RATES, .formats = WM8753_FORMATS}, - .ops = { - .hw_params = wm8753_i2s_hw_params, - .digital_mute = wm8753_mute, - .set_fmt = wm8753_mode1h_set_dai_fmt, - .set_clkdiv = wm8753_set_dai_clkdiv, - .set_pll = wm8753_set_dai_pll, - .set_sysclk = wm8753_set_dai_sysclk, - }, + .ops = &wm8753_dai_ops_hifi_mode1, }, /* DAI Voice mode 1 */ { .name = "WM8753 Voice", @@ -1341,14 +1384,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { .channels_max = 2, .rates = WM8753_RATES, .formats = WM8753_FORMATS,}, - .ops = { - .hw_params = wm8753_pcm_hw_params, - .digital_mute = wm8753_mute, - .set_fmt = wm8753_mode1v_set_dai_fmt, - .set_clkdiv = wm8753_set_dai_clkdiv, - .set_pll = wm8753_set_dai_pll, - .set_sysclk = wm8753_set_dai_sysclk, - }, + .ops = &wm8753_dai_ops_voice_mode1, }, /* DAI HiFi mode 2 - dummy */ { .name = "WM8753 HiFi", @@ -1369,14 +1405,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { .channels_max = 2, .rates = WM8753_RATES, .formats = WM8753_FORMATS,}, - .ops = { - .hw_params = wm8753_pcm_hw_params, - .digital_mute = wm8753_mute, - .set_fmt = wm8753_mode2_set_dai_fmt, - .set_clkdiv = wm8753_set_dai_clkdiv, - .set_pll = wm8753_set_dai_pll, - .set_sysclk = wm8753_set_dai_sysclk, - }, + .ops = &wm8753_dai_ops_voice_mode2, }, /* DAI HiFi mode 3 */ { .name = "WM8753 HiFi", @@ -1393,14 +1422,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { .channels_max = 2, .rates = WM8753_RATES, .formats = WM8753_FORMATS,}, - .ops = { - .hw_params = wm8753_i2s_hw_params, - .digital_mute = wm8753_mute, - .set_fmt = wm8753_mode3_4_set_dai_fmt, - .set_clkdiv = wm8753_set_dai_clkdiv, - .set_pll = wm8753_set_dai_pll, - .set_sysclk = wm8753_set_dai_sysclk, - }, + .ops = &wm8753_dai_ops_hifi_mode3, }, /* DAI Voice mode 3 - dummy */ { .name = "WM8753 Voice", @@ -1421,14 +1443,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { .channels_max = 2, .rates = WM8753_RATES, .formats = WM8753_FORMATS,}, - .ops = { - .hw_params = wm8753_i2s_hw_params, - .digital_mute = wm8753_mute, - .set_fmt = wm8753_mode3_4_set_dai_fmt, - .set_clkdiv = wm8753_set_dai_clkdiv, - .set_pll = wm8753_set_dai_pll, - .set_sysclk = wm8753_set_dai_sysclk, - }, + .ops = &wm8753_dai_ops_hifi_mode4, }, /* DAI Voice mode 4 - dummy */ { .name = "WM8753 Voice", diff --git a/trunk/sound/soc/codecs/wm8900.c b/trunk/sound/soc/codecs/wm8900.c index da5ca64f89bb..46c5ea1ff921 100644 --- a/trunk/sound/soc/codecs/wm8900.c +++ b/trunk/sound/soc/codecs/wm8900.c @@ -1088,6 +1088,14 @@ static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute) (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ SNDRV_PCM_FORMAT_S24_LE) +static struct snd_soc_dai_ops wm8900_dai_ops = { + .hw_params = wm8900_hw_params, + .set_clkdiv = wm8900_set_dai_clkdiv, + .set_pll = wm8900_set_dai_pll, + .set_fmt = wm8900_set_dai_fmt, + .digital_mute = wm8900_digital_mute, +}; + struct snd_soc_dai wm8900_dai = { .name = "WM8900 HiFi", .playback = { @@ -1104,13 +1112,7 @@ struct snd_soc_dai wm8900_dai = { .rates = WM8900_RATES, .formats = WM8900_PCM_FORMATS, }, - .ops = { - .hw_params = wm8900_hw_params, - .set_clkdiv = wm8900_set_dai_clkdiv, - .set_pll = wm8900_set_dai_pll, - .set_fmt = wm8900_set_dai_fmt, - .digital_mute = wm8900_digital_mute, - }, + .ops = &wm8900_dai_ops, }; EXPORT_SYMBOL_GPL(wm8900_dai); diff --git a/trunk/sound/soc/codecs/wm8903.c b/trunk/sound/soc/codecs/wm8903.c index c6fa8a71b4dd..8cf571f1a803 100644 --- a/trunk/sound/soc/codecs/wm8903.c +++ b/trunk/sound/soc/codecs/wm8903.c @@ -1497,6 +1497,15 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) +static struct snd_soc_dai_ops wm8903_dai_ops = { + .startup = wm8903_startup, + .shutdown = wm8903_shutdown, + .hw_params = wm8903_hw_params, + .digital_mute = wm8903_digital_mute, + .set_fmt = wm8903_set_dai_fmt, + .set_sysclk = wm8903_set_dai_sysclk, +}; + struct snd_soc_dai wm8903_dai = { .name = "WM8903", .playback = { @@ -1513,14 +1522,7 @@ struct snd_soc_dai wm8903_dai = { .rates = WM8903_CAPTURE_RATES, .formats = WM8903_FORMATS, }, - .ops = { - .startup = wm8903_startup, - .shutdown = wm8903_shutdown, - .hw_params = wm8903_hw_params, - .digital_mute = wm8903_digital_mute, - .set_fmt = wm8903_set_dai_fmt, - .set_sysclk = wm8903_set_dai_sysclk - } + .ops = &wm8903_dai_ops, }; EXPORT_SYMBOL_GPL(wm8903_dai); diff --git a/trunk/sound/soc/codecs/wm8971.c b/trunk/sound/soc/codecs/wm8971.c index 24d4c905a011..032dca22dbd3 100644 --- a/trunk/sound/soc/codecs/wm8971.c +++ b/trunk/sound/soc/codecs/wm8971.c @@ -604,6 +604,13 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec, #define WM8971_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE) +static struct snd_soc_dai_ops wm8971_dai_ops = { + .hw_params = wm8971_pcm_hw_params, + .digital_mute = wm8971_mute, + .set_fmt = wm8971_set_dai_fmt, + .set_sysclk = wm8971_set_dai_sysclk, +}; + struct snd_soc_dai wm8971_dai = { .name = "WM8971", .playback = { @@ -618,12 +625,7 @@ struct snd_soc_dai wm8971_dai = { .channels_max = 2, .rates = WM8971_RATES, .formats = WM8971_FORMATS,}, - .ops = { - .hw_params = wm8971_pcm_hw_params, - .digital_mute = wm8971_mute, - .set_fmt = wm8971_set_dai_fmt, - .set_sysclk = wm8971_set_dai_sysclk, - }, + .ops = &wm8971_dai_ops, }; EXPORT_SYMBOL_GPL(wm8971_dai); diff --git a/trunk/sound/soc/codecs/wm8990.c b/trunk/sound/soc/codecs/wm8990.c index 1a38421f7594..c518c3e5aa3f 100644 --- a/trunk/sound/soc/codecs/wm8990.c +++ b/trunk/sound/soc/codecs/wm8990.c @@ -1332,6 +1332,15 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, * 1. ADC/DAC on Primary Interface * 2. ADC on Primary Interface/DAC on secondary */ +static struct snd_soc_dai_ops wm8990_dai_ops = { + .hw_params = wm8990_hw_params, + .digital_mute = wm8990_mute, + .set_fmt = wm8990_set_dai_fmt, + .set_clkdiv = wm8990_set_dai_clkdiv, + .set_pll = wm8990_set_dai_pll, + .set_sysclk = wm8990_set_dai_sysclk, +}; + struct snd_soc_dai wm8990_dai = { /* ADC/DAC on primary */ .name = "WM8990 ADC/DAC Primary", @@ -1348,14 +1357,7 @@ struct snd_soc_dai wm8990_dai = { .channels_max = 2, .rates = WM8990_RATES, .formats = WM8990_FORMATS,}, - .ops = { - .hw_params = wm8990_hw_params, - .digital_mute = wm8990_mute, - .set_fmt = wm8990_set_dai_fmt, - .set_clkdiv = wm8990_set_dai_clkdiv, - .set_pll = wm8990_set_dai_pll, - .set_sysclk = wm8990_set_dai_sysclk, - }, + .ops = &wm8990_dai_ops, }; EXPORT_SYMBOL_GPL(wm8990_dai); diff --git a/trunk/sound/soc/codecs/wm9705.c b/trunk/sound/soc/codecs/wm9705.c index 2e9e06b2daaf..3265817c5c26 100644 --- a/trunk/sound/soc/codecs/wm9705.c +++ b/trunk/sound/soc/codecs/wm9705.c @@ -269,6 +269,10 @@ static int ac97_prepare(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) +static struct snd_soc_dai_ops wm9705_dai_ops = { + .prepare = ac97_prepare, +}; + struct snd_soc_dai wm9705_dai[] = { { .name = "AC97 HiFi", @@ -287,9 +291,7 @@ struct snd_soc_dai wm9705_dai[] = { .rates = WM9705_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = { - .prepare = ac97_prepare, - }, + .ops = &wm9705_dai_ops, }, { .name = "AC97 Aux", diff --git a/trunk/sound/soc/codecs/wm9712.c b/trunk/sound/soc/codecs/wm9712.c index b3a8be77676e..765cf1e7369e 100644 --- a/trunk/sound/soc/codecs/wm9712.c +++ b/trunk/sound/soc/codecs/wm9712.c @@ -517,6 +517,14 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ SNDRV_PCM_RATE_48000) +static struct snd_soc_dai_ops wm9712_dai_ops_hifi = { + .prepare = ac97_prepare, +}; + +static struct snd_soc_dai_ops wm9712_dai_ops_aux = { + .prepare = ac97_aux_prepare, +}; + struct snd_soc_dai wm9712_dai[] = { { .name = "AC97 HiFi", @@ -533,8 +541,7 @@ struct snd_soc_dai wm9712_dai[] = { .channels_max = 2, .rates = WM9712_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .prepare = ac97_prepare,}, + .ops = &wm9712_dai_ops_hifi, }, { .name = "AC97 Aux", @@ -544,8 +551,7 @@ struct snd_soc_dai wm9712_dai[] = { .channels_max = 1, .rates = WM9712_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .prepare = ac97_aux_prepare,}, + .ops = &wm9712_dai_ops_aux, } }; EXPORT_SYMBOL_GPL(wm9712_dai); diff --git a/trunk/sound/soc/codecs/wm9713.c b/trunk/sound/soc/codecs/wm9713.c index a93aea5c1878..523bad077fa0 100644 --- a/trunk/sound/soc/codecs/wm9713.c +++ b/trunk/sound/soc/codecs/wm9713.c @@ -1005,6 +1005,27 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream, (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ SNDRV_PCM_FORMAT_S24_LE) +static struct snd_soc_dai_ops wm9713_dai_ops_hifi = { + .prepare = ac97_hifi_prepare, + .set_clkdiv = wm9713_set_dai_clkdiv, + .set_pll = wm9713_set_dai_pll, +}; + +static struct snd_soc_dai_ops wm9713_dai_ops_aux = { + .prepare = ac97_aux_prepare, + .set_clkdiv = wm9713_set_dai_clkdiv, + .set_pll = wm9713_set_dai_pll, +}; + +static struct snd_soc_dai_ops wm9713_dai_ops_voice = { + .hw_params = wm9713_pcm_hw_params, + .shutdown = wm9713_voiceshutdown, + .set_clkdiv = wm9713_set_dai_clkdiv, + .set_pll = wm9713_set_dai_pll, + .set_fmt = wm9713_set_dai_fmt, + .set_tristate = wm9713_set_dai_tristate, +}; + struct snd_soc_dai wm9713_dai[] = { { .name = "AC97 HiFi", @@ -1021,10 +1042,7 @@ struct snd_soc_dai wm9713_dai[] = { .channels_max = 2, .rates = WM9713_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .prepare = ac97_hifi_prepare, - .set_clkdiv = wm9713_set_dai_clkdiv, - .set_pll = wm9713_set_dai_pll,}, + .ops = &wm9713_dai_ops_hifi, }, { .name = "AC97 Aux", @@ -1034,10 +1052,7 @@ struct snd_soc_dai wm9713_dai[] = { .channels_max = 1, .rates = WM9713_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .prepare = ac97_aux_prepare, - .set_clkdiv = wm9713_set_dai_clkdiv, - .set_pll = wm9713_set_dai_pll,}, + .ops = &wm9713_dai_ops_aux, }, { .name = "WM9713 Voice", @@ -1053,14 +1068,7 @@ struct snd_soc_dai wm9713_dai[] = { .channels_max = 2, .rates = WM9713_PCM_RATES, .formats = WM9713_PCM_FORMATS,}, - .ops = { - .hw_params = wm9713_pcm_hw_params, - .shutdown = wm9713_voiceshutdown, - .set_clkdiv = wm9713_set_dai_clkdiv, - .set_pll = wm9713_set_dai_pll, - .set_fmt = wm9713_set_dai_fmt, - .set_tristate = wm9713_set_dai_tristate, - }, + .ops = &wm9713_dai_ops_voice, }, }; EXPORT_SYMBOL_GPL(wm9713_dai); diff --git a/trunk/sound/soc/davinci/Kconfig b/trunk/sound/soc/davinci/Kconfig index bd7392c9657e..b502741692d6 100644 --- a/trunk/sound/soc/davinci/Kconfig +++ b/trunk/sound/soc/davinci/Kconfig @@ -20,7 +20,7 @@ config SND_DAVINCI_SOC_EVM config SND_DAVINCI_SOC_SFFSDR tristate "SoC Audio support for SFFSDR" - depends on SND_DAVINCI_SOC && MACH_SFFSDR + depends on SND_DAVINCI_SOC && MACH_DAVINCI_SFFSDR select SND_DAVINCI_SOC_I2S select SND_SOC_PCM3008 select SFFSDR_FPGA diff --git a/trunk/sound/soc/davinci/davinci-i2s.c b/trunk/sound/soc/davinci/davinci-i2s.c index 0fee779e3c76..ffdb9439d3d8 100644 --- a/trunk/sound/soc/davinci/davinci-i2s.c +++ b/trunk/sound/soc/davinci/davinci-i2s.c @@ -499,6 +499,13 @@ static void davinci_i2s_remove(struct platform_device *pdev, #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 +static struct snd_soc_dai_ops davinci_i2s_dai_ops = { + .startup = davinci_i2s_startup, + .trigger = davinci_i2s_trigger, + .hw_params = davinci_i2s_hw_params, + .set_fmt = davinci_i2s_set_dai_fmt, +}; + struct snd_soc_dai davinci_i2s_dai = { .name = "davinci-i2s", .id = 0, @@ -514,12 +521,7 @@ struct snd_soc_dai davinci_i2s_dai = { .channels_max = 2, .rates = DAVINCI_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .startup = davinci_i2s_startup, - .trigger = davinci_i2s_trigger, - .hw_params = davinci_i2s_hw_params, - .set_fmt = davinci_i2s_set_dai_fmt, - }, + .ops = &davinci_i2s_dai_ops, }; EXPORT_SYMBOL_GPL(davinci_i2s_dai); diff --git a/trunk/sound/soc/davinci/davinci-sffsdr.c b/trunk/sound/soc/davinci/davinci-sffsdr.c index 40eccfe9e358..0bf81abba8c7 100644 --- a/trunk/sound/soc/davinci/davinci-sffsdr.c +++ b/trunk/sound/soc/davinci/davinci-sffsdr.c @@ -36,16 +36,9 @@ #include "davinci-pcm.h" #include "davinci-i2s.h" -/* - * CLKX and CLKR are the inputs for the Sample Rate Generator. - * FSX and FSR are outputs, driven by the sample Rate Generator. - */ -#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ - SND_SOC_DAIFMT_CBM_CFS | \ - SND_SOC_DAIFMT_IB_NF) - static int sffsdr_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; @@ -63,8 +56,13 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream, } #endif - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); + /* Set cpu DAI configuration: + * CLKX and CLKR are the inputs for the Sample Rate Generator. + * FSX and FSR are outputs, driven by the sample Rate Generator. */ + ret = snd_soc_dai_set_fmt(cpu_dai, + SND_SOC_DAIFMT_RIGHT_J | + SND_SOC_DAIFMT_CBM_CFS | + SND_SOC_DAIFMT_IB_NF); if (ret < 0) return ret; diff --git a/trunk/sound/soc/fsl/fsl_dma.c b/trunk/sound/soc/fsl/fsl_dma.c index b3eb8570cd7b..58a3fa497503 100644 --- a/trunk/sound/soc/fsl/fsl_dma.c +++ b/trunk/sound/soc/fsl/fsl_dma.c @@ -142,8 +142,7 @@ static const struct snd_pcm_hardware fsl_dma_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_PAUSE, + SNDRV_PCM_INFO_JOINT_DUPLEX, .formats = FSLDMA_PCM_FORMATS, .rates = FSLDMA_PCM_RATES, .rate_min = 5512, diff --git a/trunk/sound/soc/fsl/fsl_ssi.c b/trunk/sound/soc/fsl/fsl_ssi.c index b7733e6be192..0fddd437a7c9 100644 --- a/trunk/sound/soc/fsl/fsl_ssi.c +++ b/trunk/sound/soc/fsl/fsl_ssi.c @@ -72,7 +72,6 @@ * @dev: struct device pointer * @playback: the number of playback streams opened * @capture: the number of capture streams opened - * @asynchronous: 0=synchronous mode, 1=asynchronous mode * @cpu_dai: the CPU DAI for this device * @dev_attr: the sysfs device attribute structure * @stats: SSI statistics @@ -87,7 +86,6 @@ struct fsl_ssi_private { struct device *dev; unsigned int playback; unsigned int capture; - int asynchronous; struct snd_soc_dai cpu_dai; struct device_attribute dev_attr; @@ -303,10 +301,9 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, * * FIXME: Little-endian samples require a different shift dir */ - clrsetbits_be32(&ssi->scr, - CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, - CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE - | (ssi_private->asynchronous ? 0 : CCSR_SSI_SCR_SYN)); + clrsetbits_be32(&ssi->scr, CCSR_SSI_SCR_I2S_MODE_MASK, + CCSR_SSI_SCR_TFR_CLK_DIS | + CCSR_SSI_SCR_I2S_MODE_SLAVE | CCSR_SSI_SCR_SYN); out_be32(&ssi->stcr, CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | @@ -385,15 +382,10 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, SNDRV_PCM_HW_PARAM_RATE, first_runtime->rate, first_runtime->rate); - /* If we're in synchronous mode, then we need to constrain - * the sample size as well. We don't support independent sample - * rates in asynchronous mode. - */ - if (!ssi_private->asynchronous) - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_SAMPLE_BITS, - first_runtime->sample_bits, - first_runtime->sample_bits); + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + first_runtime->sample_bits, + first_runtime->sample_bits); ssi_private->second_stream = substream; } @@ -429,18 +421,13 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, struct ccsr_ssi __iomem *ssi = ssi_private->ssi; unsigned int sample_size = snd_pcm_format_width(params_format(hw_params)); - u32 wl = CCSR_SSI_SxCCR_WL(sample_size); + u32 wl; /* The SSI should always be disabled at this points (SSIEN=0) */ + wl = CCSR_SSI_SxCCR_WL(sample_size); /* In synchronous mode, the SSI uses STCCR for capture */ - if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) || - !ssi_private->asynchronous) - clrsetbits_be32(&ssi->stccr, - CCSR_SSI_SxCCR_WL_MASK, wl); - else - clrsetbits_be32(&ssi->srccr, - CCSR_SSI_SxCCR_WL_MASK, wl); + clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl); } return 0; @@ -464,33 +451,28 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, switch (cmd) { case SNDRV_PCM_TRIGGER_START: - clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); + case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); setbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_TE); } else { - long timeout = jiffies + 10; - + clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN); setbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN | CCSR_SSI_SCR_RE); - /* Wait until the SSI has filled its FIFO. Without this - * delay, ALSA complains about overruns. When the FIFO - * is full, the DMA controller initiates its first - * transfer. Until then, however, the DMA's DAR - * register is zero, which translates to an - * out-of-bounds pointer. This makes ALSA think an - * overrun has occurred. + /* + * I think we need this delay to allow time for the SSI + * to put data into its FIFO. Without it, ALSA starts + * to complain about overruns. */ - while (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0) && - (jiffies < timeout)); - if (!(in_be32(&ssi->sisr) & CCSR_SSI_SISR_RFF0)) - return -EIO; + mdelay(1); } break; case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) clrbits32(&ssi->scr, CCSR_SSI_SCR_TE); @@ -580,6 +562,15 @@ static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) /** * fsl_ssi_dai_template: template CPU DAI for the SSI */ +static struct snd_soc_dai_ops fsl_ssi_dai_ops = { + .startup = fsl_ssi_startup, + .hw_params = fsl_ssi_hw_params, + .shutdown = fsl_ssi_shutdown, + .trigger = fsl_ssi_trigger, + .set_sysclk = fsl_ssi_set_sysclk, + .set_fmt = fsl_ssi_set_fmt, +}; + static struct snd_soc_dai fsl_ssi_dai_template = { .playback = { /* The SSI does not support monaural audio. */ @@ -594,14 +585,7 @@ static struct snd_soc_dai fsl_ssi_dai_template = { .rates = FSLSSI_I2S_RATES, .formats = FSLSSI_I2S_FORMATS, }, - .ops = { - .startup = fsl_ssi_startup, - .hw_params = fsl_ssi_hw_params, - .shutdown = fsl_ssi_shutdown, - .trigger = fsl_ssi_trigger, - .set_sysclk = fsl_ssi_set_sysclk, - .set_fmt = fsl_ssi_set_fmt, - }, + .ops = &fsl_ssi_dai_ops, }; /** @@ -671,7 +655,6 @@ struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info) ssi_private->ssi_phys = ssi_info->ssi_phys; ssi_private->irq = ssi_info->irq; ssi_private->dev = ssi_info->dev; - ssi_private->asynchronous = ssi_info->asynchronous; ssi_private->dev->driver_data = fsl_ssi_dai; @@ -722,14 +705,6 @@ void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai) } EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); -static int __init fsl_ssi_init(void) -{ - printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n"); - - return 0; -} -module_init(fsl_ssi_init); - MODULE_AUTHOR("Timur Tabi "); MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/fsl/fsl_ssi.h b/trunk/sound/soc/fsl/fsl_ssi.h index eade01feaab6..83b44d700e33 100644 --- a/trunk/sound/soc/fsl/fsl_ssi.h +++ b/trunk/sound/soc/fsl/fsl_ssi.h @@ -208,7 +208,6 @@ struct ccsr_ssi { * ssi_phys: physical address of the SSI registers * irq: IRQ of this SSI * dev: struct device, used to create the sysfs statistics file - * asynchronous: 0=synchronous mode, 1=asynchronous mode */ struct fsl_ssi_info { unsigned int id; @@ -216,7 +215,6 @@ struct fsl_ssi_info { dma_addr_t ssi_phys; unsigned int irq; struct device *dev; - int asynchronous; }; struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info); diff --git a/trunk/sound/soc/fsl/mpc5200_psc_i2s.c b/trunk/sound/soc/fsl/mpc5200_psc_i2s.c index 9eb1ce185bd0..3aa729df27b5 100644 --- a/trunk/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/trunk/sound/soc/fsl/mpc5200_psc_i2s.c @@ -468,6 +468,16 @@ static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) /** * psc_i2s_dai_template: template CPU Digital Audio Interface */ +static struct snd_soc_dai_ops psc_i2s_dai_ops = { + .startup = psc_i2s_startup, + .hw_params = psc_i2s_hw_params, + .hw_free = psc_i2s_hw_free, + .shutdown = psc_i2s_shutdown, + .trigger = psc_i2s_trigger, + .set_sysclk = psc_i2s_set_sysclk, + .set_fmt = psc_i2s_set_fmt, +}; + static struct snd_soc_dai psc_i2s_dai_template = { .playback = { .channels_min = 2, @@ -481,15 +491,7 @@ static struct snd_soc_dai psc_i2s_dai_template = { .rates = PSC_I2S_RATES, .formats = PSC_I2S_FORMATS, }, - .ops = { - .startup = psc_i2s_startup, - .hw_params = psc_i2s_hw_params, - .hw_free = psc_i2s_hw_free, - .shutdown = psc_i2s_shutdown, - .trigger = psc_i2s_trigger, - .set_sysclk = psc_i2s_set_sysclk, - .set_fmt = psc_i2s_set_fmt, - }, + .ops = &psc_i2s_dai_ops, }; /* --------------------------------------------------------------------- diff --git a/trunk/sound/soc/fsl/mpc8610_hpcd.c b/trunk/sound/soc/fsl/mpc8610_hpcd.c index ef67d1cdffe7..acf39a646b2f 100644 --- a/trunk/sound/soc/fsl/mpc8610_hpcd.c +++ b/trunk/sound/soc/fsl/mpc8610_hpcd.c @@ -353,11 +353,6 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, } ssi_info.irq = machine_data->ssi_irq; - /* Do we want to use asynchronous mode? */ - ssi_info.asynchronous = - of_find_property(np, "fsl,ssi-asynchronous", NULL) ? 1 : 0; - if (ssi_info.asynchronous) - dev_info(&ofdev->dev, "using asynchronous mode\n"); /* Map the global utilities registers. */ guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts"); diff --git a/trunk/sound/soc/omap/omap-mcbsp.c b/trunk/sound/soc/omap/omap-mcbsp.c index 05dd5abcddf4..d6882be33452 100644 --- a/trunk/sound/soc/omap/omap-mcbsp.c +++ b/trunk/sound/soc/omap/omap-mcbsp.c @@ -461,6 +461,16 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, return err; } +static struct snd_soc_dai_ops omap_mcbsp_dai_ops = { + .startup = omap_mcbsp_dai_startup, + .shutdown = omap_mcbsp_dai_shutdown, + .trigger = omap_mcbsp_dai_trigger, + .hw_params = omap_mcbsp_dai_hw_params, + .set_fmt = omap_mcbsp_dai_set_dai_fmt, + .set_clkdiv = omap_mcbsp_dai_set_clkdiv, + .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, +}; + #define OMAP_MCBSP_DAI_BUILDER(link_id) \ { \ .name = "omap-mcbsp-dai-"#link_id, \ @@ -477,15 +487,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, .rates = OMAP_MCBSP_RATES, \ .formats = SNDRV_PCM_FMTBIT_S16_LE, \ }, \ - .ops = { \ - .startup = omap_mcbsp_dai_startup, \ - .shutdown = omap_mcbsp_dai_shutdown, \ - .trigger = omap_mcbsp_dai_trigger, \ - .hw_params = omap_mcbsp_dai_hw_params, \ - .set_fmt = omap_mcbsp_dai_set_dai_fmt, \ - .set_clkdiv = omap_mcbsp_dai_set_clkdiv, \ - .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \ - }, \ + .ops = &omap_mcbsp_dai_ops, \ .private_data = &mcbsp_data[(link_id)].bus_id, \ } diff --git a/trunk/sound/soc/omap/osk5912.c b/trunk/sound/soc/omap/osk5912.c index a952a4eb3361..cd41a948df7b 100644 --- a/trunk/sound/soc/omap/osk5912.c +++ b/trunk/sound/soc/omap/osk5912.c @@ -186,6 +186,13 @@ static int __init osk_soc_init(void) return -ENODEV; } + if (clk_get_usecount(tlv320aic23_mclk) > 0) { + /* MCLK is already in use */ + printk(KERN_WARNING + "MCLK in use at %d Hz. We change it to %d Hz\n", + (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK); + } + /* * Configure 12 MHz output on MCLK. */ @@ -198,8 +205,9 @@ static int __init osk_soc_init(void) } } - printk(KERN_INFO "MCLK = %d [%d]\n", - (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK); + printk(KERN_INFO "MCLK = %d [%d], usecount = %d\n", + (uint) clk_get_rate(tlv320aic23_mclk), CODEC_CLOCK, + clk_get_usecount(tlv320aic23_mclk)); return 0; err1: diff --git a/trunk/sound/soc/omap/sdp3430.c b/trunk/sound/soc/omap/sdp3430.c index 715c648203a4..e226fa75669c 100644 --- a/trunk/sound/soc/omap/sdp3430.c +++ b/trunk/sound/soc/omap/sdp3430.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -82,97 +81,12 @@ static struct snd_soc_ops sdp3430_ops = { .hw_params = sdp3430_hw_params, }; -/* SDP3430 machine DAPM */ -static const struct snd_soc_dapm_widget sdp3430_twl4030_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Ext Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_HP("Headset Jack", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* External Mics: MAINMIC, SUBMIC with bias*/ - {"MAINMIC", NULL, "Mic Bias 1"}, - {"SUBMIC", NULL, "Mic Bias 2"}, - {"Mic Bias 1", NULL, "Ext Mic"}, - {"Mic Bias 2", NULL, "Ext Mic"}, - - /* External Speakers: HFL, HFR */ - {"Ext Spk", NULL, "HFL"}, - {"Ext Spk", NULL, "HFR"}, - - /* Headset: HSMIC (with bias), HSOL, HSOR */ - {"Headset Jack", NULL, "HSOL"}, - {"Headset Jack", NULL, "HSOR"}, - {"HSMIC", NULL, "Headset Mic Bias"}, - {"Headset Mic Bias", NULL, "Headset Jack"}, -}; - -static int sdp3430_twl4030_init(struct snd_soc_codec *codec) -{ - int ret; - - /* Add SDP3430 specific widgets */ - ret = snd_soc_dapm_new_controls(codec, sdp3430_twl4030_dapm_widgets, - ARRAY_SIZE(sdp3430_twl4030_dapm_widgets)); - if (ret) - return ret; - - /* Set up SDP3430 specific audio path audio_map */ - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - - /* SDP3430 connected pins */ - snd_soc_dapm_enable_pin(codec, "Ext Mic"); - snd_soc_dapm_enable_pin(codec, "Ext Spk"); - snd_soc_dapm_disable_pin(codec, "Headset Jack"); - - /* TWL4030 not connected pins */ - snd_soc_dapm_nc_pin(codec, "AUXL"); - snd_soc_dapm_nc_pin(codec, "AUXR"); - snd_soc_dapm_nc_pin(codec, "CARKITMIC"); - snd_soc_dapm_nc_pin(codec, "DIGIMIC0"); - snd_soc_dapm_nc_pin(codec, "DIGIMIC1"); - - snd_soc_dapm_nc_pin(codec, "OUTL"); - snd_soc_dapm_nc_pin(codec, "OUTR"); - snd_soc_dapm_nc_pin(codec, "EARPIECE"); - snd_soc_dapm_nc_pin(codec, "PREDRIVEL"); - snd_soc_dapm_nc_pin(codec, "PREDRIVER"); - snd_soc_dapm_nc_pin(codec, "CARKITL"); - snd_soc_dapm_nc_pin(codec, "CARKITR"); - - ret = snd_soc_dapm_sync(codec); - - return ret; -} - -/* Headset jack */ -static struct snd_soc_jack hs_jack; - -/* Headset jack detection DAPM pins */ -static struct snd_soc_jack_pin hs_jack_pins[] = { - { - .pin = "Headset Jack", - .mask = SND_JACK_HEADSET, - }, -}; - -/* Headset jack detection gpios */ -static struct snd_soc_jack_gpio hs_jack_gpios[] = { - { - .gpio = (OMAP_MAX_GPIO_LINES + 2), - .name = "hsdet-gpio", - .report = SND_JACK_HEADSET, - .debounce_time = 200, - }, -}; - /* Digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link sdp3430_dai = { .name = "TWL4030", .stream_name = "TWL4030", .cpu_dai = &omap_mcbsp_dai[0], .codec_dai = &twl4030_dai, - .init = sdp3430_twl4030_init, .ops = &sdp3430_ops, }; @@ -216,21 +130,7 @@ static int __init sdp3430_soc_init(void) if (ret) goto err1; - /* Headset jack detection */ - ret = snd_soc_jack_new(&snd_soc_sdp3430, "SDP3430 headset jack", - SND_JACK_HEADSET, &hs_jack); - if (ret) - return ret; - - ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), - hs_jack_pins); - if (ret) - return ret; - - ret = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); - - return ret; + return 0; err1: printk(KERN_ERR "Unable to add platform device\n"); @@ -242,9 +142,6 @@ module_init(sdp3430_soc_init); static void __exit sdp3430_soc_exit(void) { - snd_soc_jack_free_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); - platform_device_unregister(sdp3430_snd_device); } module_exit(sdp3430_soc_exit); diff --git a/trunk/sound/soc/pxa/pxa-ssp.c b/trunk/sound/soc/pxa/pxa-ssp.c index 52d97c4b82b1..3e18064e86b2 100644 --- a/trunk/sound/soc/pxa/pxa-ssp.c +++ b/trunk/sound/soc/pxa/pxa-ssp.c @@ -300,7 +300,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int val; u32 sscr0 = ssp_read_reg(ssp, SSCR0) & - ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); + ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC); dev_dbg(&ssp->pdev->dev, "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n", @@ -328,7 +328,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, case PXA_SSP_CLK_AUDIO: priv->sysclk = 0; ssp_set_scr(&priv->dev, 1); - sscr0 |= SSCR0_ACS; + sscr0 |= SSCR0_ADC; break; default: return -ENODEV; @@ -522,20 +522,9 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, u32 sscr1; u32 sspsp; - /* check if we need to change anything at all */ - if (priv->dai_fmt == fmt) - return 0; - - /* we can only change the settings if the port is not in use */ - if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) { - dev_err(&ssp->pdev->dev, - "can't change hardware dai format: stream is in use"); - return -EINVAL; - } - /* reset port settings */ sscr0 = ssp_read_reg(ssp, SSCR0) & - (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); + (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC); sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); sspsp = 0; @@ -655,7 +644,8 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, sscr0 |= SSCR0_FPCKE; #endif sscr0 |= SSCR0_DataSize(16); - /* use network mode (2 slots) for 16 bit stereo */ + if (params_channels(params) > 1) + sscr0 |= SSCR0_EDSS; break; case SNDRV_PCM_FORMAT_S24_LE: sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); @@ -794,6 +784,19 @@ static void pxa_ssp_remove(struct platform_device *pdev, SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE) +static struct snd_soc_dai_ops pxa_ssp_dai_ops = { + .startup = pxa_ssp_startup, + .shutdown = pxa_ssp_shutdown, + .trigger = pxa_ssp_trigger, + .hw_params = pxa_ssp_hw_params, + .set_sysclk = pxa_ssp_set_dai_sysclk, + .set_clkdiv = pxa_ssp_set_dai_clkdiv, + .set_pll = pxa_ssp_set_dai_pll, + .set_fmt = pxa_ssp_set_dai_fmt, + .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, + .set_tristate = pxa_ssp_set_dai_tristate, +}; + struct snd_soc_dai pxa_ssp_dai[] = { { .name = "pxa2xx-ssp1", @@ -814,18 +817,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { .rates = PXA_SSP_RATES, .formats = PXA_SSP_FORMATS, }, - .ops = { - .startup = pxa_ssp_startup, - .shutdown = pxa_ssp_shutdown, - .trigger = pxa_ssp_trigger, - .hw_params = pxa_ssp_hw_params, - .set_sysclk = pxa_ssp_set_dai_sysclk, - .set_clkdiv = pxa_ssp_set_dai_clkdiv, - .set_pll = pxa_ssp_set_dai_pll, - .set_fmt = pxa_ssp_set_dai_fmt, - .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, - .set_tristate = pxa_ssp_set_dai_tristate, - }, + .ops = &pxa_ssp_dai_ops, }, { .name = "pxa2xx-ssp2", .id = 1, @@ -845,18 +837,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { .rates = PXA_SSP_RATES, .formats = PXA_SSP_FORMATS, }, - .ops = { - .startup = pxa_ssp_startup, - .shutdown = pxa_ssp_shutdown, - .trigger = pxa_ssp_trigger, - .hw_params = pxa_ssp_hw_params, - .set_sysclk = pxa_ssp_set_dai_sysclk, - .set_clkdiv = pxa_ssp_set_dai_clkdiv, - .set_pll = pxa_ssp_set_dai_pll, - .set_fmt = pxa_ssp_set_dai_fmt, - .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, - .set_tristate = pxa_ssp_set_dai_tristate, - }, + .ops = &pxa_ssp_dai_ops, }, { .name = "pxa2xx-ssp3", @@ -877,18 +858,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { .rates = PXA_SSP_RATES, .formats = PXA_SSP_FORMATS, }, - .ops = { - .startup = pxa_ssp_startup, - .shutdown = pxa_ssp_shutdown, - .trigger = pxa_ssp_trigger, - .hw_params = pxa_ssp_hw_params, - .set_sysclk = pxa_ssp_set_dai_sysclk, - .set_clkdiv = pxa_ssp_set_dai_clkdiv, - .set_pll = pxa_ssp_set_dai_pll, - .set_fmt = pxa_ssp_set_dai_fmt, - .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, - .set_tristate = pxa_ssp_set_dai_tristate, - }, + .ops = &pxa_ssp_dai_ops, }, { .name = "pxa2xx-ssp4", @@ -909,18 +879,7 @@ struct snd_soc_dai pxa_ssp_dai[] = { .rates = PXA_SSP_RATES, .formats = PXA_SSP_FORMATS, }, - .ops = { - .startup = pxa_ssp_startup, - .shutdown = pxa_ssp_shutdown, - .trigger = pxa_ssp_trigger, - .hw_params = pxa_ssp_hw_params, - .set_sysclk = pxa_ssp_set_dai_sysclk, - .set_clkdiv = pxa_ssp_set_dai_clkdiv, - .set_pll = pxa_ssp_set_dai_pll, - .set_fmt = pxa_ssp_set_dai_fmt, - .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, - .set_tristate = pxa_ssp_set_dai_tristate, - }, + .ops = &pxa_ssp_dai_ops, }, }; EXPORT_SYMBOL_GPL(pxa_ssp_dai); diff --git a/trunk/sound/soc/pxa/pxa2xx-ac97.c b/trunk/sound/soc/pxa/pxa2xx-ac97.c index 49a2810ca58c..11cd0f289c16 100644 --- a/trunk/sound/soc/pxa/pxa2xx-ac97.c +++ b/trunk/sound/soc/pxa/pxa2xx-ac97.c @@ -106,13 +106,13 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai) static int pxa2xx_ac97_probe(struct platform_device *pdev, struct snd_soc_dai *dai) { - return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev)); + return pxa2xx_ac97_hw_probe(pdev); } static void pxa2xx_ac97_remove(struct platform_device *pdev, struct snd_soc_dai *dai) { - pxa2xx_ac97_hw_remove(to_platform_device(dai->dev)); + pxa2xx_ac97_hw_remove(pdev); } static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, @@ -164,6 +164,10 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) +static struct snd_soc_dai_ops pxa_ac97_dai_ops = { + .hw_params = pxa2xx_ac97_hw_params, +}; + /* * There is only 1 physical AC97 interface for pxa2xx, but it * has extra fifo's that can be used for aux DACs and ADCs. @@ -189,8 +193,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 2, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .hw_params = pxa2xx_ac97_hw_params,}, + .ops = &pxa_ac97_dai_ops, }, { .name = "pxa2xx-ac97-aux", @@ -208,8 +211,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 1, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .hw_params = pxa2xx_ac97_hw_aux_params,}, + .ops = &pxa_ac97_dai_ops, }, { .name = "pxa2xx-ac97-mic", @@ -221,53 +223,22 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 1, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .hw_params = pxa2xx_ac97_hw_mic_params,}, + .ops = &pxa_ac97_dai_ops, }, }; EXPORT_SYMBOL_GPL(pxa_ac97_dai); EXPORT_SYMBOL_GPL(soc_ac97_ops); -static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) - pxa_ac97_dai[i].dev = &pdev->dev; - - /* Punt most of the init to the SoC probe; we may need the machine - * driver to do interesting things with the clocking to get us up - * and running. - */ - return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); -} - -static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev) -{ - snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); - - return 0; -} - -static struct platform_driver pxa2xx_ac97_driver = { - .probe = pxa2xx_ac97_dev_probe, - .remove = __devexit_p(pxa2xx_ac97_dev_remove), - .driver = { - .name = "pxa2xx-ac97", - .owner = THIS_MODULE, - }, -}; - static int __init pxa_ac97_init(void) { - return platform_driver_register(&pxa2xx_ac97_driver); + return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); } module_init(pxa_ac97_init); static void __exit pxa_ac97_exit(void) { - platform_driver_unregister(&pxa2xx_ac97_driver); + snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); } module_exit(pxa_ac97_exit); diff --git a/trunk/sound/soc/pxa/pxa2xx-i2s.c b/trunk/sound/soc/pxa/pxa2xx-i2s.c index 83b59d7fe96e..e6c24408c5f9 100644 --- a/trunk/sound/soc/pxa/pxa2xx-i2s.c +++ b/trunk/sound/soc/pxa/pxa2xx-i2s.c @@ -304,6 +304,15 @@ static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) +static struct snd_soc_dai_ops pxa_i2s_dai_ops = { + .startup = pxa2xx_i2s_startup, + .shutdown = pxa2xx_i2s_shutdown, + .trigger = pxa2xx_i2s_trigger, + .hw_params = pxa2xx_i2s_hw_params, + .set_fmt = pxa2xx_i2s_set_dai_fmt, + .set_sysclk = pxa2xx_i2s_set_dai_sysclk, +}; + struct snd_soc_dai pxa_i2s_dai = { .name = "pxa2xx-i2s", .id = 0, @@ -319,14 +328,7 @@ struct snd_soc_dai pxa_i2s_dai = { .channels_max = 2, .rates = PXA2XX_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .startup = pxa2xx_i2s_startup, - .shutdown = pxa2xx_i2s_shutdown, - .trigger = pxa2xx_i2s_trigger, - .hw_params = pxa2xx_i2s_hw_params, - .set_fmt = pxa2xx_i2s_set_dai_fmt, - .set_sysclk = pxa2xx_i2s_set_dai_sysclk, - }, + .ops = &pxa_i2s_dai_ops, }; EXPORT_SYMBOL_GPL(pxa_i2s_dai); diff --git a/trunk/sound/soc/pxa/zylonite.c b/trunk/sound/soc/pxa/zylonite.c index 9f6116edbb84..0140a250db24 100644 --- a/trunk/sound/soc/pxa/zylonite.c +++ b/trunk/sound/soc/pxa/zylonite.c @@ -127,11 +127,8 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - /* Use network mode for stereo, one slot per channel. */ - if (params_channels(params) > 1) - ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 2); - else - ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1); + /* We're not really in network mode but the emulation wants this. */ + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1); if (ret < 0) return ret; diff --git a/trunk/sound/soc/s3c24xx/Kconfig b/trunk/sound/soc/s3c24xx/Kconfig index 2f3a21eee051..e05a71084c32 100644 --- a/trunk/sound/soc/s3c24xx/Kconfig +++ b/trunk/sound/soc/s3c24xx/Kconfig @@ -1,31 +1,19 @@ config SND_S3C24XX_SOC - tristate "SoC Audio for the Samsung S3CXXXX chips" - depends on ARCH_S3C2410 || ARCH_S3C64XX + tristate "SoC Audio for the Samsung S3C24XX chips" + depends on ARCH_S3C2410 help Say Y or M if you want to add support for codecs attached to - the S3C24XX and S3C64XX AC97, I2S or SSP interface. You will - also need to select the audio interfaces to support below. + the S3C24XX AC97, I2S or SSP interface. You will also need + to select the audio interfaces to support below. config SND_S3C24XX_SOC_I2S tristate - select S3C2410_DMA - -config SND_S3C_I2SV2_SOC - tristate config SND_S3C2412_SOC_I2S tristate - select SND_S3C_I2SV2_SOC - select S3C2410_DMA - -config SND_S3C64XX_SOC_I2S - tristate - select SND_S3C_I2SV2_SOC - select S3C64XX_DMA config SND_S3C2443_SOC_AC97 tristate - select S3C2410_DMA select AC97_BUS select SND_SOC_AC97_BUS @@ -38,14 +26,6 @@ config SND_S3C24XX_SOC_NEO1973_WM8753 Say Y if you want to add support for SoC audio on smdk2440 with the WM8753. -config SND_S3C24XX_SOC_JIVE_WM8750 - tristate "SoC I2S Audio support for Jive" - depends on SND_S3C24XX_SOC && MACH_JIVE - select SND_SOC_WM8750 - select SND_S3C2412_SOC_I2S - help - Sat Y if you want to add support for SoC audio on the Jive. - config SND_S3C24XX_SOC_SMDK2443_WM9710 tristate "SoC AC97 Audio support for SMDK2443 - WM9710" depends on SND_S3C24XX_SOC && MACH_SMDK2443 diff --git a/trunk/sound/soc/s3c24xx/Makefile b/trunk/sound/soc/s3c24xx/Makefile index 07a93a2ebe5f..96b3f3f617d4 100644 --- a/trunk/sound/soc/s3c24xx/Makefile +++ b/trunk/sound/soc/s3c24xx/Makefile @@ -2,25 +2,19 @@ snd-soc-s3c24xx-objs := s3c24xx-pcm.o snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o -snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o -snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o -obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o -obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o # S3C24XX Machine Support -snd-soc-jive-wm8750-objs := jive_wm8750.o snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o -obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o diff --git a/trunk/sound/soc/s3c24xx/jive_wm8750.c b/trunk/sound/soc/s3c24xx/jive_wm8750.c deleted file mode 100644 index 32063790d95b..000000000000 --- a/trunk/sound/soc/s3c24xx/jive_wm8750.c +++ /dev/null @@ -1,201 +0,0 @@ -/* sound/soc/s3c24xx/jive_wm8750.c - * - * Copyright 2007,2008 Simtec Electronics - * - * Based on sound/soc/pxa/spitz.c - * Copyright 2005 Wolfson Microelectronics PLC. - * Copyright 2005 Openedhand Ltd. - * - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "s3c24xx-pcm.h" -#include "s3c2412-i2s.h" - -#include "../codecs/wm8750.h" - -static const struct snd_soc_dapm_route audio_map[] = { - { "Headphone Jack", NULL, "LOUT1" }, - { "Headphone Jack", NULL, "ROUT1" }, - { "Internal Speaker", NULL, "LOUT2" }, - { "Internal Speaker", NULL, "ROUT2" }, - { "LINPUT1", NULL, "Line Input" }, - { "RINPUT1", NULL, "Line Input" }, -}; - -static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_SPK("Internal Speaker", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), -}; - -static int jive_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct s3c_i2sv2_rate_calc div; - unsigned int clk = 0; - int ret = 0; - - switch (params_rate(params)) { - case 8000: - case 16000: - case 48000: - case 96000: - clk = 12288000; - break; - case 11025: - case 22050: - case 44100: - clk = 11289600; - break; - } - - s3c_i2sv2_calc_rate(&div, NULL, params_rate(params), - s3c2412_get_iisclk()); - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - if (ret < 0) - return ret; - - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBS_CFS); - if (ret < 0) - return ret; - - /* set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk, - SND_SOC_CLOCK_IN); - if (ret < 0) - return ret; - - ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_RCLK, div.fs_div); - if (ret < 0) - return ret; - - ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_PRESCALER, - div.clk_div - 1); - if (ret < 0) - return ret; - - return 0; -} - -static struct snd_soc_ops jive_ops = { - .hw_params = jive_hw_params, -}; - -static int jive_wm8750_init(struct snd_soc_codec *codec) -{ - int err; - - /* These endpoints are not being used. */ - snd_soc_dapm_nc_pin(codec, "LINPUT2"); - snd_soc_dapm_nc_pin(codec, "RINPUT2"); - snd_soc_dapm_nc_pin(codec, "LINPUT3"); - snd_soc_dapm_nc_pin(codec, "RINPUT3"); - snd_soc_dapm_nc_pin(codec, "OUT3"); - snd_soc_dapm_nc_pin(codec, "MONO"); - - /* Add jive specific widgets */ - err = snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets, - ARRAY_SIZE(wm8750_dapm_widgets)); - if (err) { - printk(KERN_ERR "%s: failed to add widgets (%d)\n", - __func__, err); - return err; - } - - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - snd_soc_dapm_sync(codec); - - return 0; -} - -static struct snd_soc_dai_link jive_dai = { - .name = "wm8750", - .stream_name = "WM8750", - .cpu_dai = &s3c2412_i2s_dai, - .codec_dai = &wm8750_dai, - .init = jive_wm8750_init, - .ops = &jive_ops, -}; - -/* jive audio machine driver */ -static struct snd_soc_machine snd_soc_machine_jive = { - .name = "Jive", - .dai_link = &jive_dai, - .num_links = 1, -}; - -/* jive audio private data */ -static struct wm8750_setup_data jive_wm8750_setup = { -}; - -/* jive audio subsystem */ -static struct snd_soc_device jive_snd_devdata = { - .machine = &snd_soc_machine_jive, - .platform = &s3c24xx_soc_platform, - .codec_dev = &soc_codec_dev_wm8750_spi, - .codec_data = &jive_wm8750_setup, -}; - -static struct platform_device *jive_snd_device; - -static int __init jive_init(void) -{ - int ret; - - if (!machine_is_jive()) - return 0; - - printk("JIVE WM8750 Audio support\n"); - - jive_snd_device = platform_device_alloc("soc-audio", -1); - if (!jive_snd_device) - return -ENOMEM; - - platform_set_drvdata(jive_snd_device, &jive_snd_devdata); - jive_snd_devdata.dev = &jive_snd_device->dev; - ret = platform_device_add(jive_snd_device); - - if (ret) - platform_device_put(jive_snd_device); - - return ret; -} - -static void __exit jive_exit(void) -{ - platform_device_unregister(jive_snd_device); -} - -module_init(jive_init); -module_exit(jive_exit); - -MODULE_AUTHOR("Ben Dooks "); -MODULE_DESCRIPTION("ALSA SoC Jive Audio support"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/s3c24xx/neo1973_wm8753.c b/trunk/sound/soc/s3c24xx/neo1973_wm8753.c index 5f6aeec0437d..286e11ad50ea 100644 --- a/trunk/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/trunk/sound/soc/s3c24xx/neo1973_wm8753.c @@ -29,17 +29,25 @@ #include #include #include -#include +#include #include #include -#include +#include #include "../codecs/wm8753.h" #include "lm4857.h" #include "s3c24xx-pcm.h" #include "s3c24xx-i2s.h" +/* Debugging stuff */ +#define S3C24XX_SOC_NEO1973_WM8753_DEBUG 0 +#if S3C24XX_SOC_NEO1973_WM8753_DEBUG +#define DBG(x...) printk(KERN_DEBUG "s3c24xx-soc-neo1973-wm8753: " x) +#else +#define DBG(x...) +#endif + /* define the scenarios */ #define NEO_AUDIO_OFF 0 #define NEO_GSM_CALL_AUDIO_HANDSET 1 @@ -64,7 +72,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, int ret = 0; unsigned long iis_clkrate; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); iis_clkrate = s3c24xx_i2s_get_clockrate(); @@ -150,7 +158,7 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); /* disable the PLL */ return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0); @@ -173,7 +181,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, int ret = 0; unsigned long iis_clkrate; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); iis_clkrate = s3c24xx_i2s_get_clockrate(); @@ -216,7 +224,7 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); /* disable the PLL */ return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0); @@ -238,7 +246,7 @@ static int neo1973_get_scenario(struct snd_kcontrol *kcontrol, static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); switch (neo1973_scenario) { case NEO_AUDIO_OFF: @@ -322,7 +330,7 @@ static int neo1973_set_scenario(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); if (neo1973_scenario == ucontrol->value.integer.value[0]) return 0; @@ -336,7 +344,7 @@ static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0}; static void lm4857_write_regs(void) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); if (i2c_master_send(i2c, lm4857_regs, 4) != 4) printk(KERN_ERR "lm4857: i2c write failed\n"); @@ -349,7 +357,7 @@ static int lm4857_get_reg(struct snd_kcontrol *kcontrol, int shift = (kcontrol->private_value >> 8) & 0x0F; int mask = (kcontrol->private_value >> 16) & 0xFF; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask; return 0; @@ -377,7 +385,7 @@ static int lm4857_get_mode(struct snd_kcontrol *kcontrol, { u8 value = lm4857_regs[LM4857_CTRL] & 0x0F; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); if (value) value -= 5; @@ -391,7 +399,7 @@ static int lm4857_set_mode(struct snd_kcontrol *kcontrol, { u8 value = ucontrol->value.integer.value[0]; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); if (value) value += 5; @@ -500,7 +508,7 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec) { int i, err; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); /* set up NC codec pins */ snd_soc_dapm_nc_pin(codec, "LOUT2"); @@ -585,7 +593,7 @@ static struct snd_soc_device neo1973_snd_devdata = { static int lm4857_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); i2c = client; @@ -595,7 +603,7 @@ static int lm4857_i2c_probe(struct i2c_client *client, static int lm4857_i2c_remove(struct i2c_client *client) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); i2c = NULL; @@ -606,7 +614,7 @@ static u8 lm4857_state; static int lm4857_suspend(struct i2c_client *dev, pm_message_t state) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); dev_dbg(&dev->dev, "lm4857_suspend\n"); lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf; @@ -619,7 +627,7 @@ static int lm4857_suspend(struct i2c_client *dev, pm_message_t state) static int lm4857_resume(struct i2c_client *dev) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); if (lm4857_state) { lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f); @@ -630,7 +638,7 @@ static int lm4857_resume(struct i2c_client *dev) static void lm4857_shutdown(struct i2c_client *dev) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); dev_dbg(&dev->dev, "lm4857_shutdown\n"); lm4857_regs[LM4857_CTRL] &= 0xf0; @@ -661,7 +669,7 @@ static int __init neo1973_init(void) { int ret; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); if (!machine_is_neo1973_gta01()) { printk(KERN_INFO @@ -692,7 +700,7 @@ static int __init neo1973_init(void) static void __exit neo1973_exit(void) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); i2c_del_driver(&lm4857_i2c_driver); platform_device_unregister(neo1973_snd_device); diff --git a/trunk/sound/soc/s3c24xx/s3c-i2s-v2.c b/trunk/sound/soc/s3c24xx/s3c-i2s-v2.c deleted file mode 100644 index 295a4c910262..000000000000 --- a/trunk/sound/soc/s3c24xx/s3c-i2s-v2.c +++ /dev/null @@ -1,638 +0,0 @@ -/* sound/soc/s3c24xx/s3c-i2c-v2.c - * - * ALSA Soc Audio Layer - I2S core for newer Samsung SoCs. - * - * Copyright (c) 2006 Wolfson Microelectronics PLC. - * Graeme Gregory graeme.gregory@wolfsonmicro.com - * linux@wolfsonmicro.com - * - * Copyright (c) 2008, 2007, 2004-2005 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "s3c-i2s-v2.h" - -#define S3C2412_I2S_DEBUG_CON 0 - -static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) -{ - return cpu_dai->private_data; -} - -#define bit_set(v, b) (((v) & (b)) ? 1 : 0) - -#if S3C2412_I2S_DEBUG_CON -static void dbg_showcon(const char *fn, u32 con) -{ - printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d, RXFFULL=%d\n", fn, - bit_set(con, S3C2412_IISCON_LRINDEX), - bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY), - bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY), - bit_set(con, S3C2412_IISCON_TXFIFO_FULL), - bit_set(con, S3C2412_IISCON_RXFIFO_FULL)); - - printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n", - fn, - bit_set(con, S3C2412_IISCON_TXDMA_PAUSE), - bit_set(con, S3C2412_IISCON_RXDMA_PAUSE), - bit_set(con, S3C2412_IISCON_TXCH_PAUSE), - bit_set(con, S3C2412_IISCON_RXCH_PAUSE)); - printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn, - bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE), - bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE), - bit_set(con, S3C2412_IISCON_IIS_ACTIVE)); -} -#else -static inline void dbg_showcon(const char *fn, u32 con) -{ -} -#endif - - -/* Turn on or off the transmission path. */ -void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on) -{ - void __iomem *regs = i2s->regs; - u32 fic, con, mod; - - pr_debug("%s(%d)\n", __func__, on); - - fic = readl(regs + S3C2412_IISFIC); - con = readl(regs + S3C2412_IISCON); - mod = readl(regs + S3C2412_IISMOD); - - pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); - - if (on) { - con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE; - con &= ~S3C2412_IISCON_TXDMA_PAUSE; - con &= ~S3C2412_IISCON_TXCH_PAUSE; - - switch (mod & S3C2412_IISMOD_MODE_MASK) { - case S3C2412_IISMOD_MODE_TXONLY: - case S3C2412_IISMOD_MODE_TXRX: - /* do nothing, we are in the right mode */ - break; - - case S3C2412_IISMOD_MODE_RXONLY: - mod &= ~S3C2412_IISMOD_MODE_MASK; - mod |= S3C2412_IISMOD_MODE_TXRX; - break; - - default: - dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n"); - } - - writel(con, regs + S3C2412_IISCON); - writel(mod, regs + S3C2412_IISMOD); - } else { - /* Note, we do not have any indication that the FIFO problems - * tha the S3C2410/2440 had apply here, so we should be able - * to disable the DMA and TX without resetting the FIFOS. - */ - - con |= S3C2412_IISCON_TXDMA_PAUSE; - con |= S3C2412_IISCON_TXCH_PAUSE; - con &= ~S3C2412_IISCON_TXDMA_ACTIVE; - - switch (mod & S3C2412_IISMOD_MODE_MASK) { - case S3C2412_IISMOD_MODE_TXRX: - mod &= ~S3C2412_IISMOD_MODE_MASK; - mod |= S3C2412_IISMOD_MODE_RXONLY; - break; - - case S3C2412_IISMOD_MODE_TXONLY: - mod &= ~S3C2412_IISMOD_MODE_MASK; - con &= ~S3C2412_IISCON_IIS_ACTIVE; - break; - - default: - dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n"); - } - - writel(mod, regs + S3C2412_IISMOD); - writel(con, regs + S3C2412_IISCON); - } - - fic = readl(regs + S3C2412_IISFIC); - dbg_showcon(__func__, con); - pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); -} -EXPORT_SYMBOL_GPL(s3c2412_snd_txctrl); - -void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on) -{ - void __iomem *regs = i2s->regs; - u32 fic, con, mod; - - pr_debug("%s(%d)\n", __func__, on); - - fic = readl(regs + S3C2412_IISFIC); - con = readl(regs + S3C2412_IISCON); - mod = readl(regs + S3C2412_IISMOD); - - pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); - - if (on) { - con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE; - con &= ~S3C2412_IISCON_RXDMA_PAUSE; - con &= ~S3C2412_IISCON_RXCH_PAUSE; - - switch (mod & S3C2412_IISMOD_MODE_MASK) { - case S3C2412_IISMOD_MODE_TXRX: - case S3C2412_IISMOD_MODE_RXONLY: - /* do nothing, we are in the right mode */ - break; - - case S3C2412_IISMOD_MODE_TXONLY: - mod &= ~S3C2412_IISMOD_MODE_MASK; - mod |= S3C2412_IISMOD_MODE_TXRX; - break; - - default: - dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n"); - } - - writel(mod, regs + S3C2412_IISMOD); - writel(con, regs + S3C2412_IISCON); - } else { - /* See txctrl notes on FIFOs. */ - - con &= ~S3C2412_IISCON_RXDMA_ACTIVE; - con |= S3C2412_IISCON_RXDMA_PAUSE; - con |= S3C2412_IISCON_RXCH_PAUSE; - - switch (mod & S3C2412_IISMOD_MODE_MASK) { - case S3C2412_IISMOD_MODE_RXONLY: - con &= ~S3C2412_IISCON_IIS_ACTIVE; - mod &= ~S3C2412_IISMOD_MODE_MASK; - break; - - case S3C2412_IISMOD_MODE_TXRX: - mod &= ~S3C2412_IISMOD_MODE_MASK; - mod |= S3C2412_IISMOD_MODE_TXONLY; - break; - - default: - dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n"); - } - - writel(con, regs + S3C2412_IISCON); - writel(mod, regs + S3C2412_IISMOD); - } - - fic = readl(regs + S3C2412_IISFIC); - pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); -} -EXPORT_SYMBOL_GPL(s3c2412_snd_rxctrl); - -/* - * Wait for the LR signal to allow synchronisation to the L/R clock - * from the codec. May only be needed for slave mode. - */ -static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s) -{ - u32 iiscon; - unsigned long timeout = jiffies + msecs_to_jiffies(5); - - pr_debug("Entered %s\n", __func__); - - while (1) { - iiscon = readl(i2s->regs + S3C2412_IISCON); - if (iiscon & S3C2412_IISCON_LRINDEX) - break; - - if (timeout < jiffies) { - printk(KERN_ERR "%s: timeout\n", __func__); - return -ETIMEDOUT; - } - } - - return 0; -} - -/* - * Set S3C2412 I2S DAI format - */ -static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct s3c_i2sv2_info *i2s = to_info(cpu_dai); - u32 iismod; - - pr_debug("Entered %s\n", __func__); - - iismod = readl(i2s->regs + S3C2412_IISMOD); - pr_debug("hw_params r: IISMOD: %x \n", iismod); - -#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) -#define IISMOD_MASTER_MASK S3C2412_IISMOD_MASTER_MASK -#define IISMOD_SLAVE S3C2412_IISMOD_SLAVE -#define IISMOD_MASTER S3C2412_IISMOD_MASTER_INTERNAL -#endif - -#if defined(CONFIG_PLAT_S3C64XX) -/* From Rev1.1 datasheet, we have two master and two slave modes: - * IMS[11:10]: - * 00 = master mode, fed from PCLK - * 01 = master mode, fed from CLKAUDIO - * 10 = slave mode, using PCLK - * 11 = slave mode, using I2SCLK - */ -#define IISMOD_MASTER_MASK (1 << 11) -#define IISMOD_SLAVE (1 << 11) -#define IISMOD_MASTER (0x0) -#endif - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - i2s->master = 0; - iismod &= ~IISMOD_MASTER_MASK; - iismod |= IISMOD_SLAVE; - break; - case SND_SOC_DAIFMT_CBS_CFS: - i2s->master = 1; - iismod &= ~IISMOD_MASTER_MASK; - iismod |= IISMOD_MASTER; - break; - default: - pr_debug("unknwon master/slave format\n"); - return -EINVAL; - } - - iismod &= ~S3C2412_IISMOD_SDF_MASK; - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_RIGHT_J: - iismod |= S3C2412_IISMOD_SDF_MSB; - break; - case SND_SOC_DAIFMT_LEFT_J: - iismod |= S3C2412_IISMOD_SDF_LSB; - break; - case SND_SOC_DAIFMT_I2S: - iismod |= S3C2412_IISMOD_SDF_IIS; - break; - default: - pr_debug("Unknown data format\n"); - return -EINVAL; - } - - writel(iismod, i2s->regs + S3C2412_IISMOD); - pr_debug("hw_params w: IISMOD: %x \n", iismod); - return 0; -} - -static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *socdai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai_link *dai = rtd->dai; - struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai); - u32 iismod; - - pr_debug("Entered %s\n", __func__); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dai->cpu_dai->dma_data = i2s->dma_playback; - else - dai->cpu_dai->dma_data = i2s->dma_capture; - - /* Working copies of register */ - iismod = readl(i2s->regs + S3C2412_IISMOD); - pr_debug("%s: r: IISMOD: %x\n", __func__, iismod); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - iismod |= S3C2412_IISMOD_8BIT; - break; - case SNDRV_PCM_FORMAT_S16_LE: - iismod &= ~S3C2412_IISMOD_8BIT; - break; - } - - writel(iismod, i2s->regs + S3C2412_IISMOD); - pr_debug("%s: w: IISMOD: %x\n", __func__, iismod); - return 0; -} - -static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai); - int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); - unsigned long irqs; - int ret = 0; - - pr_debug("Entered %s\n", __func__); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - /* On start, ensure that the FIFOs are cleared and reset. */ - - writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH, - i2s->regs + S3C2412_IISFIC); - - /* clear again, just in case */ - writel(0x0, i2s->regs + S3C2412_IISFIC); - - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (!i2s->master) { - ret = s3c2412_snd_lrsync(i2s); - if (ret) - goto exit_err; - } - - local_irq_save(irqs); - - if (capture) - s3c2412_snd_rxctrl(i2s, 1); - else - s3c2412_snd_txctrl(i2s, 1); - - local_irq_restore(irqs); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - local_irq_save(irqs); - - if (capture) - s3c2412_snd_rxctrl(i2s, 0); - else - s3c2412_snd_txctrl(i2s, 0); - - local_irq_restore(irqs); - break; - default: - ret = -EINVAL; - break; - } - -exit_err: - return ret; -} - -/* - * Set S3C2412 Clock dividers - */ -static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, - int div_id, int div) -{ - struct s3c_i2sv2_info *i2s = to_info(cpu_dai); - u32 reg; - - pr_debug("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div); - - switch (div_id) { - case S3C_I2SV2_DIV_BCLK: - reg = readl(i2s->regs + S3C2412_IISMOD); - reg &= ~S3C2412_IISMOD_BCLK_MASK; - writel(reg | div, i2s->regs + S3C2412_IISMOD); - - pr_debug("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD)); - break; - - case S3C_I2SV2_DIV_RCLK: - if (div > 3) { - /* convert value to bit field */ - - switch (div) { - case 256: - div = S3C2412_IISMOD_RCLK_256FS; - break; - - case 384: - div = S3C2412_IISMOD_RCLK_384FS; - break; - - case 512: - div = S3C2412_IISMOD_RCLK_512FS; - break; - - case 768: - div = S3C2412_IISMOD_RCLK_768FS; - break; - - default: - return -EINVAL; - } - } - - reg = readl(i2s->regs + S3C2412_IISMOD); - reg &= ~S3C2412_IISMOD_RCLK_MASK; - writel(reg | div, i2s->regs + S3C2412_IISMOD); - pr_debug("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD)); - break; - - case S3C_I2SV2_DIV_PRESCALER: - if (div >= 0) { - writel((div << 8) | S3C2412_IISPSR_PSREN, - i2s->regs + S3C2412_IISPSR); - } else { - writel(0x0, i2s->regs + S3C2412_IISPSR); - } - pr_debug("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR)); - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* default table of all avaialable root fs divisors */ -static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 }; - -int s3c2412_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, - unsigned int *fstab, - unsigned int rate, struct clk *clk) -{ - unsigned long clkrate = clk_get_rate(clk); - unsigned int div; - unsigned int fsclk; - unsigned int actual; - unsigned int fs; - unsigned int fsdiv; - signed int deviation = 0; - unsigned int best_fs = 0; - unsigned int best_div = 0; - unsigned int best_rate = 0; - unsigned int best_deviation = INT_MAX; - - if (fstab == NULL) - fstab = iis_fs_tab; - - for (fs = 0; fs < ARRAY_SIZE(iis_fs_tab); fs++) { - fsdiv = iis_fs_tab[fs]; - - fsclk = clkrate / fsdiv; - div = fsclk / rate; - - if ((fsclk % rate) > (rate / 2)) - div++; - - if (div <= 1) - continue; - - actual = clkrate / (fsdiv * div); - deviation = actual - rate; - - printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n", - fsdiv, div, actual, deviation); - - deviation = abs(deviation); - - if (deviation < best_deviation) { - best_fs = fsdiv; - best_div = div; - best_rate = actual; - best_deviation = deviation; - } - - if (deviation == 0) - break; - } - - printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n", - best_fs, best_div, best_rate); - - info->fs_div = best_fs; - info->clk_div = best_div; - - return 0; -} -EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate); - -int s3c_i2sv2_probe(struct platform_device *pdev, - struct snd_soc_dai *dai, - struct s3c_i2sv2_info *i2s, - unsigned long base) -{ - struct device *dev = &pdev->dev; - - i2s->dev = dev; - - /* record our i2s structure for later use in the callbacks */ - dai->private_data = i2s; - - i2s->regs = ioremap(base, 0x100); - if (i2s->regs == NULL) { - dev_err(dev, "cannot ioremap registers\n"); - return -ENXIO; - } - - i2s->iis_pclk = clk_get(dev, "iis"); - if (i2s->iis_pclk == NULL) { - dev_err(dev, "failed to get iis_clock\n"); - iounmap(i2s->regs); - return -ENOENT; - } - - clk_enable(i2s->iis_pclk); - - s3c2412_snd_txctrl(i2s, 0); - s3c2412_snd_rxctrl(i2s, 0); - - return 0; -} - -EXPORT_SYMBOL_GPL(s3c_i2sv2_probe); - -#ifdef CONFIG_PM -static int s3c2412_i2s_suspend(struct snd_soc_dai *dai) -{ - struct s3c_i2sv2_info *i2s = to_info(dai); - u32 iismod; - - if (dai->active) { - i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD); - i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON); - i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR); - - /* some basic suspend checks */ - - iismod = readl(i2s->regs + S3C2412_IISMOD); - - if (iismod & S3C2412_IISCON_RXDMA_ACTIVE) - pr_warning("%s: RXDMA active?\n", __func__); - - if (iismod & S3C2412_IISCON_TXDMA_ACTIVE) - pr_warning("%s: TXDMA active?\n", __func__); - - if (iismod & S3C2412_IISCON_IIS_ACTIVE) - pr_warning("%s: IIS active\n", __func__); - } - - return 0; -} - -static int s3c2412_i2s_resume(struct snd_soc_dai *dai) -{ - struct s3c_i2sv2_info *i2s = to_info(dai); - - pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n", - dai->active, i2s->suspend_iismod, i2s->suspend_iiscon); - - if (dai->active) { - writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON); - writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD); - writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR); - - writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH, - i2s->regs + S3C2412_IISFIC); - - ndelay(250); - writel(0x0, i2s->regs + S3C2412_IISFIC); - } - - return 0; -} -#else -#define s3c2412_i2s_suspend NULL -#define s3c2412_i2s_resume NULL -#endif - -int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) -{ - dai->ops.trigger = s3c2412_i2s_trigger; - dai->ops.hw_params = s3c2412_i2s_hw_params; - dai->ops.set_fmt = s3c2412_i2s_set_fmt; - dai->ops.set_clkdiv = s3c2412_i2s_set_clkdiv; - - dai->suspend = s3c2412_i2s_suspend; - dai->resume = s3c2412_i2s_resume; - - return snd_soc_register_dai(dai); -} - -EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); diff --git a/trunk/sound/soc/s3c24xx/s3c-i2s-v2.h b/trunk/sound/soc/s3c24xx/s3c-i2s-v2.h deleted file mode 100644 index f66854a77fb2..000000000000 --- a/trunk/sound/soc/s3c24xx/s3c-i2s-v2.h +++ /dev/null @@ -1,90 +0,0 @@ -/* sound/soc/s3c24xx/s3c-i2s-v2.h - * - * ALSA Soc Audio Layer - S3C_I2SV2 I2S driver - * - * Copyright (c) 2007 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. -*/ - -/* This code is the core support for the I2S block found in a number of - * Samsung SoC devices which is unofficially named I2S-V2. Currently the - * S3C2412 and the S3C64XX series use this block to provide 1 or 2 I2S - * channels via configurable GPIO. - */ - -#ifndef __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H -#define __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H __FILE__ - -#define S3C_I2SV2_DIV_BCLK (1) -#define S3C_I2SV2_DIV_RCLK (2) -#define S3C_I2SV2_DIV_PRESCALER (3) - -/** - * struct s3c_i2sv2_info - S3C I2S-V2 information - * @dev: The parent device passed to use from the probe. - * @regs: The pointer to the device registe block. - * @master: True if the I2S core is the I2S bit clock master. - * @dma_playback: DMA information for playback channel. - * @dma_capture: DMA information for capture channel. - * @suspend_iismod: PM save for the IISMOD register. - * @suspend_iiscon: PM save for the IISCON register. - * @suspend_iispsr: PM save for the IISPSR register. - * - * This is the private codec state for the hardware associated with an - * I2S channel such as the register mappings and clock sources. - */ -struct s3c_i2sv2_info { - struct device *dev; - void __iomem *regs; - - struct clk *iis_pclk; - struct clk *iis_cclk; - struct clk *iis_clk; - - unsigned char master; - - struct s3c24xx_pcm_dma_params *dma_playback; - struct s3c24xx_pcm_dma_params *dma_capture; - - u32 suspend_iismod; - u32 suspend_iiscon; - u32 suspend_iispsr; -}; - -struct s3c_i2sv2_rate_calc { - unsigned int clk_div; /* for prescaler */ - unsigned int fs_div; /* for root frame clock */ -}; - -extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info, - unsigned int *fstab, - unsigned int rate, struct clk *clk); - -/** - * s3c_i2sv2_probe - probe for i2s device helper - * @pdev: The platform device supplied to the original probe. - * @dai: The ASoC DAI structure supplied to the original probe. - * @i2s: Our local i2s structure to fill in. - * @base: The base address for the registers. - */ -extern int s3c_i2sv2_probe(struct platform_device *pdev, - struct snd_soc_dai *dai, - struct s3c_i2sv2_info *i2s, - unsigned long base); - -/** - * s3c_i2sv2_register_dai - register dai with soc core - * @dai: The snd_soc_dai structure to register - * - * Fill in any missing fields and then register the given dai with the - * soc core. - */ -extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai); - -#endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ diff --git a/trunk/sound/soc/s3c24xx/s3c2412-i2s.c b/trunk/sound/soc/s3c24xx/s3c2412-i2s.c index 1ceae690d019..382d7eee53ef 100644 --- a/trunk/sound/soc/s3c24xx/s3c2412-i2s.c +++ b/trunk/sound/soc/s3c24xx/s3c2412-i2s.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -31,16 +30,26 @@ #include #include -#include +#include +#include + +#include -#include -#include +#include +#include #include #include "s3c24xx-pcm.h" #include "s3c2412-i2s.h" #define S3C2412_I2S_DEBUG 0 +#define S3C2412_I2S_DEBUG_CON 0 + +#if S3C2412_I2S_DEBUG +#define DBG(x...) printk(KERN_INFO x) +#else +#define DBG(x...) do { } while (0) +#endif static struct s3c2410_dma_client s3c2412_dma_client_out = { .name = "I2S PCM Stereo out" @@ -64,7 +73,431 @@ static struct s3c24xx_pcm_dma_params s3c2412_i2s_pcm_stereo_in = { .dma_size = 4, }; -static struct s3c_i2sv2_info s3c2412_i2s; +struct s3c2412_i2s_info { + struct device *dev; + void __iomem *regs; + struct clk *iis_clk; + struct clk *iis_pclk; + struct clk *iis_cclk; + + u32 suspend_iismod; + u32 suspend_iiscon; + u32 suspend_iispsr; +}; + +static struct s3c2412_i2s_info s3c2412_i2s; + +#define bit_set(v, b) (((v) & (b)) ? 1 : 0) + +#if S3C2412_I2S_DEBUG_CON +static void dbg_showcon(const char *fn, u32 con) +{ + printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d, RXFFULL=%d\n", fn, + bit_set(con, S3C2412_IISCON_LRINDEX), + bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY), + bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY), + bit_set(con, S3C2412_IISCON_TXFIFO_FULL), + bit_set(con, S3C2412_IISCON_RXFIFO_FULL)); + + printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n", + fn, + bit_set(con, S3C2412_IISCON_TXDMA_PAUSE), + bit_set(con, S3C2412_IISCON_RXDMA_PAUSE), + bit_set(con, S3C2412_IISCON_TXCH_PAUSE), + bit_set(con, S3C2412_IISCON_RXCH_PAUSE)); + printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn, + bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE), + bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE), + bit_set(con, S3C2412_IISCON_IIS_ACTIVE)); +} +#else +static inline void dbg_showcon(const char *fn, u32 con) +{ +} +#endif + +/* Turn on or off the transmission path. */ +static void s3c2412_snd_txctrl(int on) +{ + struct s3c2412_i2s_info *i2s = &s3c2412_i2s; + void __iomem *regs = i2s->regs; + u32 fic, con, mod; + + DBG("%s(%d)\n", __func__, on); + + fic = readl(regs + S3C2412_IISFIC); + con = readl(regs + S3C2412_IISCON); + mod = readl(regs + S3C2412_IISMOD); + + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); + + if (on) { + con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE; + con &= ~S3C2412_IISCON_TXDMA_PAUSE; + con &= ~S3C2412_IISCON_TXCH_PAUSE; + + switch (mod & S3C2412_IISMOD_MODE_MASK) { + case S3C2412_IISMOD_MODE_TXONLY: + case S3C2412_IISMOD_MODE_TXRX: + /* do nothing, we are in the right mode */ + break; + + case S3C2412_IISMOD_MODE_RXONLY: + mod &= ~S3C2412_IISMOD_MODE_MASK; + mod |= S3C2412_IISMOD_MODE_TXRX; + break; + + default: + dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n"); + } + + writel(con, regs + S3C2412_IISCON); + writel(mod, regs + S3C2412_IISMOD); + } else { + /* Note, we do not have any indication that the FIFO problems + * tha the S3C2410/2440 had apply here, so we should be able + * to disable the DMA and TX without resetting the FIFOS. + */ + + con |= S3C2412_IISCON_TXDMA_PAUSE; + con |= S3C2412_IISCON_TXCH_PAUSE; + con &= ~S3C2412_IISCON_TXDMA_ACTIVE; + + switch (mod & S3C2412_IISMOD_MODE_MASK) { + case S3C2412_IISMOD_MODE_TXRX: + mod &= ~S3C2412_IISMOD_MODE_MASK; + mod |= S3C2412_IISMOD_MODE_RXONLY; + break; + + case S3C2412_IISMOD_MODE_TXONLY: + mod &= ~S3C2412_IISMOD_MODE_MASK; + con &= ~S3C2412_IISCON_IIS_ACTIVE; + break; + + default: + dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n"); + } + + writel(mod, regs + S3C2412_IISMOD); + writel(con, regs + S3C2412_IISCON); + } + + fic = readl(regs + S3C2412_IISFIC); + dbg_showcon(__func__, con); + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); +} + +static void s3c2412_snd_rxctrl(int on) +{ + struct s3c2412_i2s_info *i2s = &s3c2412_i2s; + void __iomem *regs = i2s->regs; + u32 fic, con, mod; + + DBG("%s(%d)\n", __func__, on); + + fic = readl(regs + S3C2412_IISFIC); + con = readl(regs + S3C2412_IISCON); + mod = readl(regs + S3C2412_IISMOD); + + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); + + if (on) { + con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE; + con &= ~S3C2412_IISCON_RXDMA_PAUSE; + con &= ~S3C2412_IISCON_RXCH_PAUSE; + + switch (mod & S3C2412_IISMOD_MODE_MASK) { + case S3C2412_IISMOD_MODE_TXRX: + case S3C2412_IISMOD_MODE_RXONLY: + /* do nothing, we are in the right mode */ + break; + + case S3C2412_IISMOD_MODE_TXONLY: + mod &= ~S3C2412_IISMOD_MODE_MASK; + mod |= S3C2412_IISMOD_MODE_TXRX; + break; + + default: + dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n"); + } + + writel(mod, regs + S3C2412_IISMOD); + writel(con, regs + S3C2412_IISCON); + } else { + /* See txctrl notes on FIFOs. */ + + con &= ~S3C2412_IISCON_RXDMA_ACTIVE; + con |= S3C2412_IISCON_RXDMA_PAUSE; + con |= S3C2412_IISCON_RXCH_PAUSE; + + switch (mod & S3C2412_IISMOD_MODE_MASK) { + case S3C2412_IISMOD_MODE_RXONLY: + con &= ~S3C2412_IISCON_IIS_ACTIVE; + mod &= ~S3C2412_IISMOD_MODE_MASK; + break; + + case S3C2412_IISMOD_MODE_TXRX: + mod &= ~S3C2412_IISMOD_MODE_MASK; + mod |= S3C2412_IISMOD_MODE_TXONLY; + break; + + default: + dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n"); + } + + writel(con, regs + S3C2412_IISCON); + writel(mod, regs + S3C2412_IISMOD); + } + + fic = readl(regs + S3C2412_IISFIC); + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic); +} + + +/* + * Wait for the LR signal to allow synchronisation to the L/R clock + * from the codec. May only be needed for slave mode. + */ +static int s3c2412_snd_lrsync(void) +{ + u32 iiscon; + unsigned long timeout = jiffies + msecs_to_jiffies(5); + + DBG("Entered %s\n", __func__); + + while (1) { + iiscon = readl(s3c2412_i2s.regs + S3C2412_IISCON); + if (iiscon & S3C2412_IISCON_LRINDEX) + break; + + if (timeout < jiffies) { + printk(KERN_ERR "%s: timeout\n", __func__); + return -ETIMEDOUT; + } + } + + return 0; +} + +/* + * Check whether CPU is the master or slave + */ +static inline int s3c2412_snd_is_clkmaster(void) +{ + u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); + + DBG("Entered %s\n", __func__); + + iismod &= S3C2412_IISMOD_MASTER_MASK; + return !(iismod == S3C2412_IISMOD_SLAVE); +} + +/* + * Set S3C2412 I2S DAI format + */ +static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + u32 iismod; + + + DBG("Entered %s\n", __func__); + + iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); + DBG("hw_params r: IISMOD: %x \n", iismod); + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBM_CFM: + iismod &= ~S3C2412_IISMOD_MASTER_MASK; + iismod |= S3C2412_IISMOD_SLAVE; + break; + case SND_SOC_DAIFMT_CBS_CFS: + iismod &= ~S3C2412_IISMOD_MASTER_MASK; + iismod |= S3C2412_IISMOD_MASTER_INTERNAL; + break; + default: + DBG("unknwon master/slave format\n"); + return -EINVAL; + } + + iismod &= ~S3C2412_IISMOD_SDF_MASK; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_RIGHT_J: + iismod |= S3C2412_IISMOD_SDF_MSB; + break; + case SND_SOC_DAIFMT_LEFT_J: + iismod |= S3C2412_IISMOD_SDF_LSB; + break; + case SND_SOC_DAIFMT_I2S: + iismod |= S3C2412_IISMOD_SDF_IIS; + break; + default: + DBG("Unknown data format\n"); + return -EINVAL; + } + + writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD); + DBG("hw_params w: IISMOD: %x \n", iismod); + return 0; +} + +static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + u32 iismod; + + DBG("Entered %s\n", __func__); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + rtd->dai->cpu_dai->dma_data = &s3c2412_i2s_pcm_stereo_out; + else + rtd->dai->cpu_dai->dma_data = &s3c2412_i2s_pcm_stereo_in; + + /* Working copies of register */ + iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); + DBG("%s: r: IISMOD: %x\n", __func__, iismod); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S8: + iismod |= S3C2412_IISMOD_8BIT; + break; + case SNDRV_PCM_FORMAT_S16_LE: + iismod &= ~S3C2412_IISMOD_8BIT; + break; + } + + writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD); + DBG("%s: w: IISMOD: %x\n", __func__, iismod); + return 0; +} + +static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); + unsigned long irqs; + int ret = 0; + + DBG("Entered %s\n", __func__); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + /* On start, ensure that the FIFOs are cleared and reset. */ + + writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH, + s3c2412_i2s.regs + S3C2412_IISFIC); + + /* clear again, just in case */ + writel(0x0, s3c2412_i2s.regs + S3C2412_IISFIC); + + case SNDRV_PCM_TRIGGER_RESUME: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (!s3c2412_snd_is_clkmaster()) { + ret = s3c2412_snd_lrsync(); + if (ret) + goto exit_err; + } + + local_irq_save(irqs); + + if (capture) + s3c2412_snd_rxctrl(1); + else + s3c2412_snd_txctrl(1); + + local_irq_restore(irqs); + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + local_irq_save(irqs); + + if (capture) + s3c2412_snd_rxctrl(0); + else + s3c2412_snd_txctrl(0); + + local_irq_restore(irqs); + break; + default: + ret = -EINVAL; + break; + } + +exit_err: + return ret; +} + +/* default table of all avaialable root fs divisors */ +static unsigned int s3c2412_iis_fs[] = { 256, 512, 384, 768, 0 }; + +int s3c2412_iis_calc_rate(struct s3c2412_rate_calc *info, + unsigned int *fstab, + unsigned int rate, struct clk *clk) +{ + unsigned long clkrate = clk_get_rate(clk); + unsigned int div; + unsigned int fsclk; + unsigned int actual; + unsigned int fs; + unsigned int fsdiv; + signed int deviation = 0; + unsigned int best_fs = 0; + unsigned int best_div = 0; + unsigned int best_rate = 0; + unsigned int best_deviation = INT_MAX; + + + if (fstab == NULL) + fstab = s3c2412_iis_fs; + + for (fs = 0;; fs++) { + fsdiv = s3c2412_iis_fs[fs]; + + if (fsdiv == 0) + break; + + fsclk = clkrate / fsdiv; + div = fsclk / rate; + + if ((fsclk % rate) > (rate / 2)) + div++; + + if (div <= 1) + continue; + + actual = clkrate / (fsdiv * div); + deviation = actual - rate; + + printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n", + fsdiv, div, actual, deviation); + + deviation = abs(deviation); + + if (deviation < best_deviation) { + best_fs = fsdiv; + best_div = div; + best_rate = actual; + best_deviation = deviation; + } + + if (deviation == 0) + break; + } + + printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n", + best_fs, best_div, best_rate); + + info->fs_div = best_fs; + info->clk_div = best_div; + + return 0; +} +EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate); /* * Set S3C2412 Clock source @@ -74,17 +507,15 @@ static int s3c2412_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, { u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD); - pr_debug("%s(%p, %d, %u, %d)\n", __func__, cpu_dai, clk_id, + DBG("%s(%p, %d, %u, %d)\n", __func__, cpu_dai, clk_id, freq, dir); switch (clk_id) { case S3C2412_CLKSRC_PCLK: - s3c2412_i2s.master = 1; iismod &= ~S3C2412_IISMOD_MASTER_MASK; iismod |= S3C2412_IISMOD_MASTER_INTERNAL; break; case S3C2412_CLKSRC_I2SCLK: - s3c2412_i2s.master = 0; iismod &= ~S3C2412_IISMOD_MASTER_MASK; iismod |= S3C2412_IISMOD_MASTER_EXTERNAL; break; @@ -96,6 +527,74 @@ static int s3c2412_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, return 0; } +/* + * Set S3C2412 Clock dividers + */ +static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, + int div_id, int div) +{ + struct s3c2412_i2s_info *i2s = &s3c2412_i2s; + u32 reg; + + DBG("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div); + + switch (div_id) { + case S3C2412_DIV_BCLK: + reg = readl(i2s->regs + S3C2412_IISMOD); + reg &= ~S3C2412_IISMOD_BCLK_MASK; + writel(reg | div, i2s->regs + S3C2412_IISMOD); + + DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD)); + break; + + case S3C2412_DIV_RCLK: + if (div > 3) { + /* convert value to bit field */ + + switch (div) { + case 256: + div = S3C2412_IISMOD_RCLK_256FS; + break; + + case 384: + div = S3C2412_IISMOD_RCLK_384FS; + break; + + case 512: + div = S3C2412_IISMOD_RCLK_512FS; + break; + + case 768: + div = S3C2412_IISMOD_RCLK_768FS; + break; + + default: + return -EINVAL; + } + } + + reg = readl(s3c2412_i2s.regs + S3C2412_IISMOD); + reg &= ~S3C2412_IISMOD_RCLK_MASK; + writel(reg | div, i2s->regs + S3C2412_IISMOD); + DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD)); + break; + + case S3C2412_DIV_PRESCALER: + if (div >= 0) { + writel((div << 8) | S3C2412_IISPSR_PSREN, + i2s->regs + S3C2412_IISPSR); + } else { + writel(0x0, i2s->regs + S3C2412_IISPSR); + } + DBG("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR)); + break; + + default: + return -EINVAL; + } + + return 0; +} struct clk *s3c2412_get_iisclk(void) { @@ -107,30 +606,34 @@ EXPORT_SYMBOL_GPL(s3c2412_get_iisclk); static int s3c2412_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai) { - int ret; + DBG("Entered %s\n", __func__); - pr_debug("Entered %s\n", __func__); + s3c2412_i2s.dev = &pdev->dev; - ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS); - if (ret) - return ret; + s3c2412_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100); + if (s3c2412_i2s.regs == NULL) + return -ENXIO; - s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; - s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; + s3c2412_i2s.iis_pclk = clk_get(&pdev->dev, "iis"); + if (s3c2412_i2s.iis_pclk == NULL) { + DBG("failed to get iis_clock\n"); + iounmap(s3c2412_i2s.regs); + return -ENODEV; + } s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); if (s3c2412_i2s.iis_cclk == NULL) { - pr_debug("failed to get i2sclk clock\n"); + DBG("failed to get i2sclk clock\n"); iounmap(s3c2412_i2s.regs); return -ENODEV; } - /* Set MPLL as the source for IIS CLK */ - clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll")); + + clk_enable(s3c2412_i2s.iis_pclk); clk_enable(s3c2412_i2s.iis_cclk); - s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk; + s3c2412_i2s.iis_clk = s3c2412_i2s.iis_pclk; /* Configure the I2S pins in correct mode */ s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK); @@ -139,18 +642,86 @@ static int s3c2412_i2s_probe(struct platform_device *pdev, s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI); s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO); + s3c2412_snd_txctrl(0); + s3c2412_snd_rxctrl(0); + return 0; } +#ifdef CONFIG_PM +static int s3c2412_i2s_suspend(struct snd_soc_dai *dai) +{ + struct s3c2412_i2s_info *i2s = &s3c2412_i2s; + u32 iismod; + + if (dai->active) { + i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD); + i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON); + i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR); + + /* some basic suspend checks */ + + iismod = readl(i2s->regs + S3C2412_IISMOD); + + if (iismod & S3C2412_IISCON_RXDMA_ACTIVE) + pr_warning("%s: RXDMA active?\n", __func__); + + if (iismod & S3C2412_IISCON_TXDMA_ACTIVE) + pr_warning("%s: TXDMA active?\n", __func__); + + if (iismod & S3C2412_IISCON_IIS_ACTIVE) + pr_warning("%s: IIS active\n", __func__); + } + + return 0; +} + +static int s3c2412_i2s_resume(struct snd_soc_dai *dai) +{ + struct s3c2412_i2s_info *i2s = &s3c2412_i2s; + + pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n", + dai->active, i2s->suspend_iismod, i2s->suspend_iiscon); + + if (dai->active) { + writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON); + writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD); + writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR); + + writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH, + i2s->regs + S3C2412_IISFIC); + + ndelay(250); + writel(0x0, i2s->regs + S3C2412_IISFIC); + + } + + return 0; +} +#else +#define s3c2412_i2s_suspend NULL +#define s3c2412_i2s_resume NULL +#endif /* CONFIG_PM */ + #define S3C2412_I2S_RATES \ (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) +static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = { + .trigger = s3c2412_i2s_trigger, + .hw_params = s3c2412_i2s_hw_params, + .set_fmt = s3c2412_i2s_set_fmt, + .set_clkdiv = s3c2412_i2s_set_clkdiv, + .set_sysclk = s3c2412_i2s_set_sysclk, +}; + struct snd_soc_dai s3c2412_i2s_dai = { - .name = "s3c2412-i2s", - .id = 0, - .probe = s3c2412_i2s_probe, + .name = "s3c2412-i2s", + .id = 0, + .probe = s3c2412_i2s_probe, + .suspend = s3c2412_i2s_suspend, + .resume = s3c2412_i2s_resume, .playback = { .channels_min = 2, .channels_max = 2, @@ -163,15 +734,13 @@ struct snd_soc_dai s3c2412_i2s_dai = { .rates = S3C2412_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE, }, - .ops = { - .set_sysclk = s3c2412_i2s_set_sysclk, - }, + .ops = &s3c2412_i2s_dai_ops, }; EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); static int __init s3c2412_i2s_init(void) { - return s3c_i2sv2_register_dai(&s3c2412_i2s_dai); + return snd_soc_register_dai(&s3c2412_i2s_dai); } module_init(s3c2412_i2s_init); @@ -181,6 +750,7 @@ static void __exit s3c2412_i2s_exit(void) } module_exit(s3c2412_i2s_exit); + /* Module information */ MODULE_AUTHOR("Ben Dooks, "); MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); diff --git a/trunk/sound/soc/s3c24xx/s3c2412-i2s.h b/trunk/sound/soc/s3c24xx/s3c2412-i2s.h index 92848e54be16..aac08a25e541 100644 --- a/trunk/sound/soc/s3c24xx/s3c2412-i2s.h +++ b/trunk/sound/soc/s3c24xx/s3c2412-i2s.h @@ -15,11 +15,9 @@ #ifndef __SND_SOC_S3C24XX_S3C2412_I2S_H #define __SND_SOC_S3C24XX_S3C2412_I2S_H __FILE__ -#include "s3c-i2s-v2.h" - -#define S3C2412_DIV_BCLK S3C_I2SV2_DIV_BCLK -#define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK -#define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER +#define S3C2412_DIV_BCLK (1) +#define S3C2412_DIV_RCLK (2) +#define S3C2412_DIV_PRESCALER (3) #define S3C2412_CLKSRC_PCLK (0) #define S3C2412_CLKSRC_I2SCLK (1) @@ -28,4 +26,13 @@ extern struct clk *s3c2412_get_iisclk(void); extern struct snd_soc_dai s3c2412_i2s_dai; +struct s3c2412_rate_calc { + unsigned int clk_div; /* for prescaler */ + unsigned int fs_div; /* for root frame clock */ +}; + +extern int s3c2412_iis_calc_rate(struct s3c2412_rate_calc *info, + unsigned int *fstab, + unsigned int rate, struct clk *clk); + #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */ diff --git a/trunk/sound/soc/s3c24xx/s3c2443-ac97.c b/trunk/sound/soc/s3c24xx/s3c2443-ac97.c index 5c7f18a22645..83ea623234e7 100644 --- a/trunk/sound/soc/s3c24xx/s3c2443-ac97.c +++ b/trunk/sound/soc/s3c24xx/s3c2443-ac97.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include @@ -355,6 +355,11 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) +static struct snd_soc_dai_ops s3c2443_ac97_dai_ops = { + .hw_params = s3c2443_ac97_hw_params, + .trigger = s3c2443_ac97_trigger, +}; + struct snd_soc_dai s3c2443_ac97_dai[] = { { .name = "s3c2443-ac97", @@ -374,9 +379,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = { .channels_max = 2, .rates = s3c2443_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .hw_params = s3c2443_ac97_hw_params, - .trigger = s3c2443_ac97_trigger}, + .ops = &s3c2443_ac97_dai_ops, }, { .name = "pxa2xx-ac97-mic", @@ -388,9 +391,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = { .channels_max = 1, .rates = s3c2443_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .hw_params = s3c2443_ac97_hw_mic_params, - .trigger = s3c2443_ac97_mic_trigger,}, + .ops = &s3c2443_ac97_dai_ops, }, }; EXPORT_SYMBOL_GPL(s3c2443_ac97_dai); diff --git a/trunk/sound/soc/s3c24xx/s3c24xx-i2s.c b/trunk/sound/soc/s3c24xx/s3c24xx-i2s.c index 407ccd7180fe..4473fb584c4c 100644 --- a/trunk/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/trunk/sound/soc/s3c24xx/s3c24xx-i2s.c @@ -30,15 +30,22 @@ #include #include #include -#include +#include #include #include -#include +#include #include "s3c24xx-pcm.h" #include "s3c24xx-i2s.h" +#define S3C24XX_I2S_DEBUG 0 +#if S3C24XX_I2S_DEBUG +#define DBG(x...) printk(KERN_DEBUG "s3c24xx-i2s: " x) +#else +#define DBG(x...) +#endif + static struct s3c2410_dma_client s3c24xx_dma_client_out = { .name = "I2S PCM Stereo out" }; @@ -77,13 +84,13 @@ static void s3c24xx_snd_txctrl(int on) u32 iiscon; u32 iismod; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("r: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); + DBG("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); if (on) { iisfcon |= S3C2410_IISFCON_TXDMA | S3C2410_IISFCON_TXENABLE; @@ -113,7 +120,7 @@ static void s3c24xx_snd_txctrl(int on) writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); } - pr_debug("w: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); + DBG("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); } static void s3c24xx_snd_rxctrl(int on) @@ -122,13 +129,13 @@ static void s3c24xx_snd_rxctrl(int on) u32 iiscon; u32 iismod; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON); iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("r: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); + DBG("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); if (on) { iisfcon |= S3C2410_IISFCON_RXDMA | S3C2410_IISFCON_RXENABLE; @@ -158,7 +165,7 @@ static void s3c24xx_snd_rxctrl(int on) writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); } - pr_debug("w: IISCON: %x IISMOD: %x IISFCON: %x\n", iiscon, iismod, iisfcon); + DBG("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon); } /* @@ -170,7 +177,7 @@ static int s3c24xx_snd_lrsync(void) u32 iiscon; int timeout = 50; /* 5ms */ - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); while (1) { iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); @@ -190,7 +197,7 @@ static int s3c24xx_snd_lrsync(void) */ static inline int s3c24xx_snd_is_clkmaster(void) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1; } @@ -203,10 +210,10 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, { u32 iismod; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("hw_params r: IISMOD: %x \n", iismod); + DBG("hw_params r: IISMOD: %lx \n", iismod); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: @@ -231,7 +238,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, } writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("hw_params w: IISMOD: %x \n", iismod); + DBG("hw_params w: IISMOD: %lx \n", iismod); return 0; } @@ -242,7 +249,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; u32 iismod; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out; @@ -251,7 +258,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, /* Working copies of register */ iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("hw_params r: IISMOD: %x\n", iismod); + DBG("hw_params r: IISMOD: %lx\n", iismod); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: @@ -269,7 +276,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, } writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("hw_params w: IISMOD: %x\n", iismod); + DBG("hw_params w: IISMOD: %lx\n", iismod); return 0; } @@ -278,7 +285,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, { int ret = 0; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -320,7 +327,7 @@ static int s3c24xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, { u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); iismod &= ~S3C2440_IISMOD_MPLL; @@ -346,7 +353,7 @@ static int s3c24xx_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, { u32 reg; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); switch (div_id) { case S3C24XX_DIV_BCLK: @@ -382,7 +389,7 @@ EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); static int s3c24xx_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100); if (s3c24xx_i2s.regs == NULL) @@ -390,7 +397,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev, s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis"); if (s3c24xx_i2s.iis_clk == NULL) { - pr_err("failed to get iis_clock\n"); + DBG("failed to get iis_clock\n"); iounmap(s3c24xx_i2s.regs); return -ENODEV; } @@ -414,7 +421,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev, #ifdef CONFIG_PM static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); s3c24xx_i2s.iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON); s3c24xx_i2s.iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); @@ -428,7 +435,7 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) { - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); clk_enable(s3c24xx_i2s.iis_clk); writel(s3c24xx_i2s.iiscon, s3c24xx_i2s.regs + S3C2410_IISCON); @@ -449,6 +456,14 @@ static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) +static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = { + .trigger = s3c24xx_i2s_trigger, + .hw_params = s3c24xx_i2s_hw_params, + .set_fmt = s3c24xx_i2s_set_fmt, + .set_clkdiv = s3c24xx_i2s_set_clkdiv, + .set_sysclk = s3c24xx_i2s_set_sysclk, +}; + struct snd_soc_dai s3c24xx_i2s_dai = { .name = "s3c24xx-i2s", .id = 0, @@ -465,13 +480,7 @@ struct snd_soc_dai s3c24xx_i2s_dai = { .channels_max = 2, .rates = S3C24XX_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = { - .trigger = s3c24xx_i2s_trigger, - .hw_params = s3c24xx_i2s_hw_params, - .set_fmt = s3c24xx_i2s_set_fmt, - .set_clkdiv = s3c24xx_i2s_set_clkdiv, - .set_sysclk = s3c24xx_i2s_set_sysclk, - }, + .ops = &s3c24xx_i2s_dai_ops, }; EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); diff --git a/trunk/sound/soc/s3c24xx/s3c24xx-pcm.c b/trunk/sound/soc/s3c24xx/s3c24xx-pcm.c index a9d68fa2b34a..ba1ae09dfaed 100644 --- a/trunk/sound/soc/s3c24xx/s3c24xx-pcm.c +++ b/trunk/sound/soc/s3c24xx/s3c24xx-pcm.c @@ -29,10 +29,17 @@ #include #include #include -#include +#include #include "s3c24xx-pcm.h" +#define S3C24XX_PCM_DEBUG 0 +#if S3C24XX_PCM_DEBUG +#define DBG(x...) printk(KERN_DEBUG "s3c24xx-pcm: " x) +#else +#define DBG(x...) +#endif + static const struct snd_pcm_hardware s3c24xx_pcm_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -77,16 +84,16 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream) dma_addr_t pos = prtd->dma_pos; int ret; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); while (prtd->dma_loaded < prtd->dma_limit) { unsigned long len = prtd->dma_period; - pr_debug("dma_loaded: %d\n", prtd->dma_loaded); + DBG("dma_loaded: %d\n", prtd->dma_loaded); if ((pos + len) > prtd->dma_end) { len = prtd->dma_end - pos; - pr_debug(KERN_DEBUG "%s: corrected dma len %ld\n", + DBG(KERN_DEBUG "%s: corrected dma len %ld\n", __func__, len); } @@ -112,7 +119,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel, struct snd_pcm_substream *substream = dev_id; struct s3c24xx_runtime_data *prtd; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR) return; @@ -141,7 +148,7 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream, unsigned long totbytes = params_buffer_bytes(params); int ret = 0; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); /* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ @@ -154,14 +161,14 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream, /* prepare DMA */ prtd->params = dma; - pr_debug("params %p, client %p, channel %d\n", prtd->params, + DBG("params %p, client %p, channel %d\n", prtd->params, prtd->params->client, prtd->params->channel); ret = s3c2410_dma_request(prtd->params->channel, prtd->params->client, NULL); if (ret < 0) { - printk(KERN_ERR "failed to get dma channel\n"); + DBG(KERN_ERR "failed to get dma channel\n"); return ret; } } @@ -189,7 +196,7 @@ static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream) { struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); /* TODO - do we need to ensure DMA flushed */ snd_pcm_set_runtime_buffer(substream, NULL); @@ -207,7 +214,7 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream) struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; int ret = 0; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); /* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ @@ -252,7 +259,7 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; int ret = 0; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); spin_lock(&prtd->lock); @@ -290,7 +297,7 @@ s3c24xx_pcm_pointer(struct snd_pcm_substream *substream) unsigned long res; dma_addr_t src, dst; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); spin_lock(&prtd->lock); s3c2410_dma_getposition(prtd->params->channel, &src, &dst); @@ -302,7 +309,7 @@ s3c24xx_pcm_pointer(struct snd_pcm_substream *substream) spin_unlock(&prtd->lock); - pr_debug("Pointer %x %x\n", src, dst); + DBG("Pointer %x %x\n", src, dst); /* we seem to be getting the odd error from the pcm library due * to out-of-bounds pointers. this is maybe due to the dma engine @@ -323,7 +330,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct s3c24xx_runtime_data *prtd; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware); @@ -342,10 +349,10 @@ static int s3c24xx_pcm_close(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct s3c24xx_runtime_data *prtd = runtime->private_data; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); if (!prtd) - pr_debug("s3c24xx_pcm_close called with prtd == NULL\n"); + DBG("s3c24xx_pcm_close called with prtd == NULL\n"); kfree(prtd); @@ -357,7 +364,7 @@ static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); return dma_mmap_writecombine(substream->pcm->card->dev, vma, runtime->dma_area, @@ -383,7 +390,7 @@ static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) struct snd_dma_buffer *buf = &substream->dma_buffer; size_t size = s3c24xx_pcm_hardware.buffer_bytes_max; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); buf->dev.type = SNDRV_DMA_TYPE_DEV; buf->dev.dev = pcm->card->dev; @@ -402,7 +409,7 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm) struct snd_dma_buffer *buf; int stream; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); for (stream = 0; stream < 2; stream++) { substream = pcm->streams[stream].substream; @@ -426,7 +433,7 @@ static int s3c24xx_pcm_new(struct snd_card *card, { int ret = 0; - pr_debug("Entered %s\n", __func__); + DBG("Entered %s\n", __func__); if (!card->dev->dma_mask) card->dev->dma_mask = &s3c24xx_pcm_dmamask; diff --git a/trunk/sound/soc/s3c24xx/s3c24xx_uda134x.c b/trunk/sound/soc/s3c24xx/s3c24xx_uda134x.c index 8e79a416db57..a0a4d1832a14 100644 --- a/trunk/sound/soc/s3c24xx/s3c24xx_uda134x.c +++ b/trunk/sound/soc/s3c24xx/s3c24xx_uda134x.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include "s3c24xx-pcm.h" #include "s3c24xx-i2s.h" diff --git a/trunk/sound/soc/s3c24xx/s3c64xx-i2s.c b/trunk/sound/soc/s3c24xx/s3c64xx-i2s.c deleted file mode 100644 index 6e1e85dc1ff2..000000000000 --- a/trunk/sound/soc/s3c24xx/s3c64xx-i2s.c +++ /dev/null @@ -1,220 +0,0 @@ -/* sound/soc/s3c24xx/s3c64xx-i2s.c - * - * ALSA SoC Audio Layer - S3C64XX I2S driver - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * Ben Dooks - * http://armlinux.simtec.co.uk/ - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "s3c24xx-pcm.h" -#include "s3c64xx-i2s.h" - -static struct s3c2410_dma_client s3c64xx_dma_client_out = { - .name = "I2S PCM Stereo out" -}; - -static struct s3c2410_dma_client s3c64xx_dma_client_in = { - .name = "I2S PCM Stereo in" -}; - -static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_out[2] = { - [0] = { - .channel = DMACH_I2S0_OUT, - .client = &s3c64xx_dma_client_out, - .dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD, - .dma_size = 4, - }, - [1] = { - .channel = DMACH_I2S1_OUT, - .client = &s3c64xx_dma_client_out, - .dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD, - .dma_size = 4, - }, -}; - -static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_in[2] = { - [0] = { - .channel = DMACH_I2S0_IN, - .client = &s3c64xx_dma_client_in, - .dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD, - .dma_size = 4, - }, - [1] = { - .channel = DMACH_I2S1_IN, - .client = &s3c64xx_dma_client_in, - .dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD, - .dma_size = 4, - }, -}; - -static struct s3c_i2sv2_info s3c64xx_i2s[2]; - -static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) -{ - return cpu_dai->private_data; -} - -static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir) -{ - struct s3c_i2sv2_info *i2s = to_info(cpu_dai); - u32 iismod = readl(i2s->regs + S3C2412_IISMOD); - - switch (clk_id) { - case S3C64XX_CLKSRC_PCLK: - iismod &= ~S3C64XX_IISMOD_IMS_SYSMUX; - break; - - case S3C64XX_CLKSRC_MUX: - iismod |= S3C64XX_IISMOD_IMS_SYSMUX; - break; - - default: - return -EINVAL; - } - - writel(iismod, i2s->regs + S3C2412_IISMOD); - - return 0; -} - - -unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *dai) -{ - struct s3c_i2sv2_info *i2s = to_info(dai); - - return clk_get_rate(i2s->iis_cclk); -} -EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clockrate); - -static int s3c64xx_i2s_probe(struct platform_device *pdev, - struct snd_soc_dai *dai) -{ - struct device *dev = &pdev->dev; - struct s3c_i2sv2_info *i2s; - int ret; - - dev_dbg(dev, "%s: probing dai %d\n", __func__, pdev->id); - - if (pdev->id < 0 || pdev->id > ARRAY_SIZE(s3c64xx_i2s)) { - dev_err(dev, "id %d out of range\n", pdev->id); - return -EINVAL; - } - - i2s = &s3c64xx_i2s[pdev->id]; - - ret = s3c_i2sv2_probe(pdev, dai, i2s, - pdev->id ? S3C64XX_PA_IIS1 : S3C64XX_PA_IIS0); - if (ret) - return ret; - - i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; - i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; - - i2s->iis_cclk = clk_get(dev, "audio-bus"); - if (IS_ERR(i2s->iis_cclk)) { - dev_err(dev, "failed to get audio-bus"); - iounmap(i2s->regs); - return -ENODEV; - } - - /* configure GPIO for i2s port */ - switch (pdev->id) { - case 0: - s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); - s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); - s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK); - s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI); - s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0); - break; - case 1: - s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK); - s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK); - s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK); - s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI); - s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0); - } - - return 0; -} - - -#define S3C64XX_I2S_RATES \ - (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ - SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) - -#define S3C64XX_I2S_FMTS \ - (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE) - -struct snd_soc_dai s3c64xx_i2s_dai = { - .name = "s3c64xx-i2s", - .id = 0, - .probe = s3c64xx_i2s_probe, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = S3C64XX_I2S_RATES, - .formats = S3C64XX_I2S_FMTS, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = S3C64XX_I2S_RATES, - .formats = S3C64XX_I2S_FMTS, - }, - .ops = { - .set_sysclk = s3c64xx_i2s_set_sysclk, - }, -}; -EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); - -static int __init s3c64xx_i2s_init(void) -{ - return s3c_i2sv2_register_dai(&s3c64xx_i2s_dai); -} -module_init(s3c64xx_i2s_init); - -static void __exit s3c64xx_i2s_exit(void) -{ - snd_soc_unregister_dai(&s3c64xx_i2s_dai); -} -module_exit(s3c64xx_i2s_exit); - -/* Module information */ -MODULE_AUTHOR("Ben Dooks, "); -MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); -MODULE_LICENSE("GPL"); - - - diff --git a/trunk/sound/soc/s3c24xx/s3c64xx-i2s.h b/trunk/sound/soc/s3c24xx/s3c64xx-i2s.h deleted file mode 100644 index b7ffe3c38b66..000000000000 --- a/trunk/sound/soc/s3c24xx/s3c64xx-i2s.h +++ /dev/null @@ -1,31 +0,0 @@ -/* sound/soc/s3c24xx/s3c64xx-i2s.h - * - * ALSA SoC Audio Layer - S3C64XX I2S driver - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * Ben Dooks - * http://armlinux.simtec.co.uk/ - * - * 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. - */ - -#ifndef __SND_SOC_S3C24XX_S3C64XX_I2S_H -#define __SND_SOC_S3C24XX_S3C64XX_I2S_H __FILE__ - -#include "s3c-i2s-v2.h" - -#define S3C64XX_DIV_BCLK S3C_I2SV2_DIV_BCLK -#define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK -#define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER - -#define S3C64XX_CLKSRC_PCLK (0) -#define S3C64XX_CLKSRC_MUX (1) - -extern struct snd_soc_dai s3c64xx_i2s_dai; - -extern unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *cpu_dai); - -#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ diff --git a/trunk/sound/soc/sh/ssi.c b/trunk/sound/soc/sh/ssi.c index d1e5390fddeb..56fa0872abbb 100644 --- a/trunk/sound/soc/sh/ssi.c +++ b/trunk/sound/soc/sh/ssi.c @@ -336,6 +336,16 @@ static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) +static struct snd_soc_dai_ops ssi_dai_ops = { + .startup = ssi_startup, + .shutdown = ssi_shutdown, + .trigger = ssi_trigger, + .hw_params = ssi_hw_params, + .set_sysclk = ssi_set_sysclk, + .set_clkdiv = ssi_set_clkdiv, + .set_fmt = ssi_set_fmt, +}; + struct snd_soc_dai sh4_ssi_dai[] = { { .name = "SSI0", @@ -352,15 +362,7 @@ struct snd_soc_dai sh4_ssi_dai[] = { .channels_min = 2, .channels_max = 8, }, - .ops = { - .startup = ssi_startup, - .shutdown = ssi_shutdown, - .trigger = ssi_trigger, - .hw_params = ssi_hw_params, - .set_sysclk = ssi_set_sysclk, - .set_clkdiv = ssi_set_clkdiv, - .set_fmt = ssi_set_fmt, - }, + .ops = &ssi_dai_ops, }, #ifdef CONFIG_CPU_SUBTYPE_SH7760 { @@ -378,15 +380,7 @@ struct snd_soc_dai sh4_ssi_dai[] = { .channels_min = 2, .channels_max = 8, }, - .ops = { - .startup = ssi_startup, - .shutdown = ssi_shutdown, - .trigger = ssi_trigger, - .hw_params = ssi_hw_params, - .set_sysclk = ssi_set_sysclk, - .set_clkdiv = ssi_set_clkdiv, - .set_fmt = ssi_set_fmt, - }, + .ops = &ssi_dai_ops, }, #endif }; diff --git a/trunk/sound/soc/soc-core.c b/trunk/sound/soc/soc-core.c index d4b90d82a098..16518329f6b2 100644 --- a/trunk/sound/soc/soc-core.c +++ b/trunk/sound/soc/soc-core.c @@ -133,8 +133,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) mutex_lock(&pcm_mutex); /* startup the audio subsystem */ - if (cpu_dai->ops.startup) { - ret = cpu_dai->ops.startup(substream, cpu_dai); + if (cpu_dai->ops->startup) { + ret = cpu_dai->ops->startup(substream, cpu_dai); if (ret < 0) { printk(KERN_ERR "asoc: can't open interface %s\n", cpu_dai->name); @@ -150,8 +150,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) } } - if (codec_dai->ops.startup) { - ret = codec_dai->ops.startup(substream, codec_dai); + if (codec_dai->ops->startup) { + ret = codec_dai->ops->startup(substream, codec_dai); if (ret < 0) { printk(KERN_ERR "asoc: can't open codec %s\n", codec_dai->name); @@ -247,8 +247,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) platform->pcm_ops->close(substream); platform_err: - if (cpu_dai->ops.shutdown) - cpu_dai->ops.shutdown(substream, cpu_dai); + if (cpu_dai->ops->shutdown) + cpu_dai->ops->shutdown(substream, cpu_dai); out: mutex_unlock(&pcm_mutex); return ret; @@ -340,11 +340,11 @@ static int soc_codec_close(struct snd_pcm_substream *substream) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) snd_soc_dai_digital_mute(codec_dai, 1); - if (cpu_dai->ops.shutdown) - cpu_dai->ops.shutdown(substream, cpu_dai); + if (cpu_dai->ops->shutdown) + cpu_dai->ops->shutdown(substream, cpu_dai); - if (codec_dai->ops.shutdown) - codec_dai->ops.shutdown(substream, codec_dai); + if (codec_dai->ops->shutdown) + codec_dai->ops->shutdown(substream, codec_dai); if (machine->ops && machine->ops->shutdown) machine->ops->shutdown(substream); @@ -408,16 +408,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) } } - if (codec_dai->ops.prepare) { - ret = codec_dai->ops.prepare(substream, codec_dai); + if (codec_dai->ops->prepare) { + ret = codec_dai->ops->prepare(substream, codec_dai); if (ret < 0) { printk(KERN_ERR "asoc: codec DAI prepare error\n"); goto out; } } - if (cpu_dai->ops.prepare) { - ret = cpu_dai->ops.prepare(substream, cpu_dai); + if (cpu_dai->ops->prepare) { + ret = cpu_dai->ops->prepare(substream, cpu_dai); if (ret < 0) { printk(KERN_ERR "asoc: cpu DAI prepare error\n"); goto out; @@ -494,8 +494,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, } } - if (codec_dai->ops.hw_params) { - ret = codec_dai->ops.hw_params(substream, params, codec_dai); + if (codec_dai->ops->hw_params) { + ret = codec_dai->ops->hw_params(substream, params, codec_dai); if (ret < 0) { printk(KERN_ERR "asoc: can't set codec %s hw params\n", codec_dai->name); @@ -503,8 +503,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, } } - if (cpu_dai->ops.hw_params) { - ret = cpu_dai->ops.hw_params(substream, params, cpu_dai); + if (cpu_dai->ops->hw_params) { + ret = cpu_dai->ops->hw_params(substream, params, cpu_dai); if (ret < 0) { printk(KERN_ERR "asoc: interface %s hw params failed\n", cpu_dai->name); @@ -526,12 +526,12 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, return ret; platform_err: - if (cpu_dai->ops.hw_free) - cpu_dai->ops.hw_free(substream, cpu_dai); + if (cpu_dai->ops->hw_free) + cpu_dai->ops->hw_free(substream, cpu_dai); interface_err: - if (codec_dai->ops.hw_free) - codec_dai->ops.hw_free(substream, codec_dai); + if (codec_dai->ops->hw_free) + codec_dai->ops->hw_free(substream, codec_dai); codec_err: if (machine->ops && machine->ops->hw_free) @@ -570,11 +570,11 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) platform->pcm_ops->hw_free(substream); /* now free hw params for the DAI's */ - if (codec_dai->ops.hw_free) - codec_dai->ops.hw_free(substream, codec_dai); + if (codec_dai->ops->hw_free) + codec_dai->ops->hw_free(substream, codec_dai); - if (cpu_dai->ops.hw_free) - cpu_dai->ops.hw_free(substream, cpu_dai); + if (cpu_dai->ops->hw_free) + cpu_dai->ops->hw_free(substream, cpu_dai); mutex_unlock(&pcm_mutex); return 0; @@ -591,8 +591,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_soc_dai *codec_dai = machine->codec_dai; int ret; - if (codec_dai->ops.trigger) { - ret = codec_dai->ops.trigger(substream, cmd, codec_dai); + if (codec_dai->ops->trigger) { + ret = codec_dai->ops->trigger(substream, cmd, codec_dai); if (ret < 0) return ret; } @@ -603,8 +603,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return ret; } - if (cpu_dai->ops.trigger) { - ret = cpu_dai->ops.trigger(substream, cmd, cpu_dai); + if (cpu_dai->ops->trigger) { + ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai); if (ret < 0) return ret; } @@ -645,8 +645,8 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) /* mute any active DAC's */ for (i = 0; i < card->num_links; i++) { struct snd_soc_dai *dai = card->dai_link[i].codec_dai; - if (dai->ops.digital_mute && dai->playback.active) - dai->ops.digital_mute(dai, 1); + if (dai->ops->digital_mute && dai->playback.active) + dai->ops->digital_mute(dai, 1); } /* suspend all pcms */ @@ -741,8 +741,8 @@ static void soc_resume_deferred(struct work_struct *work) /* unmute any active DACs */ for (i = 0; i < card->num_links; i++) { struct snd_soc_dai *dai = card->dai_link[i].codec_dai; - if (dai->ops.digital_mute && dai->playback.active) - dai->ops.digital_mute(dai, 0); + if (dai->ops->digital_mute && dai->playback.active) + dai->ops->digital_mute(dai, 0); } for (i = 0; i < card->num_links; i++) { @@ -2051,8 +2051,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { - if (dai->ops.set_sysclk) - return dai->ops.set_sysclk(dai, clk_id, freq, dir); + if (dai->ops->set_sysclk) + return dai->ops->set_sysclk(dai, clk_id, freq, dir); else return -EINVAL; } @@ -2071,8 +2071,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) { - if (dai->ops.set_clkdiv) - return dai->ops.set_clkdiv(dai, div_id, div); + if (dai->ops->set_clkdiv) + return dai->ops->set_clkdiv(dai, div_id, div); else return -EINVAL; } @@ -2090,8 +2090,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, unsigned int freq_in, unsigned int freq_out) { - if (dai->ops.set_pll) - return dai->ops.set_pll(dai, pll_id, freq_in, freq_out); + if (dai->ops->set_pll) + return dai->ops->set_pll(dai, pll_id, freq_in, freq_out); else return -EINVAL; } @@ -2106,8 +2106,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); */ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) { - if (dai->ops.set_fmt) - return dai->ops.set_fmt(dai, fmt); + if (dai->ops->set_fmt) + return dai->ops->set_fmt(dai, fmt); else return -EINVAL; } @@ -2125,8 +2125,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int mask, int slots) { - if (dai->ops.set_sysclk) - return dai->ops.set_tdm_slot(dai, mask, slots); + if (dai->ops->set_sysclk) + return dai->ops->set_tdm_slot(dai, mask, slots); else return -EINVAL; } @@ -2141,8 +2141,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); */ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) { - if (dai->ops.set_sysclk) - return dai->ops.set_tristate(dai, tristate); + if (dai->ops->set_sysclk) + return dai->ops->set_tristate(dai, tristate); else return -EINVAL; } @@ -2157,8 +2157,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); */ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) { - if (dai->ops.digital_mute) - return dai->ops.digital_mute(dai, mute); + if (dai->ops->digital_mute) + return dai->ops->digital_mute(dai, mute); else return -EINVAL; } @@ -2211,6 +2211,9 @@ static int snd_soc_unregister_card(struct snd_soc_card *card) return 0; } +static struct snd_soc_dai_ops null_dai_ops = { +}; + /** * snd_soc_register_dai - Register a DAI with the ASoC core * @@ -2225,6 +2228,9 @@ int snd_soc_register_dai(struct snd_soc_dai *dai) if (!dai->dev) printk(KERN_WARNING "No device for DAI %s\n", dai->name); + if (!dai->ops) + dai->ops = &null_dai_ops; + INIT_LIST_HEAD(&dai->list); mutex_lock(&client_mutex); diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index 735903a74675..4b8dbbfe2efb 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -332,7 +332,7 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, * kcontrol name. */ name_len = strlen(w->kcontrols[i].name) + 1; - if (w->id != snd_soc_dapm_mixer_named_ctl) + if (w->id == snd_soc_dapm_mixer) name_len += 1 + strlen(w->name); path->long_name = kmalloc(name_len, GFP_KERNEL); @@ -341,14 +341,15 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, return -ENOMEM; switch (w->id) { + case snd_soc_dapm_mixer: default: snprintf(path->long_name, name_len, "%s %s", w->name, w->kcontrols[i].name); - break; + break; case snd_soc_dapm_mixer_named_ctl: snprintf(path->long_name, name_len, "%s", w->kcontrols[i].name); - break; + break; } path->long_name[name_len - 1] = '\0'; @@ -521,137 +522,6 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w, } EXPORT_SYMBOL_GPL(dapm_reg_event); -/* - * Scan a single DAPM widget for a complete audio path and update the - * power status appropriately. - */ -static int dapm_power_widget(struct snd_soc_codec *codec, int event, - struct snd_soc_dapm_widget *w) -{ - int in, out, power_change, power, ret; - - /* vmid - no action */ - if (w->id == snd_soc_dapm_vmid) - return 0; - - /* active ADC */ - if (w->id == snd_soc_dapm_adc && w->active) { - in = is_connected_input_ep(w); - dapm_clear_walk(w->codec); - w->power = (in != 0) ? 1 : 0; - dapm_update_bits(w); - return 0; - } - - /* active DAC */ - if (w->id == snd_soc_dapm_dac && w->active) { - out = is_connected_output_ep(w); - dapm_clear_walk(w->codec); - w->power = (out != 0) ? 1 : 0; - dapm_update_bits(w); - return 0; - } - - /* pre and post event widgets */ - if (w->id == snd_soc_dapm_pre) { - if (!w->event) - return 0; - - if (event == SND_SOC_DAPM_STREAM_START) { - ret = w->event(w, - NULL, SND_SOC_DAPM_PRE_PMU); - if (ret < 0) - return ret; - } else if (event == SND_SOC_DAPM_STREAM_STOP) { - ret = w->event(w, - NULL, SND_SOC_DAPM_PRE_PMD); - if (ret < 0) - return ret; - } - return 0; - } - if (w->id == snd_soc_dapm_post) { - if (!w->event) - return 0; - - if (event == SND_SOC_DAPM_STREAM_START) { - ret = w->event(w, - NULL, SND_SOC_DAPM_POST_PMU); - if (ret < 0) - return ret; - } else if (event == SND_SOC_DAPM_STREAM_STOP) { - ret = w->event(w, - NULL, SND_SOC_DAPM_POST_PMD); - if (ret < 0) - return ret; - } - return 0; - } - - /* all other widgets */ - in = is_connected_input_ep(w); - dapm_clear_walk(w->codec); - out = is_connected_output_ep(w); - dapm_clear_walk(w->codec); - power = (out != 0 && in != 0) ? 1 : 0; - power_change = (w->power == power) ? 0 : 1; - w->power = power; - - if (!power_change) - return 0; - - /* call any power change event handlers */ - if (w->event) - pr_debug("power %s event for %s flags %x\n", - w->power ? "on" : "off", - w->name, w->event_flags); - - /* power up pre event */ - if (power && w->event && - (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { - ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); - if (ret < 0) - return ret; - } - - /* power down pre event */ - if (!power && w->event && - (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { - ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); - if (ret < 0) - return ret; - } - - /* Lower PGA volume to reduce pops */ - if (w->id == snd_soc_dapm_pga && !power) - dapm_set_pga(w, power); - - dapm_update_bits(w); - - /* Raise PGA volume to reduce pops */ - if (w->id == snd_soc_dapm_pga && power) - dapm_set_pga(w, power); - - /* power up post event */ - if (power && w->event && - (w->event_flags & SND_SOC_DAPM_POST_PMU)) { - ret = w->event(w, - NULL, SND_SOC_DAPM_POST_PMU); - if (ret < 0) - return ret; - } - - /* power down post event */ - if (!power && w->event && - (w->event_flags & SND_SOC_DAPM_POST_PMD)) { - ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); - if (ret < 0) - return ret; - } - - return 0; -} - /* * Scan each dapm widget for complete audio path. * A complete path is a route that has valid endpoints i.e.:- @@ -664,7 +534,7 @@ static int dapm_power_widget(struct snd_soc_codec *codec, int event, static int dapm_power_widgets(struct snd_soc_codec *codec, int event) { struct snd_soc_dapm_widget *w; - int i, c = 1, *seq = NULL, ret = 0; + int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power; /* do we have a sequenced stream event */ if (event == SND_SOC_DAPM_STREAM_START) { @@ -675,20 +545,135 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) seq = dapm_down_seq; } - for (i = 0; i < c; i++) { + for(i = 0; i < c; i++) { list_for_each_entry(w, &codec->dapm_widgets, list) { /* is widget in stream order */ if (seq && seq[i] && w->id != seq[i]) continue; - ret = dapm_power_widget(codec, event, w); - if (ret != 0) - return ret; + /* vmid - no action */ + if (w->id == snd_soc_dapm_vmid) + continue; + + /* active ADC */ + if (w->id == snd_soc_dapm_adc && w->active) { + in = is_connected_input_ep(w); + dapm_clear_walk(w->codec); + w->power = (in != 0) ? 1 : 0; + dapm_update_bits(w); + continue; + } + + /* active DAC */ + if (w->id == snd_soc_dapm_dac && w->active) { + out = is_connected_output_ep(w); + dapm_clear_walk(w->codec); + w->power = (out != 0) ? 1 : 0; + dapm_update_bits(w); + continue; + } + + /* pre and post event widgets */ + if (w->id == snd_soc_dapm_pre) { + if (!w->event) + continue; + + if (event == SND_SOC_DAPM_STREAM_START) { + ret = w->event(w, + NULL, SND_SOC_DAPM_PRE_PMU); + if (ret < 0) + return ret; + } else if (event == SND_SOC_DAPM_STREAM_STOP) { + ret = w->event(w, + NULL, SND_SOC_DAPM_PRE_PMD); + if (ret < 0) + return ret; + } + continue; + } + if (w->id == snd_soc_dapm_post) { + if (!w->event) + continue; + + if (event == SND_SOC_DAPM_STREAM_START) { + ret = w->event(w, + NULL, SND_SOC_DAPM_POST_PMU); + if (ret < 0) + return ret; + } else if (event == SND_SOC_DAPM_STREAM_STOP) { + ret = w->event(w, + NULL, SND_SOC_DAPM_POST_PMD); + if (ret < 0) + return ret; + } + continue; + } + + /* all other widgets */ + in = is_connected_input_ep(w); + dapm_clear_walk(w->codec); + out = is_connected_output_ep(w); + dapm_clear_walk(w->codec); + power = (out != 0 && in != 0) ? 1 : 0; + power_change = (w->power == power) ? 0: 1; + w->power = power; + + if (!power_change) + continue; + + /* call any power change event handlers */ + if (w->event) + pr_debug("power %s event for %s flags %x\n", + w->power ? "on" : "off", + w->name, w->event_flags); + + /* power up pre event */ + if (power && w->event && + (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { + ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); + if (ret < 0) + return ret; + } + + /* power down pre event */ + if (!power && w->event && + (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { + ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); + if (ret < 0) + return ret; + } + + /* Lower PGA volume to reduce pops */ + if (w->id == snd_soc_dapm_pga && !power) + dapm_set_pga(w, power); + + dapm_update_bits(w); + + /* Raise PGA volume to reduce pops */ + if (w->id == snd_soc_dapm_pga && power) + dapm_set_pga(w, power); + + /* power up post event */ + if (power && w->event && + (w->event_flags & SND_SOC_DAPM_POST_PMU)) { + ret = w->event(w, + NULL, SND_SOC_DAPM_POST_PMU); + if (ret < 0) + return ret; + } + + /* power down post event */ + if (!power && w->event && + (w->event_flags & SND_SOC_DAPM_POST_PMD)) { + ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); + if (ret < 0) + return ret; + } } } - return 0; + return ret; } #ifdef DEBUG diff --git a/trunk/sound/soc/soc-jack.c b/trunk/sound/soc/soc-jack.c index 28346fb2e70c..ab64a30bedde 100644 --- a/trunk/sound/soc/soc-jack.c +++ b/trunk/sound/soc/soc-jack.c @@ -14,10 +14,6 @@ #include #include #include -#include -#include -#include -#include /** * snd_soc_jack_new - Create a new jack @@ -140,128 +136,3 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, return 0; } EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins); - -#ifdef CONFIG_GPIOLIB -/* gpio detect */ -static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) -{ - struct snd_soc_jack *jack = gpio->jack; - int enable; - int report; - - if (gpio->debounce_time > 0) - mdelay(gpio->debounce_time); - - enable = gpio_get_value(gpio->gpio); - if (gpio->invert) - enable = !enable; - - if (enable) - report = gpio->report; - else - report = 0; - - snd_soc_jack_report(jack, report, gpio->report); -} - -/* irq handler for gpio pin */ -static irqreturn_t gpio_handler(int irq, void *data) -{ - struct snd_soc_jack_gpio *gpio = data; - - schedule_work(&gpio->work); - - return IRQ_HANDLED; -} - -/* gpio work */ -static void gpio_work(struct work_struct *work) -{ - struct snd_soc_jack_gpio *gpio; - - gpio = container_of(work, struct snd_soc_jack_gpio, work); - snd_soc_jack_gpio_detect(gpio); -} - -/** - * snd_soc_jack_add_gpios - Associate GPIO pins with an ASoC jack - * - * @jack: ASoC jack - * @count: number of pins - * @gpios: array of gpio pins - * - * This function will request gpio, set data direction and request irq - * for each gpio in the array. - */ -int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios) -{ - int i, ret; - - for (i = 0; i < count; i++) { - if (!gpio_is_valid(gpios[i].gpio)) { - printk(KERN_ERR "Invalid gpio %d\n", - gpios[i].gpio); - ret = -EINVAL; - goto undo; - } - if (!gpios[i].name) { - printk(KERN_ERR "No name for gpio %d\n", - gpios[i].gpio); - ret = -EINVAL; - goto undo; - } - - ret = gpio_request(gpios[i].gpio, gpios[i].name); - if (ret) - goto undo; - - ret = gpio_direction_input(gpios[i].gpio); - if (ret) - goto err; - - ret = request_irq(gpio_to_irq(gpios[i].gpio), - gpio_handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - jack->card->dev->driver->name, - &gpios[i]); - if (ret) - goto err; - - INIT_WORK(&gpios[i].work, gpio_work); - gpios[i].jack = jack; - } - - return 0; - -err: - gpio_free(gpios[i].gpio); -undo: - snd_soc_jack_free_gpios(jack, i, gpios); - - return ret; -} -EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpios); - -/** - * snd_soc_jack_free_gpios - Release GPIO pins' resources of an ASoC jack - * - * @jack: ASoC jack - * @count: number of pins - * @gpios: array of gpio pins - * - * Release gpio and irq resources for gpio pins associated with an ASoC jack. - */ -void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios) -{ - int i; - - for (i = 0; i < count; i++) { - free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]); - gpio_free(gpios[i].gpio); - gpios[i].jack = NULL; - } -} -EXPORT_SYMBOL_GPL(snd_soc_jack_free_gpios); -#endif /* CONFIG_GPIOLIB */